// Copyright (c) 2012, 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.

part of dart.collection;

typedef bool _Predicate<T>(T value);

/**
 * A node in a splay tree. It holds the sorting key and the left
 * and right children in the tree.
 */
class _SplayTreeNode<K> {
  final K key;
  _SplayTreeNode<K> left;
  _SplayTreeNode<K> right;

  _SplayTreeNode(K this.key);
}

/**
 * A node in a splay tree based map.
 *
 * A [_SplayTreeNode] that also contains a value
 */
class _SplayTreeMapNode<K, V> extends _SplayTreeNode<K> {
  V value;
  _SplayTreeMapNode(K key, V this.value) : super(key);
}

/**
 * A splay tree is a self-balancing binary search tree.
 *
 * It has the additional property that recently accessed elements
 * are quick to access again.
 * It performs basic operations such as insertion, look-up and
 * removal, in O(log(n)) amortized time.
 */
abstract class _SplayTree<K, Node extends _SplayTreeNode<K>> {
  // The root node of the splay tree. It will contain either the last
  // element inserted or the last element looked up.
  Node get _root;
  set _root(Node newValue);

  // The dummy node used when performing a splay on the tree. Reusing it
  // avoids allocating a node each time a splay is performed.
  Node get _dummy;

  // Number of elements in the splay tree.
  int _count = 0;

  /**
   * Counter incremented whenever the keys in the map changes.
   *
   * Used to detect concurrent modifications.
   */
  int _modificationCount = 0;

  /**
   * Counter incremented whenever the tree structure changes.
   *
   * Used to detect that an in-place traversal cannot use
   * cached information that relies on the tree structure.
   */
  int _splayCount = 0;

  /** The comparator that is used for this splay tree. */
  Comparator<K> get _comparator;

  /** The predicate to determine that a given object is a valid key. */
  _Predicate get _validKey;

  /** Comparison used to compare keys. */
  int _compare(K key1, K key2);

  /**
   * Perform the splay operation for the given key. Moves the node with
   * the given key to the top of the tree.  If no node has the given
   * key, the last node on the search path is moved to the top of the
   * tree. This is the simplified top-down splaying algorithm from:
   * "Self-adjusting Binary Search Trees" by Sleator and Tarjan.
   *
   * Returns the result of comparing the new root of the tree to [key].
   * Returns -1 if the table is empty.
   */
  int _splay(K key) {
    if (_root == null) return -1;

    // The right child of the dummy node will hold
    // the L tree of the algorithm.  The left child of the dummy node
    // will hold the R tree of the algorithm.  Using a dummy node, left
    // and right will always be nodes and we avoid special cases.
    Node left = _dummy;
    Node right = _dummy;
    Node current = _root;
    int comp;
    while (true) {
      comp = _compare(current.key, key);
      if (comp > 0) {
        if (current.left == null) break;
        comp = _compare(current.left.key, key);
        if (comp > 0) {
          // Rotate right.
          _SplayTreeNode<K> tmp = current.left;
          current.left = tmp.right;
          tmp.right = current;
          current = tmp;
          if (current.left == null) break;
        }
        // Link right.
        right.left = current;
        right = current;
        current = current.left;
      } else if (comp < 0) {
        if (current.right == null) break;
        comp = _compare(current.right.key, key);
        if (comp < 0) {
          // Rotate left.
          Node tmp = current.right;
          current.right = tmp.left;
          tmp.left = current;
          current = tmp;
          if (current.right == null) break;
        }
        // Link left.
        left.right = current;
        left = current;
        current = current.right;
      } else {
        break;
      }
    }
    // Assemble.
    left.right = current.left;
    right.left = current.right;
    current.left = _dummy.right;
    current.right = _dummy.left;
    _root = current;

    _dummy.right = null;
    _dummy.left = null;
    _splayCount++;
    return comp;
  }

  // Emulates splaying with a key that is smaller than any in the subtree
  // anchored at [node].
  // and that node is returned. It should replace the reference to [node]
  // in any parent tree or root pointer.
  Node _splayMin(Node node) {
    Node current = node;
    while (current.left != null) {
      Node left = current.left;
      current.left = left.right;
      left.right = current;
      current = left;
    }
    return current;
  }

