diff --git a/dart/lib/src/reference.dart b/dart/lib/src/reference.dart
new file mode 100644
index 0000000..3954f06
--- /dev/null
+++ b/dart/lib/src/reference.dart
@@ -0,0 +1,446 @@
+import 'dart:collection';
+import 'dart:convert';
+import 'dart:typed_data';
+import 'types.dart';
+
+/// Main class to read a value out of a FlexBuffer.
+///
+/// This class let you access values stored in the buffer in a lazy fashion.
+class Reference {
+  final ByteData _buffer;
+  final int _offset;
+  final BitWidth _parentWidth;
+  final String _path;
+  int _byteWidth;
+  ValueType _valueType;
+  int _length;
+
+  Reference._(this._buffer, this._offset, this._parentWidth, int packedType, this._path) {
+    _byteWidth = 1 << (packedType & 3);
+    _valueType = ValueTypeUtils.fromInt(packedType >> 2);
+  }
+
+  /// Use this method to access the root value of a FlexBuffer.
+  static Reference fromBuffer(ByteBuffer buffer) {
+    final len = buffer.lengthInBytes;
+    if (len < 3) {
+      throw UnsupportedError('Buffer needs to be bigger than 3');
+    }
+    final byteData = ByteData.view(buffer);
+    final byteWidth = byteData.getUint8(len - 1);
+    final packedType = byteData.getUint8(len - 2);
+    final offset = len - byteWidth - 2;
+    return Reference._(ByteData.view(buffer), offset, BitWidthUtil.fromByteWidth(byteWidth), packedType, "/");
+  }
+
+  /// Returns true if the underlying value is null.
+  bool get isNull => _valueType == ValueType.Null;
+  /// Returns true if the underlying value can be represented as [num].
+  bool get isNum => ValueTypeUtils.isNumber(_valueType) || ValueTypeUtils.isIndirectNumber(_valueType);
+  /// Returns true if the underlying value was encoded as a float (direct or indirect).
+  bool get isDouble => _valueType == ValueType.Float || _valueType == ValueType.IndirectFloat;
+  /// Returns true if the underlying value was encoded as an int or uint (direct or indirect).
+  bool get isInt => isNum && !isDouble;
+  /// Returns true if the underlying value was encoded as a string or a key.
+  bool get isString => _valueType == ValueType.String || _valueType == ValueType.Key;
+  /// Returns true if the underlying value was encoded as a bool.
+  bool get isBool => _valueType == ValueType.Bool;
+  /// Returns true if the underlying value was encoded as a blob.
+  bool get isBlob => _valueType == ValueType.Blob;
+  /// Returns true if the underlying value points to a vector.
+  bool get isVector => ValueTypeUtils.isAVector(_valueType);
+  /// Returns true if the underlying value points to a map.
+  bool get isMap => _valueType == ValueType.Map;
+
+  /// If this [isBool], returns the bool value. Otherwise, returns null.
+  bool get boolValue {
+    if(_valueType == ValueType.Bool) {
+      return _readInt(_offset, _parentWidth) != 0;
+    }
+    return null;
+  }
+
+  /// Returns an [int], if the underlying value can be represented as an int.
+  ///
+  /// Otherwise returns [null].
+  int get intValue {
+    if (_valueType == ValueType.Int) {
+      return _readInt(_offset, _parentWidth);
+    }
+    if (_valueType == ValueType.UInt) {
+      return _readUInt(_offset, _parentWidth);
+    }
+    if (_valueType == ValueType.IndirectInt) {
+      return _readInt(_indirect, BitWidthUtil.fromByteWidth(_byteWidth));
+    }
+    if (_valueType == ValueType.IndirectUInt) {
+      return _readUInt(_indirect, BitWidthUtil.fromByteWidth(_byteWidth));
+    }
+    return null;
+  }
+
+  /// Returns [double], if the underlying value [isDouble].
+  ///
+  /// Otherwise returns [null].
+  double get doubleValue {
+    if (_valueType == ValueType.Float) {
+      return _readFloat(_offset, _parentWidth);
+    }
+    if (_valueType == ValueType.IndirectFloat) {
+      return _readFloat(_indirect, BitWidthUtil.fromByteWidth(_byteWidth));
+    }
+    return null;
+  }
+
+  /// Returns [num], if the underlying value is numeric, be it int uint, or float (direct or indirect).
+  ///
+  /// Otherwise returns [null].
+  num get numValue => doubleValue ?? intValue;
+
+  /// Returns [String] value or null otherwise.
+  /// 
+  /// This method performers a utf8 decoding, as FlexBuffers format stores strings in utf8 encoding. 
+  String get stringValue {
+    if (_valueType == ValueType.String || _valueType == ValueType.Key) {
+      return utf8.decode(_buffer.buffer.asUint8List(_indirect, length));
+    }
+    return null;
+  }
+
+  /// Returns [Uint8List] value or null otherwise.
+  Uint8List get blobValue {
+    if (_valueType == ValueType.Blob) {
+      return _buffer.buffer.asUint8List(_indirect, length);
+    }
+    return null;
+  }
+
+  /// Can be used with an [int] or a [String] value for key.
+  /// If the underlying value in FlexBuffer is a vector, then use [int] for access.
+  /// If the underlying value in FlexBuffer is a map, then use [String] for access.
+  /// Returns [Reference] value. Throws an exception when [key] is not applicable.
+  Reference operator [](Object key) {
+    if (key is int && ValueTypeUtils.isAVector(_valueType)) {
+      final index = key;
+      if(index >= length || index < 0) {
+        throw ArgumentError('Key: [$key] is not applicable on: $_path of: $_valueType length: $length');
+      }
+      final elementOffset = _indirect + index * _byteWidth;
+      final reference = Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), 0, "$_path[$index]");
+      reference._byteWidth = 1;
+      if (ValueTypeUtils.isTypedVector(_valueType)) {
+        reference._valueType = ValueTypeUtils.typedVectorElementType(_valueType);
+        return reference;
+      }
+      if(ValueTypeUtils.isFixedTypedVector(_valueType)) {
+        reference._valueType = ValueTypeUtils.fixedTypedVectorElementType(_valueType);
+        return reference;
+      }
+      final packedType = _buffer.getUint8(_indirect + length * _byteWidth + index);
+      return Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path[$index]");
+    }
+    if (key is String && _valueType == ValueType.Map) {
+      final index = _keyIndex(key);
+      if (index != null) {
+        return _valueForIndexWithKey(index, key);
+      }
+    }
+    throw ArgumentError('Key: [$key] is not applicable on: $_path of: $_valueType');
+  }
+
+  /// Get an iterable if the underlying flexBuffer value is a vector.
+  /// Otherwise throws an exception.
+  Iterable<Reference> get vectorIterable {
+    if(isVector == false) {
+      throw UnsupportedError('Value is not a vector. It is: $_valueType');
+    }
+    return _VectorIterator(this);
+  }
+
+  /// Get an iterable for keys if the underlying flexBuffer value is a map.
+  /// Otherwise throws an exception.
+  Iterable<String> get mapKeyIterable {
+    if(isMap == false) {
+      throw UnsupportedError('Value is not a map. It is: $_valueType');
+    }
+    return _MapKeyIterator(this);
+  }
+
+  /// Get an iterable for values if the underlying flexBuffer value is a map.
+  /// Otherwise throws an exception.
+  Iterable<Reference> get mapValueIterable {
+    if(isMap == false) {
+      throw UnsupportedError('Value is not a map. It is: $_valueType');
+    }
+    return _MapValueIterator(this);
+  }
+
+  /// Returns the length of the the underlying FlexBuffer value.
+  /// If the underlying value is [null] the length is 0.
+  /// If the underlying value is a number, or a bool, the length is 1.
+  /// If the underlying value is a vector, or map, the length reflects number of elements / element pairs.
+  /// If the values is a string or a blob, the length reflects a number of bytes the value occupies (strings are encoded in utf8 format).
+  int get length {
+    if (_length != null) {
+      return _length;
+    }
+    // needs to be checked before more generic isAVector
+    if(ValueTypeUtils.isFixedTypedVector(_valueType)) {
+      _length = ValueTypeUtils.fixedTypedVectorElementSize(_valueType);
+    } else if(_valueType == ValueType.Blob || ValueTypeUtils.isAVector(_valueType) || _valueType == ValueType.Map){
+      _length = _readUInt(_indirect - _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
+    } else if (_valueType == ValueType.Null) {
+      _length = 0;
+    } else if (_valueType == ValueType.String) {
+      final indirect = _indirect;
+      var size_byte_width = _byteWidth;
+      var size = _readUInt(indirect - size_byte_width, BitWidthUtil.fromByteWidth(size_byte_width));
+      while (_buffer.getInt8(indirect + size) != 0) {
+        size_byte_width <<= 1;
+        size = _readUInt(indirect - size_byte_width, BitWidthUtil.fromByteWidth(size_byte_width));
+      }
+      _length = size;
+    } else if (_valueType == ValueType.Key) {
+      final indirect = _indirect;
+      var size = 1;
+      while (_buffer.getInt8(indirect + size) != 0) {
+        size += 1;
+      }
+      _length = size;
+    } else {
+      _length = 1;
+    }
+    return _length;
+  }
+
+
+  /// Returns a minified JSON representation of the underlying FlexBuffer value.
+  ///
+  /// This method involves materializing the entire object tree, which may be
+  /// expensive. It is more efficient to work with [Reference] and access only the needed data.
+  /// Blob values are represented as base64 encoded string.
+  String get json {
+    if(_valueType == ValueType.Bool) {
+      return boolValue ? 'true' : 'false';
+    }
+    if (_valueType == ValueType.Null) {
+      return 'null';
+    }
+    if(ValueTypeUtils.isNumber(_valueType)) {
+      return jsonEncode(numValue);
+    }
+    if (_valueType == ValueType.String) {
+      return jsonEncode(stringValue);
+    }
+    if (_valueType == ValueType.Blob) {
+      return jsonEncode(base64Encode(blobValue));
+    }
+    if (ValueTypeUtils.isAVector(_valueType)) {
+      final result = StringBuffer();
+      result.write('[');
+      for (var i = 0; i < length; i++) {
+        result.write(this[i].json);
+        if (i < length - 1) {
+          result.write(',');
+        }
+      }
+      result.write(']');
+      return result.toString();
+    }
+    if (_valueType == ValueType.Map) {
+      final result = StringBuffer();
+      result.write('{');
+      for (var i = 0; i < length; i++) {
+        result.write(jsonEncode(_keyForIndex(i)));
+        result.write(':');
+        result.write(_valueForIndex(i).json);
+        if (i < length - 1) {
+          result.write(',');
+        }
+      }
+      result.write('}');
+      return result.toString();
+    }
+    throw UnsupportedError('Type: $_valueType is not supported for JSON conversion');
+  }
+
+  /// Computes the indirect offset of the value.
+  ///
+  /// To optimize for the more common case of being called only once, this
+  /// value is not cached. Callers that need to use it more than once should
+  /// cache the return value in a local variable.
+  int get _indirect {
+    final step = _readUInt(_offset, _parentWidth);
+    return _offset - step;
+  }
+
+  int _readInt(int offset, BitWidth width) {
+    _validateOffset(offset, width);
+    if (width == BitWidth.width8) {
+      return _buffer.getInt8(offset);
+    }
+    if (width == BitWidth.width16) {
+      return _buffer.getInt16(offset, Endian.little);
+    }
+    if (width == BitWidth.width32) {
+      return _buffer.getInt32(offset, Endian.little);
+    }
+    return _buffer.getInt64(offset, Endian.little);
+  }
+
+  int _readUInt(int offset, BitWidth width) {
+    _validateOffset(offset, width);
+    if (width == BitWidth.width8) {
+      return _buffer.getUint8(offset);
+    }
+    if (width == BitWidth.width16) {
+      return _buffer.getUint16(offset, Endian.little);
+    }
+    if (width == BitWidth.width32) {
+      return _buffer.getUint32(offset, Endian.little);
+    }
+    return _buffer.getUint64(offset, Endian.little);
+  }
+
+  double _readFloat(int offset, BitWidth width) {
+    _validateOffset(offset, width);
+    if (width.index < BitWidth.width32.index) {
+      throw StateError('Bad width: $width');
+    }
+
+    if (width == BitWidth.width32) {
+      return _buffer.getFloat32(offset, Endian.little);
+    }
+
+    return _buffer.getFloat64(offset, Endian.little);
+  }
+
+  void _validateOffset(int offset, BitWidth width) {
+    if (_offset < 0 || _buffer.lengthInBytes <= offset + width.index || offset & (BitWidthUtil.toByteWidth(width) - 1) != 0) {
+      throw StateError('Bad offset: $offset, width: $width');
+    }
+  }
+
+  int _keyIndex(String key) {
+    final input = utf8.encode(key);
+    final keysVectorOffset = _indirect - _byteWidth * 3;
+    final indirectOffset = keysVectorOffset - _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth));
+    final byteWidth = _readUInt(keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
+    var low = 0;
+    var high = length - 1;
+    while (low <= high) {
+      final mid = (high + low) >> 1;
+      final dif = _diffKeys(input, mid, indirectOffset, byteWidth);
+      if (dif == 0) return mid;
+      if (dif < 0) {
+        high = mid - 1;
+      } else {
+        low = mid + 1;
+      }
+    }
+    return null;
+  }
+
+  int _diffKeys(List<int> input, int index, int indirect_offset, int byteWidth) {
+    final keyOffset = indirect_offset + index * byteWidth;
+    final keyIndirectOffset = keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth));
+    for (var i = 0; i < input.length; i++) {
+      final dif = input[i] - _buffer.getUint8(keyIndirectOffset + i);
+      if (dif != 0) {
+        return dif;
+      }
+    }
+    return (_buffer.getUint8(keyIndirectOffset + input.length) == 0) ? 0 : -1;
+  }
+
+  Reference _valueForIndexWithKey(int index, String key) {
+    final indirect = _indirect;
+    final elementOffset = indirect + index * _byteWidth;
+    final packedType = _buffer.getUint8(indirect + length * _byteWidth + index);
+    return Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/$key");
+  }
+
+  Reference _valueForIndex(int index) {
+    final indirect = _indirect;
+    final elementOffset = indirect + index * _byteWidth;
+    final packedType = _buffer.getUint8(indirect + length * _byteWidth + index);
+    return Reference._(_buffer, elementOffset, BitWidthUtil.fromByteWidth(_byteWidth), packedType, "$_path/[$index]");
+  }
+
+  String _keyForIndex(int index) {
+    final keysVectorOffset = _indirect - _byteWidth * 3;
+    final indirectOffset = keysVectorOffset - _readUInt(keysVectorOffset, BitWidthUtil.fromByteWidth(_byteWidth));
+    final byteWidth = _readUInt(keysVectorOffset + _byteWidth, BitWidthUtil.fromByteWidth(_byteWidth));
+    final keyOffset = indirectOffset + index * byteWidth;
+    final keyIndirectOffset = keyOffset - _readUInt(keyOffset, BitWidthUtil.fromByteWidth(byteWidth));
+    var length = 0;
+    while (_buffer.getUint8(keyIndirectOffset + length) != 0) {
+      length += 1;
+    }
+    return utf8.decode(_buffer.buffer.asUint8List(keyIndirectOffset, length));
+  }
+
+}
+
+class _VectorIterator with IterableMixin<Reference> implements Iterator<Reference> {
+  final Reference _vector;
+  int index;
+
+  _VectorIterator(this._vector) {
+    index = -1;
+  }
+
+  @override
+  Reference get current => _vector[index];
+
+  @override
+  bool moveNext() {
+    index++;
+    return index < _vector.length;
+  }
+
+  @override
+  Iterator<Reference> get iterator => this;
+}
+
+class _MapKeyIterator with IterableMixin<String> implements Iterator<String> {
+  final Reference _map;
+  int index;
+
+  _MapKeyIterator(this._map) {
+    index = -1;
+  }
+
+  @override
+  String get current => _map._keyForIndex(index);
+
+  @override
+  bool moveNext() {
+    index++;
+    return index < _map.length;
+  }
+
+  @override
+  Iterator<String> get iterator => this;
+}
+
+class _MapValueIterator with IterableMixin<Reference> implements Iterator<Reference> {
+  final Reference _map;
+  int index;
+
+  _MapValueIterator(this._map) {
+    index = -1;
+  }
+
+  @override
+  Reference get current => _map._valueForIndex(index);
+
+  @override
+  bool moveNext() {
+    index++;
+    return index < _map.length;
+  }
+
+  @override
+  Iterator<Reference> get iterator => this;
+}
