Add bitset implementation.
diff --git a/lib/src/bitset.dart b/lib/src/bitset.dart
new file mode 100644
index 0000000..4cc567b
--- /dev/null
+++ b/lib/src/bitset.dart
@@ -0,0 +1,102 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// 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 SetBase;
+
+import 'dart:typed_data';
+
+/// Creates an empty set of non-negative integers.
+///
+/// The [maxElements] it must be no larger than [maxSupportedElements].
+/// Then the resulting set can only contain integers which
+/// are non-negative and *less than* [maxElements].
+///
+/// The set is backed directly by as many bits as necessary.
+/// A verly large value for [maxElements] may not be supported by the
+/// underlying system.
+Set<int> bitSet(int maxElements) {
+ RangeError.checkNotNegative(maxElements, "maxElements");
+ return _DenseBitSet(maxElements);
+}
+
+class _DenseBitSet extends SetBase<int> {
+ final int _maxElements;
+ final Uint8List _bits;
+ int _elementCount = 0;
+ _DenseBitSet(this._maxElements) : _bits = Uint8List((_maxElements + 7) ~/ 8);
+
+ // Used by [toSet].
+ _DenseBitSet._(this._maxElements, this._elementCount, this._bits);
+
+ bool add(int value) {
+ RangeError.checkValidIndex(value, this, "value", _maxElements);
+ var mask = 1 << (value & 7);
+ int index = value ~/ 8;
+ int byte = _bits[index];
+ if (byte & mask == 0) {
+ _bits[index] = byte + mask;
+ _elementCount++;
+ return true;
+ }
+ return false;
+ }
+
+ bool contains(Object element) {
+ if (element is int) {
+ if (element < 0 || element >= _maxElements) return false;
+ return _contains(element);
+ }
+ return false;
+ }
+
+ bool _contains(int element) =>
+ _bits[element ~/ 8] & (1 << (element & 7)) != 0;
+
+ Iterable<int> get _elements sync* {
+ int index = 0;
+ for (int i = 0; i < _bits.length; i++) {
+ int byte = _bits[i];
+ if (byte != 0) {
+ for (int j = 0, bit = 1; j < 8; bit += bit, j++) {
+ if (byte & bit != 0) yield index;
+ index++;
+ }
+ } else {
+ index += 8;
+ }
+ }
+ }
+
+ Iterator<int> get iterator => _elements.iterator;
+
+ int get length => _elementCount;
+
+ @override
+ int/*?*/ lookup(Object element) {
+ if (element is int) {
+ if (element < 0 || element >= _maxElements) return null;
+ if (_contains(element)) return element;
+ }
+ return null;
+ }
+
+ @override
+ bool remove(Object value) {
+ if (value is int) {
+ if (value < 0 || value >= _maxElements) return false;
+ var mask = 1 << (value & 7);
+ int index = value ~/ 8;
+ int byte = _bits[index];
+ if (byte & mask == 1) {
+ _bits[index] = byte - mask;
+ _elementCount--;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ Set<int> toSet() =>
+ _DenseBitSet._(_maxElements, _elementCount, Uint8List.fromList(_bits));
+}