  // Emulates splaying with a key that is greater than any in the subtree
  // anchored at [node].
  // After this, the largest element in the tree is the root of the subtree,
  // and that node is returned. It should replace the reference to [node]
  // in any parent tree or root pointer.
  Node _splayMax(Node node) {
    Node current = node;
    while (current.right != null) {
      Node right = current.right;
      current.right = right.left;
      right.left = current;
      current = right;
    }
    return current;
  }

  Node _remove(K key) {
    if (_root == null) return null;
    int comp = _splay(key);
    if (comp != 0) return null;
    Node result = _root;
    _count--;
    // assert(_count >= 0);
    if (_root.left == null) {
      _root = _root.right;
    } else {
      Node right = _root.right;
      // Splay to make sure that the new root has an empty right child.
      _root = _splayMax(_root.left);
      // Insert the original right child as the right child of the new
      // root.
      _root.right = right;
    }
    _modificationCount++;
    return result;
  }

  /**
   * Adds a new root node with the given [key] or [value].
   *
   * The [comp] value is the result of comparing the existing root's key
   * with key.
   */
  void _addNewRoot(Node node, int comp) {
    _count++;
    _modificationCount++;
    if (_root == null) {
      _root = node;
      return;
    }
    // assert(_count >= 0);
    if (comp < 0) {
      node.left = _root;
      node.right = _root.right;
      _root.right = null;
    } else {
      node.right = _root;
      node.left = _root.left;
      _root.left = null;
    }
    _root = node;
  }

  Node get _first {
    if (_root == null) return null;
    _root = _splayMin(_root);
    return _root;
  }

  Node get _last {
    if (_root == null) return null;
    _root = _splayMax(_root);
    return _root;
  }

  void _clear() {
    _root = null;
    _count = 0;
    _modificationCount++;
  }
}

class _TypeTest<T> {
  bool test(v) => v is T;
}

/**
 * A [Map] of objects that can be ordered relative to each other.
 *
 * The map is based on a self-balancing binary tree. It allows most operations
 * in amortized logarithmic time.
 *
 * Keys of the map are compared using the `compare` function passed in
 * the constructor, both for ordering and for equality.
 * If the map contains only the key `a`, then `map.containsKey(b)`
 * will return `true` if and only if `compare(a, b) == 0`,
 * and the value of `a == b` is not even checked.
 * If the compare function is omitted, the objects are assumed to be
 * [Comparable], and are compared using their [Comparable.compareTo] method.
 * Non-comparable objects (including `null`) will not work as keys
 * in that case.
 *
 * To allow calling [operator[]], [remove] or [containsKey] with objects
 * that are not supported by the `compare` function, an extra `isValidKey`
 * predicate function can be supplied. This function is tested before
 * using the `compare` function on an argument value that may not be a [K]
 * value. If omitted, the `isValidKey` function defaults to testing if the
 * value is a [K].
 */
