diff options
Diffstat (limited to 'src/org/gnunet/construct/Construct.java')
-rw-r--r-- | src/org/gnunet/construct/Construct.java | 61 |
1 files changed, 45 insertions, 16 deletions
diff --git a/src/org/gnunet/construct/Construct.java b/src/org/gnunet/construct/Construct.java index 603f5a5..965b97b 100644 --- a/src/org/gnunet/construct/Construct.java +++ b/src/org/gnunet/construct/Construct.java | |||
@@ -50,7 +50,7 @@ Wanted syntax (not fully implemented yet) | |||
50 | 50 | ||
51 | 51 | ||
52 | /** | 52 | /** |
53 | * Parse and write the binary representation of java classes, as defined by org.gnunet.construct.*-Annotations | 53 | * Parse and write the binary representation of java classes, as defined by org.gnunet.construct.*-annotations |
54 | * on their members. | 54 | * on their members. |
55 | * | 55 | * |
56 | * @author Christian Grothoff | 56 | * @author Christian Grothoff |
@@ -62,9 +62,18 @@ public class Construct { | |||
62 | .getLogger(Construct.class); | 62 | .getLogger(Construct.class); |
63 | 63 | ||
64 | 64 | ||
65 | private static HashMap<Class<? extends Message>, Parser> parserCache = new HashMap<Class<? extends Message>, | 65 | private static Map<Class<? extends Message>, Parser> parserCache = new HashMap<Class<? extends Message>, |
66 | Parser>(100); | 66 | Parser>(100); |
67 | 67 | ||
68 | |||
69 | /** | ||
70 | * The class Construct is not intended to be instantiated, this its constructor is private. | ||
71 | */ | ||
72 | private Construct() { | ||
73 | |||
74 | } | ||
75 | |||
76 | |||
68 | /** | 77 | /** |
69 | * Given a byte buffer with a message, parse it into an object of type c. The | 78 | * Given a byte buffer with a message, parse it into an object of type c. The |
70 | * fields of the class are expected to be annotated with annotations from | 79 | * fields of the class are expected to be annotated with annotations from |
@@ -82,6 +91,15 @@ public class Construct { | |||
82 | return m; | 91 | return m; |
83 | } | 92 | } |
84 | 93 | ||
94 | /** | ||
95 | * Given a byte array with a message, parse it into an object of type c. The | ||
96 | * fields of the class are expected to be annotated with annotations from | ||
97 | * the construct package. | ||
98 | * | ||
99 | * @param srcBuf buffer with the serialized binary data | ||
100 | * @param c desired object type to return | ||
101 | * @return instance of the desired object type | ||
102 | */ | ||
85 | public static <T extends Message> T parseAs(byte[] srcBuf, Class<T> c) { | 103 | public static <T extends Message> T parseAs(byte[] srcBuf, Class<T> c) { |
86 | return parseAs(ByteBuffer.wrap(srcBuf), c); | 104 | return parseAs(ByteBuffer.wrap(srcBuf), c); |
87 | } | 105 | } |
@@ -248,8 +266,7 @@ public class Construct { | |||
248 | Field nestedField = field; | 266 | Field nestedField = field; |
249 | 267 | ||
250 | if (n.newFrame()) { | 268 | if (n.newFrame()) { |
251 | ParserGenerator pg = new ParserGenerator(); | 269 | Parser p = getParser((Class<Message>) nestedField.getType()); |
252 | Parser p = getParser((Class<Message>) nestedField.getType(), pg); | ||
253 | 270 | ||
254 | parser = new NestedParser(p, n.optional(), nestedField, true); | 271 | parser = new NestedParser(p, n.optional(), nestedField, true); |
255 | 272 | ||
@@ -269,11 +286,6 @@ public class Construct { | |||
269 | } | 286 | } |
270 | } | 287 | } |
271 | 288 | ||
272 | public void visit(ByteFill bf) { | ||
273 | parser = new ByteFillParser(field); | ||
274 | } | ||
275 | |||
276 | |||
277 | public void visit(FixedSizeArray fsa) { | 289 | public void visit(FixedSizeArray fsa) { |
278 | Field f = field; | 290 | Field f = field; |
279 | int elemNumber = fsa.length(); | 291 | int elemNumber = fsa.length(); |
@@ -284,14 +296,13 @@ public class Construct { | |||
284 | parser = new FixedSizeArrayParser(elemNumber, parser, f); | 296 | parser = new FixedSizeArrayParser(elemNumber, parser, f); |
285 | } | 297 | } |
286 | 298 | ||
287 | public void visit(FixedSizeByteArray fsba) { | ||
288 | Field f = field; | ||
289 | int elemNumber = fsba.length(); | ||
290 | 299 | ||
291 | parser = new FixedSizeByteArrayParser(elemNumber, f); | 300 | public void visit(FixedSizeIntegerArray fsa) { |
301 | Field f = field; | ||
302 | int elemNumber = fsa.length(); | ||
303 | parser = new FixedSizeIntegerArrayParser(elemNumber, fsa.signed(), fsa.bitSize() / 8, f); | ||
292 | } | 304 | } |
293 | 305 | ||
294 | |||
295 | public void visit(Double d) { | 306 | public void visit(Double d) { |
296 | if (!field.getType().equals(java.lang.Double.TYPE)) { | 307 | if (!field.getType().equals(java.lang.Double.TYPE)) { |
297 | throw new AssertionError("@Double target must be a primitive 'double' field"); | 308 | throw new AssertionError("@Double target must be a primitive 'double' field"); |
@@ -322,6 +333,10 @@ public class Construct { | |||
322 | Parser p = getParser((Class<? extends Message>) field.getType() | 333 | Parser p = getParser((Class<? extends Message>) field.getType() |
323 | .getComponentType()); | 334 | .getComponentType()); |
324 | 335 | ||
336 | if (!Message.class.isAssignableFrom(field.getType().getComponentType())) { | ||
337 | throw new AssertionError("VariableSizeArray only valid on arrays of messages."); | ||
338 | } | ||
339 | |||
325 | try { | 340 | try { |
326 | parser = new VariableSizeArrayParser(p, c.getField(vsa | 341 | parser = new VariableSizeArrayParser(p, c.getField(vsa |
327 | .lengthField()), field); | 342 | .lengthField()), field); |
@@ -412,10 +427,10 @@ public class Construct { | |||
412 | } | 427 | } |
413 | 428 | ||
414 | /** | 429 | /** |
415 | * Compute the size of a serialized message. | 430 | * Compute the exact size of a serialized message. |
416 | * | 431 | * |
417 | * @param m object to serialize | 432 | * @param m object to serialize |
418 | * @return number of bytes required, -1 on error | 433 | * @return number of bytes required to store the message in binary form |
419 | */ | 434 | */ |
420 | public static int getSize(Message m) { | 435 | public static int getSize(Message m) { |
421 | if (m == null) { | 436 | if (m == null) { |
@@ -425,6 +440,13 @@ public class Construct { | |||
425 | return p.getSize(m); | 440 | return p.getSize(m); |
426 | } | 441 | } |
427 | 442 | ||
443 | |||
444 | /** | ||
445 | * Return the binary representation of the message m | ||
446 | * | ||
447 | * @param m the message to serialize | ||
448 | * @return a byte array containing the serialized message | ||
449 | */ | ||
428 | public static byte[] toBinary(Message m) { | 450 | public static byte[] toBinary(Message m) { |
429 | byte[] a = new byte[getSize(m)]; | 451 | byte[] a = new byte[getSize(m)]; |
430 | ByteBuffer buf = ByteBuffer.wrap(a); | 452 | ByteBuffer buf = ByteBuffer.wrap(a); |
@@ -432,6 +454,13 @@ public class Construct { | |||
432 | return a; | 454 | return a; |
433 | } | 455 | } |
434 | 456 | ||
457 | /** | ||
458 | * Fill in all fields of a message that are inferable from existing information. | ||
459 | * | ||
460 | * Examples: The size field for variable size arrays, the type of unions, ... | ||
461 | * | ||
462 | * @param m the message that should be patched | ||
463 | */ | ||
435 | public static void patch(Message m) { | 464 | public static void patch(Message m) { |
436 | Parser p = getParser(m.getClass()); | 465 | Parser p = getParser(m.getClass()); |
437 | p.patch(m, p.getSize(m), null, m); | 466 | p.patch(m, p.getSize(m), null, m); |