1313
1414package com .google .census ;
1515
16- import static java .nio .charset .StandardCharsets .UTF_8 ;
16+ import com .google .census .proto .CensusContextProto ;
17+ import com .google .protobuf .InvalidProtocolBufferException ;
1718
1819import java .nio .ByteBuffer ;
1920import java .util .HashMap ;
2021import java .util .Map .Entry ;
21-
2222import javax .annotation .Nullable ;
2323
2424/** Native implementation {@link CensusContext} serialization. */
2525final class CensusSerializer {
2626 private static final char TAG_PREFIX = '\2' ;
2727 private static final char TAG_DELIM = '\3' ;
2828
29- // The serialized tags are of the form: (<tag prefix> + 'key' + <tag delim> + 'value')*
29+
30+ // Serializes a CensusContext by transforming it into a CensusContextProto. The
31+ // encoded tags are of the form: (<tag prefix> + 'key' + <tag delim> + 'value')*
3032 static ByteBuffer serialize (CensusContextImpl context ) {
3133 StringBuilder builder = new StringBuilder ();
3234 for (Entry <String , String > tag : context .tags .entrySet ()) {
@@ -36,27 +38,58 @@ static ByteBuffer serialize(CensusContextImpl context) {
3638 .append (TAG_DELIM )
3739 .append (tag .getValue ());
3840 }
39- return ByteBuffer .wrap (builder .toString ().getBytes (UTF_8 ));
41+ return ByteBuffer .wrap (CensusContextProto .CensusContext .
42+ newBuilder ().setTags (builder .toString ()).build ().toByteArray ());
4043 }
4144
42- // The serialized tags are of the form: (<tag prefix> + 'key' + <tag delim> + 'value')*
45+ // Deserializes based on an serialized CensusContextProto. The encoded tags are of the form:
46+ // (<tag prefix> + 'key' + <tag delim> + 'value')*
4347 @ Nullable
4448 static CensusContextImpl deserialize (ByteBuffer buffer ) {
45- String input = new String (buffer .array (), UTF_8 );
46- HashMap <String , String > tags = new HashMap <>();
47- if (!input .matches ("(\2 [^\2 \3 ]*\3 [^\2 \3 ]*)*" )) {
49+ try {
50+ CensusContextProto .CensusContext context =
51+ CensusContextProto .CensusContext .parser ().parseFrom (buffer .array ());
52+ return new CensusContextImpl (fromString (context .getTags ()));
53+ } catch (IllegalArgumentException | InvalidProtocolBufferException e ) {
4854 return null ;
4955 }
50- if (!input .isEmpty ()) {
51- int keyIndex = 0 ;
52- do {
53- int valIndex = input .indexOf (TAG_DELIM , keyIndex + 1 );
54- String key = input .substring (keyIndex + 1 , valIndex );
55- keyIndex = input .indexOf (TAG_PREFIX , valIndex + 1 );
56- String val = input .substring (valIndex + 1 , keyIndex == -1 ? input .length () : keyIndex );
57- tags .put (key , val );
58- } while (keyIndex != -1 );
56+ }
57+
58+ private static HashMap <String , String > fromString (String encoded ) {
59+ HashMap <String , String > tags = new HashMap <>();
60+ int length = encoded .length ();
61+ int index = 0 ;
62+ while (index != length ) {
63+ int valIndex = endOfKey (encoded , index );
64+ String key = encoded .substring (index + 1 , valIndex );
65+ index = endOfValue (encoded , valIndex );
66+ String val = encoded .substring (valIndex + 1 , index );
67+ tags .put (key , val );
68+ }
69+ return tags ;
70+ }
71+
72+ private static int endOfKey (String encoded , int index ) {
73+ int valIndex = encoded .indexOf (TAG_DELIM , index );
74+ if (valIndex == -1 ) {
75+ throw new IllegalArgumentException ("Missing tag delimiter." );
76+ }
77+ int keyIndex = encoded .lastIndexOf (TAG_PREFIX , valIndex );
78+ if (keyIndex != index ) {
79+ throw new IllegalArgumentException ("Missing tag prefix." );
80+ }
81+ return valIndex ;
82+ }
83+
84+ private static int endOfValue (String encoded , int index ) {
85+ int keyIndex = encoded .indexOf (TAG_PREFIX , index );
86+ if (keyIndex == -1 ) {
87+ keyIndex = encoded .length ();
88+ }
89+ int valIndex = encoded .lastIndexOf (TAG_DELIM , keyIndex );
90+ if (valIndex != index ) {
91+ throw new IllegalArgumentException ("Missing tag delimiter." );
5992 }
60- return new CensusContextImpl ( tags ) ;
93+ return keyIndex ;
6194 }
6295}
0 commit comments