class SplayTreeMap<K, V> extends _SplayTree<K, _SplayTreeMapNode<K, V>>
    implements Map<K, V> {
  _SplayTreeMapNode<K, V> _root;
  final _SplayTreeMapNode<K, V> _dummy =
      new _SplayTreeMapNode<K, V>(null, null);

  Comparator<K> _comparator;
  _Predicate _validKey;

  SplayTreeMap([int compare(K key1, K key2), bool isValidKey(potentialKey)])
      : _comparator = compare ?? Comparable.compare as Comparator<K>,
        _validKey = isValidKey ?? ((v) => v is K);

  /**
   * Creates a [SplayTreeMap] that contains all key/value pairs of [other].
   */
  factory SplayTreeMap.from(Map other,
                            [int compare(K key1, K key2),
                             bool isValidKey(potentialKey)]) {
    SplayTreeMap<K, V> result = new SplayTreeMap<K, V>(compare, isValidKey);
    other.forEach((k, v) { result[k as Object/*=K*/] = v as Object/*=V*/; });
    return result;
  }

  /**
   * Creates a [SplayTreeMap] where the keys and values are computed from the
   * [iterable].
   *
   * For each element of the [iterable] this constructor computes a key/value
   * pair, by applying [key] and [value] respectively.
   *
   * The keys of the key/value pairs do not need to be unique. The last
   * occurrence of a key will simply overwrite any previous value.
   *
   * If no functions are specified for [key] and [value] the default is to
   * use the iterable value itself.
   */
  factory SplayTreeMap.fromIterable(Iterable iterable,
                                    {K key(element),
                                     V value(element),
                                     int compare(K key1, K key2),
                                     bool isValidKey(potentialKey) }) {
    SplayTreeMap<K, V> map = new SplayTreeMap<K, V>(compare, isValidKey);
    Maps._fillMapWithMappedIterable(map, iterable, key, value);
    return map;
  }

  /**
   * Creates a [SplayTreeMap] associating the given [keys] to [values].
   *
   * This constructor iterates over [keys] and [values] and maps each element of
   * [keys] to the corresponding element of [values].
   *
   * If [keys] contains the same object multiple times, the last occurrence
   * overwrites the previous value.
   *
   * It is an error if the two [Iterable]s don't have the same length.
   */
  factory SplayTreeMap.fromIterables(Iterable<K> keys, Iterable<V> values,
      [int compare(K key1, K key2), bool isValidKey(potentialKey)]) {
    SplayTreeMap<K, V> map = new SplayTreeMap<K, V>(compare, isValidKey);
    Maps._fillMapWithIterables(map, keys, values);
    return map;
  }

  int _compare(K key1, K key2) => _comparator(key1, key2);

  SplayTreeMap._internal();

  V operator [](Object key) {
    if (!_validKey(key)) return null;
    if (_root != null) {
      int comp = _splay(key as dynamic/*=K*/);
      if (comp == 0) {
        return _root.value;
      }
    }
    return null;
  }

  V remove(Object key) {
    if (!_validKey(key)) return null;
    _SplayTreeMapNode<K, V> mapRoot = _remove(key as dynamic/*=K*/);
    if (mapRoot != null) return mapRoot.value;
    return null;
  }

  void operator []=(K key, V value) {
    if (key == null) throw new ArgumentError(key);
    // Splay on the key to move the last node on the search path for
    // the key to the root of the tree.
    int comp = _splay(key);
    if (comp == 0) {
      _root.value = value;
      return;
    }
    _addNewRoot(new _SplayTreeMapNode(key, value), comp);
  }


  V putIfAbsent(K key, V ifAbsent()) {
    if (key == null) throw new ArgumentError(key);
    int comp = _splay(key);
    if (comp == 0) {
      return _root.value;
    }
    int modificationCount = _modificationCount;
    int splayCount = _splayCount;
    V value = ifAbsent();
    if (modificationCount != _modificationCount) {
      throw new ConcurrentModificationError(this);
    }
    if (splayCount != _splayCount) {
      comp = _splay(key);
      // Key is still not there, otherwise _modificationCount would be changed.
      assert(comp != 0);
    }
    _addNewRoot(new _SplayTreeMapNode(key, value), comp);
    return value;
  }

  void addAll(Map<K, V> other) {
    other.forEach((K key, V value) { this[key] = value; });
  }

  bool get isEmpty {
    return (_root == null);
  }

  bool get isNotEmpty => !isEmpty;

  void forEach(void f(K key, V value)) {
    Iterator<_SplayTreeNode<K>> nodes =
        new _SplayTreeNodeIterator<K>(this);
    while (nodes.moveNext()) {
      _SplayTreeMapNode<K, V> node = nodes.current;
      f(node.key, node.value);
    }
  }

  int get length {
    return _count;
  }

  void clear() {
    _clear();
  }

  bool containsKey(Object key) {
    return _validKey(key) && _splay(key as dynamic/*=K*/) == 0;
  }

  bool containsValue(Object value) {
    bool found = false;
    int initialSplayCount = _splayCount;
    bool visit(_SplayTreeMapNode node) {
      while (node != null) {
        if (node.value == value) return true;
        if (initialSplayCount != _splayCount) {
          throw new ConcurrentModificationError(this);
        }
        if (node.right != null && visit(node.right)) return true;
        node = node.left;
      }
      return false;
    }
    return visit(_root);
  }

  Iterable<K> get keys => new _SplayTreeKeyIterable<K>(this);

  Iterable<V> get values => new _SplayTreeValueIterable<K, V>(this);

  String toString() {
    return Maps.mapToString(this);
  }

  /**
   * Get the first key in the map. Returns [:null:] if the map is empty.
   */
  K firstKey() {
    if (_root == null) return null;
    return _first.key;
  }

  /**
   * Get the last key in the map. Returns [:null:] if the map is empty.
   */
  K lastKey() {
    if (_root == null) return null;
    return _last.key;
  }

  /**
   * Get the last key in the map that is strictly smaller than [key]. Returns
   * [:null:] if no key was not found.
   */
  K lastKeyBefore(K key) {
    if (key == null) throw new ArgumentError(key);
    if (_root == null) return null;
    int comp = _splay(key);
    if (comp < 0) return _root.key;
    _SplayTreeNode<K> node = _root.left;
    if (node == null) return null;
    while (node.right != null) {
      node = node.right;
    }
    return node.key;
  }

  /**
   * Get the first key in the map that is strictly larger than [key]. Returns
   * [:null:] if no key was not found.
   */
  K firstKeyAfter(K key) {
    if (key == null) throw new ArgumentError(key);
    if (_root == null) return null;
    int comp = _splay(key);
    if (comp > 0) return _root.key;
    _SplayTreeNode<K> node = _root.right;
    if (node == null) return null;
    while (node.left != null) {
      node = node.left;
    }
    return node.key;
  }
}

