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; |
+} |