Chromium Code Reviews| Index: lib/src/protobuf/map_mixin.dart |
| diff --git a/lib/src/protobuf/map_mixin.dart b/lib/src/protobuf/map_mixin.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..ad82a523a558ce19f33baa89c3a34c7f6f71a510 |
| --- /dev/null |
| +++ b/lib/src/protobuf/map_mixin.dart |
| @@ -0,0 +1,133 @@ |
| +// Copyright (c) 2015, 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 protobuf; |
| + |
| +// Used by the protoc plugin to avoid name conflicts. |
| +// TODO: extract names automatically somehow? |
| +const PbMapMixin_reservedNames = const [ |
| + 'addAll', 'containsKey', 'containsValue', 'forEach', 'putIfAbsent', |
| + 'remove', 'isEmpty', 'isNotEmpty', 'keys', 'length', 'values', |
| + 'getMapValue', 'mustGetMapValue', 'setMapValue' |
| +]; |
| + |
| +/// A PbMapMixin provides an experimental implementation of the |
|
Siggi Cherem (dart-lang)
2015/06/22 19:45:37
since your new protoc is more pluggable, I wonder
skybrian
2015/06/22 21:53:50
I'd like to keep it in the open source code as an
Siggi Cherem (dart-lang)
2015/06/22 22:22:25
Totally, we could still include an example in the
|
| +/// Map interface for a GeneratedMessage. |
| +/// |
| +/// This mixin is enabled via an option in |
| +/// dart_options.proto in dart-protoc-plugin. |
| +class PbMapMixin implements Map<String, dynamic> { |
|
Søren Gjesse
2015/06/22 07:25:01
Just for context here. Is this supposed to replace
skybrian
2015/06/22 21:53:50
Yes.
|
| + |
| + // GeneratedMessage properties and methods used by this mixin. |
| + |
| + BuilderInfo info_; |
| + void clear(); |
| + int getTagNumber(String fieldName); |
| + getField(int tagNumber); |
| + void setField(int tagNumber, var value, [int fieldType = null]); |
| + |
| + @override |
| + operator [] (key) { |
| + if (key is !String) return null; |
| + var tag = getTagNumber(key); |
| + if (tag == null) return null; |
| + return getField(tag); |
| + } |
| + |
| + @override |
| + operator []= (String key, val) { |
| + var tag = getTagNumber(key); |
| + if (tag == null) { |
| + throw new ArgumentError( |
| + "field '${key}' not found in ${info_.messageName}"); |
| + } |
| + setField(tag, val); |
| + } |
| + |
| + @override |
| + get keys => info_.byName.keys; |
| + |
| + @override |
| + bool containsKey(Object key) => info_.byName.containsKey(key); |
| + |
| + @override |
| + get length => info_.byName.length; |
| + |
| + @override |
| + remove(key) { |
| + throw new UnsupportedError( |
| + "remove() not supported by ${info_.messageName}"); |
| + } |
| + |
| + // methods copied from MapMixin (since mixins cannot mix in other mixins). |
|
Søren Gjesse
2015/06/22 07:25:01
Could another option be that whenever PbMapMixin i
skybrian
2015/06/22 21:53:50
Good idea. I can implement a simple form of inheri
|
| + |
| + @override |
| + void forEach(void action(String key, value)) { |
| + for (String key in keys) { |
| + action(key, this[key]); |
| + } |
| + } |
| + |
| + @override |
| + void addAll(Map<String, dynamic> other) { |
| + for (String key in other.keys) { |
| + this[key] = other[key]; |
| + } |
| + } |
| + |
| + @override |
| + bool containsValue(value) { |
| + for (String key in keys) { |
| + if (this[key] == value) return true; |
| + } |
| + return false; |
| + } |
| + |
| + @override |
| + putIfAbsent(String key, ifAbsent()) { |
| + if (keys.contains(key)) { |
| + return this[key]; |
| + } |
| + return this[key] = ifAbsent(); |
| + } |
| + |
| + bool get isEmpty => keys.isEmpty; |
| + bool get isNotEmpty => keys.isNotEmpty; |
| + Iterable get values => new _PbMapMixinValues(this); |
| +} |
| + |
| +class _PbMapMixinValues extends Iterable { |
| + final PbMapMixin _map; |
| + _PbMapMixinValues(this._map); |
| + |
| + int get length => _map.length; |
| + bool get isEmpty => _map.isEmpty; |
| + bool get isNotEmpty => _map.isNotEmpty; |
| + get first => _map[_map.keys.first]; |
| + get single => _map[_map.keys.single]; |
| + get last => _map[_map.keys.last]; |
| + |
| + Iterator get iterator => new _PbMapMixinValueIterator(_map); |
| +} |
| + |
| +class _PbMapMixinValueIterator implements Iterator { |
| + final Iterator _keys; |
| + final PbMapMixin _map; |
| + var _current = null; |
| + |
| + _PbMapMixinValueIterator(PbMapMixin map) : |
| + _map = map, |
| + _keys = map.keys.iterator; |
| + |
| + bool moveNext() { |
| + if (_keys.moveNext()) { |
| + _current = _map[_keys.current]; |
| + return true; |
| + } |
| + _current = null; |
| + return false; |
| + } |
| + |
| + get current => _current; |
| +} |