abstract class _SplayTreeIterator<K, T> implements Iterator<T> {
  final _SplayTree<K, _SplayTreeNode<K>> _tree;
  /**
   * Worklist of nodes to visit.
   *
   * These nodes have been passed over on the way down in a
   * depth-first left-to-right traversal. Visiting each node,
   * and their right subtrees will visit the remainder of
   * the nodes of a full traversal.
   *
   * Only valid as long as the original tree isn't reordered.
   */
  final List<_SplayTreeNode<K>> _workList = <_SplayTreeNode<K>>[];

  /**
   * Original modification counter of [_tree].
   *
   * Incremented on [_tree] when a key is added or removed.
   * If it changes, iteration is aborted.
   *
   * Not final because some iterators may modify the tree knowingly,
   * and they update the modification count in that case.
   */
  int _modificationCount;

  /**
   * Count of splay operations on [_tree] when [_workList] was built.
   *
   * If the splay count on [_tree] increases, [_workList] becomes invalid.
   */
  int _splayCount;

  /** Current node. */
  _SplayTreeNode<K> _currentNode;

  _SplayTreeIterator(_SplayTree<K, _SplayTreeNode<K>> tree)
      : _tree = tree,
        _modificationCount = tree._modificationCount,
        _splayCount = tree._splayCount {
    _findLeftMostDescendent(tree._root);
  }

  _SplayTreeIterator.startAt(_SplayTree<K, _SplayTreeNode<K>> tree, K startKey)
      : _tree = tree,
        _modificationCount = tree._modificationCount {
    if (tree._root == null) return;
    int compare = tree._splay(startKey);
    _splayCount = tree._splayCount;
    if (compare < 0) {
      // Don't include the root, start at the next element after the root.
      _findLeftMostDescendent(tree._root.right);
    } else {
      _workList.add(tree._root);
    }
  }

  T get current {
    if (_currentNode == null) return null;
    return _getValue(_currentNode);
  }

  void _findLeftMostDescendent(_SplayTreeNode<K> node) {
    while (node != null) {
      _workList.add(node);
      node = node.left;
    }
  }

  /**
   * Called when the tree structure of the tree has changed.
   *
   * This can be caused by a splay operation.
   * If the key-set changes, iteration is aborted before getting
   * here, so we know that the keys are the same as before, it's
   * only the tree that has been reordered.
   */
  void _rebuildWorkList(_SplayTreeNode<K> currentNode) {
    assert(!_workList.isEmpty);
    _workList.clear();
    if (currentNode == null) {
      _findLeftMostDescendent(_tree._root);
    } else {
      _tree._splay(currentNode.key);
      _findLeftMostDescendent(_tree._root.right);
      assert(!_workList.isEmpty);
    }
  }

  bool moveNext() {
    if (_modificationCount != _tree._modificationCount) {
      throw new ConcurrentModificationError(_tree);
    }
    // Picks the next element in the worklist as current.
    // Updates the worklist with the left-most path of the current node's
    // right-hand child.
    // If the worklist is no longer valid (after a splay), it is rebuild
    // from scratch.
    if (_workList.isEmpty) {
      _currentNode = null;
      return false;
    }
    if (_tree._splayCount != _splayCount && _currentNode != null) {
      _rebuildWorkList(_currentNode);
    }
    _currentNode = _workList.removeLast();
    _findLeftMostDescendent(_currentNode.right);
    return true;
  }

  T _getValue(_SplayTreeNode<K> node);
}

