Skip to content
Browse files

add succession extension type and (get-raw ...) to get value bypassin…

…g extensions
  • Loading branch information...
1 parent e4ca8a0 commit d7b7c917e2933d0899c12438081ffb6f94ad42fc @ninjudd committed
View
2 project.clj
@@ -1,4 +1,4 @@
-(defproject clojure-protobuf "0.4.4"
+(defproject clojure-protobuf "0.4.5"
:description "Clojure-protobuf provides a clojure interface to Google's protocol buffers."
:dependencies [[clojure "1.2.0"]
[ordered-set "0.2.2"]]
View
11 proto/clojure/protobuf/extensions.proto
@@ -4,9 +4,10 @@ option java_package = "clojure.protobuf";
option java_outer_classname = "Extensions";
extend google.protobuf.FieldOptions {
- optional bool set = 52001;
- optional bool map = 52002;
- optional string map_by = 52003;
- optional bool counter = 52004;
- optional string meta = 52010;
+ optional bool set = 52001;
+ optional bool map = 52002;
+ optional string map_by = 52003;
+ optional bool counter = 52004;
+ optional bool succession = 52005;
+ optional string meta = 52010;
}
View
10 proto/clojure/protobuf/test.proto
@@ -18,6 +18,8 @@ message Foo {
repeated Count counts = 10 [(map_by) = "key"];
+ repeated Time time = 11 [(succession) = true];
+
enum Response {
YES = 0;
NO = 1;
@@ -34,6 +36,14 @@ message Foo {
optional bool deleted = 26 [default = false];
}
+message Time {
+ optional sint32 year = 1;
+ optional int32 month = 2;
+ optional int32 day = 3;
+ optional int32 hour = 4;
+ optional int32 minute = 5;
+}
+
message Pair {
required string key = 1;
required string val = 2;
View
7 src/clj/protobuf.clj
@@ -101,4 +101,9 @@
(defn adjoin
"Merge the given map into the protobuf. Like append, except default values in map will be used if it i."
[^PersistentProtocolBufferMap p map]
- (.adjoin p map))
+ (.adjoin p map))
+
+(defn get-raw
+ "Get value at key ignoring extension fields."
+ [^PersistentProtocolBufferMap p key]
+ (.getValAt p key false))
View
147 src/jvm/clojure/protobuf/PersistentProtocolBufferMap.java
@@ -249,78 +249,85 @@ static protected Keyword mapFieldBy(Descriptors.FieldDescriptor field) {
static Keyword k_item = Keyword.intern(Symbol.intern("item"));
static Keyword k_exists = Keyword.intern(Symbol.intern("exists"));
static protected Object fromProtoValue(Descriptors.FieldDescriptor field, Object value) {
+ return fromProtoValue(field, value, true);
+ }
+
+ static protected Object fromProtoValue(Descriptors.FieldDescriptor field, Object value, boolean use_extensions) {
if (value instanceof List) {
List values = (List) value;
Iterator iterator = values.iterator();
- Keyword map_field_by = mapFieldBy(field);
- DescriptorProtos.FieldOptions options = field.getOptions();
- if (map_field_by != null) {
- ITransientMap map = PersistentHashMap.EMPTY.asTransient();
- while (iterator.hasNext()) {
- PersistentProtocolBufferMap val = (PersistentProtocolBufferMap) fromProtoValue(field, iterator.next());
- Object key = val.valAt(map_field_by);
- PersistentProtocolBufferMap existing = (PersistentProtocolBufferMap) map.valAt(key);
- if (existing != null) {
- map.assoc(key, existing.append(val));
- } else {
- map.assoc(key, val);
+ if (use_extensions) {
+ Keyword map_field_by = mapFieldBy(field);
+ DescriptorProtos.FieldOptions options = field.getOptions();
+ if (map_field_by != null) {
+ ITransientMap map = PersistentHashMap.EMPTY.asTransient();
+ while (iterator.hasNext()) {
+ PersistentProtocolBufferMap val = (PersistentProtocolBufferMap) fromProtoValue(field, iterator.next());
+ Object key = val.valAt(map_field_by);
+ PersistentProtocolBufferMap existing = (PersistentProtocolBufferMap) map.valAt(key);
+ if (existing != null) {
+ map.assoc(key, existing.append(val));
+ } else {
+ map.assoc(key, val);
+ }
}
- }
- return map.persistent();
- } else if (options.getExtension(Extensions.counter)) {
- Object count = iterator.next();
- while (iterator.hasNext()) {
- count = Numbers.add(count, iterator.next());
- }
- return count;
- } else if (options.getExtension(Extensions.map)) {
- Def def = PersistentProtocolBufferMap.Def.create(field.getMessageType());
- Descriptors.FieldDescriptor key_field = def.fieldDescriptor(k_key);
- Descriptors.FieldDescriptor val_field = def.fieldDescriptor(k_val);
-
- ITransientMap map = PersistentHashMap.EMPTY.asTransient();
- while (iterator.hasNext()) {
- DynamicMessage message = (DynamicMessage) iterator.next();
- Object key = fromProtoValue(key_field, message.getField(key_field));
- Object val = fromProtoValue(val_field, message.getField(val_field));
- Object existing = map.valAt(key);
- if (existing != null && existing instanceof IPersistentCollection) {
- map.assoc(key, ((IPersistentCollection) existing).cons(val));
- } else {
- map.assoc(key, val);
+ return map.persistent();
+ } else if (options.getExtension(Extensions.counter)) {
+ Object count = iterator.next();
+ while (iterator.hasNext()) {
+ count = Numbers.add(count, iterator.next());
}
- }
- return map.persistent();
- } else if (options.getExtension(Extensions.set)) {
- Def def = PersistentProtocolBufferMap.Def.create(field.getMessageType());
- Descriptors.FieldDescriptor item_field = def.fieldDescriptor(k_item);
- Descriptors.FieldDescriptor exists_field = def.fieldDescriptor(k_exists);
-
- ITransientSet set = (ITransientSet) PersistentOrderedSet.EMPTY.asTransient();
- while (iterator.hasNext()) {
- DynamicMessage message = (DynamicMessage) iterator.next();
- Object item = fromProtoValue(item_field, message.getField(item_field));
- Boolean exists = (Boolean) message.getField(exists_field);
-
- if (exists) {
- set.conj(item);
- } else {
- try {
- set.disjoin(item);
- } catch (Exception e) {
- e.printStackTrace();
+ return count;
+ } else if (options.getExtension(Extensions.succession)) {
+ return fromProtoValue(field, values.get(values.size() - 1));
+ } else if (options.getExtension(Extensions.map)) {
+ Def def = PersistentProtocolBufferMap.Def.create(field.getMessageType());
+ Descriptors.FieldDescriptor key_field = def.fieldDescriptor(k_key);
+ Descriptors.FieldDescriptor val_field = def.fieldDescriptor(k_val);
+
+ ITransientMap map = PersistentHashMap.EMPTY.asTransient();
+ while (iterator.hasNext()) {
+ DynamicMessage message = (DynamicMessage) iterator.next();
+ Object key = fromProtoValue(key_field, message.getField(key_field));
+ Object val = fromProtoValue(val_field, message.getField(val_field));
+ Object existing = map.valAt(key);
+ if (existing != null && existing instanceof IPersistentCollection) {
+ map.assoc(key, ((IPersistentCollection) existing).cons(val));
+ } else {
+ map.assoc(key, val);
}
}
+ return map.persistent();
+ } else if (options.getExtension(Extensions.set)) {
+ Def def = PersistentProtocolBufferMap.Def.create(field.getMessageType());
+ Descriptors.FieldDescriptor item_field = def.fieldDescriptor(k_item);
+ Descriptors.FieldDescriptor exists_field = def.fieldDescriptor(k_exists);
+
+ ITransientSet set = (ITransientSet) PersistentOrderedSet.EMPTY.asTransient();
+ while (iterator.hasNext()) {
+ DynamicMessage message = (DynamicMessage) iterator.next();
+ Object item = fromProtoValue(item_field, message.getField(item_field));
+ Boolean exists = (Boolean) message.getField(exists_field);
+
+ if (exists) {
+ set.conj(item);
+ } else {
+ try {
+ set.disjoin(item);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
+ return set.persistent();
}
- return set.persistent();
- } else {
- List<Object> list = new ArrayList<Object>(values.size());
- while (iterator.hasNext()) {
- list.add(fromProtoValue(field, iterator.next()));
- }
- return PersistentVector.create(list);
}
+ List<Object> list = new ArrayList<Object>(values.size());
+ while (iterator.hasNext()) {
+ list.add(fromProtoValue(field, iterator.next(), use_extensions));
+ }
+ return PersistentVector.create(list);
} else {
switch (field.getJavaType()) {
case ENUM:
@@ -331,7 +338,7 @@ static protected Object fromProtoValue(Descriptors.FieldDescriptor field, Object
DynamicMessage message = (DynamicMessage) value;
// Total hack because getField() doesn't return an empty array for repeated messages.
- if (field.isRepeated() && !message.isInitialized()) return fromProtoValue(field, new ArrayList());
+ if (field.isRepeated() && !message.isInitialized()) return fromProtoValue(field, new ArrayList(), use_extensions);
return new PersistentProtocolBufferMap(null, def, message);
default:
@@ -467,11 +474,7 @@ public IMapEntry entryAt(Object key) {
}
public Object valAt(Object key) {
- Descriptors.FieldDescriptor field = def.fieldDescriptor(key);
- if (field == null) return null;
- if (field.isRepeated() && message().getRepeatedFieldCount(field) == 0) return null;
- if (!field.isRepeated() && !field.hasDefaultValue() && !message().hasField(field)) return null;
- return fromProtoValue(field, message().getField(field));
+ return getValAt(key, true);
}
public Object valAt(Object key, Object notFound) {
@@ -479,6 +482,14 @@ public Object valAt(Object key, Object notFound) {
return (val == null) ? notFound : val;
}
+ public Object getValAt(Object key, boolean use_extensions) {
+ Descriptors.FieldDescriptor field = def.fieldDescriptor(key);
+ if (field == null) return null;
+ if (field.isRepeated() && message().getRepeatedFieldCount(field) == 0) return null;
+ if (!field.isRepeated() && !field.hasDefaultValue() && !message().hasField(field)) return null;
+ return fromProtoValue(field, message().getField(field), use_extensions);
+ }
+
public IPersistentMap assoc(Object key, Object val) {
DynamicMessage.Builder builder = builder();
Descriptors.FieldDescriptor field = def.fieldDescriptor(key);
View
25 test/protobuf_test.clj
@@ -147,7 +147,7 @@
(is (= ["odd"] (get-in p [:foo-by-id 6 :tags])))
(is (= nil (get-in p [:foo-by-id 6 :label]))))))
-(deftest test-counts
+(deftest test-nested-counters
(let [p (protobuf Foo :counts {"foo" {:i 5 :d 5.0}})]
(is (= 5 (get-in p [:counts "foo" :i])))
(is (= 5.0 (get-in p [:counts "foo" :d])))
@@ -158,13 +158,32 @@
(let [p (append p {:counts {"foo" {:i -8 :d 4.06} "bar" {:i -66}}})]
(is (= -1 (get-in p [:counts "foo" :i])))
(is (= 6.66 (get-in p [:counts "foo" :d])))
- (is (= 33 (get-in p [:counts "bar" :i])))))))
+ (is (= 33 (get-in p [:counts "bar" :i])))
+ (is (= [{:key "foo", :i 5, :d 5.0}
+ {:key "foo", :i 2, :d -2.4}
+ {:key "bar", :i 99}
+ {:key "foo", :i -8, :d 4.06}
+ {:key "bar", :i -66}]
+ (get-raw p :counts)))))))
+
+(deftest test-succession
+ (let [p (protobuf Foo :time {:year 1978 :month 11 :day 24})]
+ (is (= 1978 (get-in p [:time :year])))
+ (is (= 11 (get-in p [:time :month])))
+ (is (= 24 (get-in p [:time :day])))
+ (let [p (append p {:time {:year 1974 :month 1}})]
+ (is (= 1974 (get-in p [:time :year])))
+ (is (= 1 (get-in p [:time :month])))
+ (is (= nil (get-in p [:time :day])))
+ (is (= [{:year 1978, :month 11, :day 24} {:year 1974, :month 1}]
+ (get-raw p :time))))))
(deftest test-protofields
(let [fields {:parent {:repeated false, :type :message},
:floats {:repeated true, :type :float},
:doubles {:repeated true, :type :double},
:counts {:repeated true, :type :message},
+ :time {:repeated true, :type :message},
:attr-map {:repeated true, :type :message},
:tag-set {:repeated true, :type :message},
:item-map {:repeated true, :type :message},
@@ -206,7 +225,7 @@
(is (= [:yes :not_sure :maybe :not_sure :no] (:responses p)))
(is (= #{:id :label :tags :parent :responses :tag_set :deleted :attr_map :foo_by_id
- :pair_map :groups :doubles :floats :item_map :counts :lat :long}
+ :pair_map :groups :doubles :floats :item_map :counts :time :lat :long}
(set (keys (protofields Foo)))))
(clojure.protobuf.PersistentProtocolBufferMap/setUseUnderscores false)))

0 comments on commit d7b7c91

Please sign in to comment.
Something went wrong with that request. Please try again.