Hide UTF-16 assumptions in the API. (#13)

* Avoid the API depending on the underlying data being random-access UTF-16 code units.

In this case, don't return `codeUnits` as a list of integers, but explicitly say `utf16CodeUnits` and return them as an iterable. That can be implemented as efficiently as possible on, say, a UTF-8 byte array.

* Also use .characters in rest of example.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2346cf1..1904b5e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,12 @@
 # Changelog
 
+## 0.5.0
+
+* Change [codeUnits] getter to [utf16CodeUnits] which returns an iterable.
+  This avoids leaking that the underlying string has efficient UTF-16
+  code unit access in the API, and allows the same interface to be
+  just as efficiently implemented on top of UTF-8.
+
 ## 0.4.0
 
 * Added an extension method on `String` to allow easy access to the `Characters`
@@ -22,4 +29,4 @@
 
 ## 0.1.0
 
-* Initial release
\ No newline at end of file
+* Initial release
diff --git a/example/main.dart b/example/main.dart
index b01e334..4e6316b 100644
--- a/example/main.dart
+++ b/example/main.dart
@@ -20,6 +20,6 @@
 
   // Replace characters.
   Characters newHi =
-      Characters(hi).replaceAll(Characters('πŸ‡©πŸ‡°'), Characters('πŸ‡ΊπŸ‡Έ'));
+      hi.characters.replaceAll('πŸ‡©πŸ‡°'.characters, 'πŸ‡ΊπŸ‡Έ'.characters);
   print('Change flag: "$newHi"');
 }
diff --git a/lib/src/characters.dart b/lib/src/characters.dart
index eec3ca8..17a45fe 100644
--- a/lib/src/characters.dart
+++ b/lib/src/characters.dart
@@ -250,7 +250,7 @@
   Characters get source;
 
   /// The code units of the current character range.
-  List<int> get codeUnits;
+  Iterable<int> get utf16CodeUnits;
 
   /// The code points of the current character range.
   Runes get runes;
diff --git a/lib/src/characters_impl.dart b/lib/src/characters_impl.dart
index 85d615c..e3dc6ac 100644
--- a/lib/src/characters_impl.dart
+++ b/lib/src/characters_impl.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import "dart:collection" show ListBase;
-
 import 'package:characters/src/grapheme_clusters/table.dart';
 
 import "characters.dart";
@@ -488,7 +486,7 @@
   }
 
   @override
-  List<int> get codeUnits => _CodeUnits(_string, _start, _end);
+  Iterable<int> get utf16CodeUnits => _string.codeUnits.getRange(_start, _end);
 
   @override
   Runes get runes => Runes(current);
@@ -900,30 +898,6 @@
   String get stringBefore => _string.substring(0, _start);
 }
 
-class _CodeUnits extends ListBase<int> {
-  final String _string;
-  final int _start;
-  final int _end;
-
-  _CodeUnits(this._string, this._start, this._end);
-
-  int get length => _end - _start;
-
-  int operator [](int index) {
-    RangeError.checkValidIndex(index, this, "index", _end - _start);
-    return _string.codeUnitAt(_start + index);
-  }
-
-  void operator []=(int index, int value) {
-    throw UnsupportedError("Cannot modify an unmodifiable list");
-  }
-
-  @override
-  set length(int newLength) {
-    throw UnsupportedError("Cannot modify an unmodifiable list");
-  }
-}
-
 String _explodeReplace(String string, int start, int end,
     String internalReplacement, String outerReplacement) {
   if (start == end) {
diff --git a/pubspec.yaml b/pubspec.yaml
index f12c032..5750ec9 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: characters
-version: 0.4.0
+version: 0.5.0
 description: String replacement with operations that are Unicode/grapheme cluster aware.
 homepage: https://www.github.com/dart-lang/characters