class _SplayTreeKeyIterable<K> extends Iterable<K>
                               implements EfficientLength {
  _SplayTree<K, _SplayTreeNode<K>> _tree;
  _SplayTreeKeyIterable(this._tree);
  int get length => _tree._count;
  bool get isEmpty => _tree._count == 0;
  Iterator<K> get iterator => new _SplayTreeKeyIterator<K>(_tree);

  Set<K> toSet() {
    SplayTreeSet<K> set =
        new SplayTreeSet<K>(_tree._comparator, _tree._validKey);
    set._count = _tree._count;
    set._root = set._copyNode(_tree._root);
    return set;
  }
}

class _SplayTreeValueIterable<K, V> extends Iterable<V>
                                    implements EfficientLength {
  SplayTreeMap<K, V> _map;
  _SplayTreeValueIterable(this._map);
  int get length => _map._count;
  bool get isEmpty => _map._count == 0;
  Iterator<V> get iterator => new _SplayTreeValueIterator<K, V>(_map);
}

class _SplayTreeKeyIterator<K> extends _SplayTreeIterator<K, K> {
  _SplayTreeKeyIterator(_SplayTree<K, _SplayTreeNode<K>> map): super(map);
  K _getValue(_SplayTreeNode<K> node) => node.key;
}

class _SplayTreeValueIterator<K, V> extends _SplayTreeIterator<K, V> {
  _SplayTreeValueIterator(SplayTreeMap<K, V> map): super(map);
  V _getValue(_SplayTreeNode<K> node) {
    _SplayTreeMapNode<K, V> mapNode =
        node as dynamic/*=_SplayTreeMapNode<K, V>*/;
    return mapNode.value;
  }
}

class _SplayTreeNodeIterator<K>
    extends _SplayTreeIterator<K, _SplayTreeNode<K>> {
  _SplayTreeNodeIterator(_SplayTree<K, _SplayTreeNode<K>> tree): super(tree);
  _SplayTreeNodeIterator.startAt(
      _SplayTree<K, _SplayTreeNode<K>> tree, K startKey)
      : super.startAt(tree, startKey);
  _SplayTreeNode<K> _getValue(_SplayTreeNode<K> node) => node;
}


/**
 * A [Set] of objects that can be ordered relative to each other.
 *
 * The set is based on a self-balancing binary tree. It allows most operations
 * in amortized logarithmic time.
 *
 * Elements of the set are compared using the `compare` function passed in
 * the constructor, both for ordering and for equality.
 * If the set contains only an object `a`, then `set.contains(b)`
 * will return `true` if and only if `compare(a, b) == 0`,
 * and the value of `a == b` is not even checked.
 * If the compare function is omitted, the objects are assumed to be
 * [Comparable], and are compared using their [Comparable.compareTo] method.
 * Non-comparable objects (including `null`) will not work as an element
 * in that case.
 */
class SplayTreeSet<E> extends _SplayTree<E, _SplayTreeNode<E>>
    with IterableMixin<E>, SetMixin<E> {
  _SplayTreeNode<E> _root;
  final _SplayTreeNode<E> _dummy = new _SplayTreeNode<E>(null);

  Comparator<E> _comparator;
  _Predicate _validKey;

  /**
   * Create a new [SplayTreeSet] with the given compare function.
   *
   * If the [compare] function is omitted, it defaults to [Comparable.compare],
   * and the elements must be comparable.
   *
   * A provided `compare` function may not work on all objects. It may not even
   * work on all `E` instances.
   *
   * For operations that add elements to the set, the user is supposed to not
   * pass in objects that doesn't work with the compare function.
   *
   * The methods [contains], [remove], [lookup], [removeAll] or [retainAll]
   * are typed to accept any object(s), and the [isValidKey] test can used to
   * filter those objects before handing them to the `compare` function.
   *
   * If [isValidKey] is provided, only values satisfying `isValidKey(other)`
   * are compared using the `compare` method in the methods mentioned above.
   * If the `isValidKey` function returns false for an object, it is assumed to
   * not be in the set.
   *
   * If omitted, the `isValidKey` function defaults to checking against the
   * type parameter: `other is E`.
   */
  SplayTreeSet([int compare(E key1, E key2), bool isValidKey(potentialKey)])
      : _comparator =
            compare ?? Comparable.compare as dynamic/*=Comparator<E>*/,
        _validKey = isValidKey ?? ((v) => v is E);

  /**
   * Creates a [SplayTreeSet] that contains all [elements].
   *
   * The set works as if created by `new SplayTreeSet<E>(compare, isValidKey)`.
   *
   * All the [elements] should be valid as arguments to the [compare] function.
   */
  factory SplayTreeSet.from(Iterable elements,
                            [int compare(E key1, E key2),
                             bool isValidKey(potentialKey)]) {
    SplayTreeSet<E> result = new SplayTreeSet<E>(compare, isValidKey);
    for (final element in elements) {
      E e = element as Object/*=E*/;
      result.add(e);
    }
    return result;
  }

  int _compare(E e1, E e2) => _comparator(e1, e2);

  // From Iterable.

  Iterator<E> get iterator => new _SplayTreeKeyIterator<E>(this);

  int get length => _count;
  bool get isEmpty => _root == null;
  bool get isNotEmpty => _root != null;

  E get first {
    if (_count == 0) throw IterableElementError.noElement();
    return _first.key;
  }

  E get last {
    if (_count == 0) throw IterableElementError.noElement();
    return _last.key;
  }

  E get single {
    if (_count == 0) throw IterableElementError.noElement();
    if (_count > 1) throw IterableElementError.tooMany();
    return _root.key;
  }

  // From Set.
  bool contains(Object object) {
    return _validKey(object) && _splay(object as dynamic/*=E*/) == 0;
  }

  bool add(E element) {
    int compare = _splay(element);
    if (compare == 0) return false;
    _addNewRoot(new _SplayTreeNode(element), compare);
    return true;
  }

  bool remove(Object object) {
    if (!_validKey(object)) return false;
    return _remove(object as dynamic/*=E*/) != null;
  }

  void addAll(Iterable<E> elements) {
    for (E element in elements) {
      int compare = _splay(element);
      if (compare != 0) {
        _addNewRoot(new _SplayTreeNode(element), compare);
      }
    }
  }

  void removeAll(Iterable<Object> elements) {
    for (Object element in elements) {
      if (_validKey(element)) _remove(element as dynamic/*=E*/);
    }
  }

  void retainAll(Iterable<Object> elements) {
    // Build a set with the same sense of equality as this set.
    SplayTreeSet<E> retainSet = new SplayTreeSet<E>(_comparator, _validKey);
    int modificationCount = _modificationCount;
    for (Object object in elements) {
      if (modificationCount != _modificationCount) {
        // The iterator should not have side effects.
        throw new ConcurrentModificationError(this);
      }
      // Equivalent to this.contains(object).
      if (_validKey(object) && _splay(object as dynamic/*=E*/) == 0) {
        retainSet.add(_root.key);
      }
    }
    // Take over the elements from the retained set, if it differs.
    if (retainSet._count != _count) {
      _root = retainSet._root;
      _count = retainSet._count;
      _modificationCount++;
    }
  }

  E lookup(Object object) {
    if (!_validKey(object)) return null;
    int comp = _splay(object as dynamic/*=E*/);
    if (comp != 0) return null;
    return _root.key;
  }

  Set<E> intersection(Set<Object> other) {
    Set<E> result = new SplayTreeSet<E>(_comparator, _validKey);
    for (E element in this) {
      if (other.contains(element)) result.add(element);
    }
    return result;
  }

  Set<E> difference(Set<Object> other) {
    Set<E> result = new SplayTreeSet<E>(_comparator, _validKey);
    for (E element in this) {
      if (!other.contains(element)) result.add(element);
    }
    return result;
  }

  Set<E> union(Set<E> other) {
    return _clone()..addAll(other);
  }

  SplayTreeSet<E> _clone() {
    var set = new SplayTreeSet<E>(_comparator, _validKey);
    set._count = _count;
    set._root = _copyNode(_root);
    return set;
  }

  // Copies the structure of a SplayTree into a new similar structure.
  // Works on _SplayTreeMapNode as well, but only copies the keys,
  _SplayTreeNode<E> _copyNode(_SplayTreeNode<E> node) {
    if (node == null) return null;
    return new _SplayTreeNode<E>(node.key)..left = _copyNode(node.left)
                                          ..right = _copyNode(node.right);
  }

  void clear() { _clear(); }

  Set<E> toSet() => _clone();

  String toString() => IterableBase.iterableToFullString(this, '{', '}');
}
