1 /*
2 * hunt-proton: AMQP Protocol library for D programming language.
3 *
4 * Copyright (C) 2018-2019 HuntLabs
5 *
6 * Website: https://www.huntlabs.net/
7 *
8 * Licensed under the Apache-2.0 License.
9 *
10 */
11
12 module hunt.proton.codec.ArrayType;
13
14 /*
15 import java.lang.reflect.Array;
16 import java.util.Arrays;
17 import hunt.collection.Collection;
18
19 class ArrayType implements PrimitiveType!(Object[])
20 {
21 private EncoderImpl _encoder;
22 private BooleanType _boolType;
23 private ByteType _byteType;
24 private ShortType _shortType;
25 private IntegerType _integerType;
26 private LongType _longType;
27 private FloatType _floatType;
28 private DoubleType _doubleType;
29 private CharacterType _characterType;
30
31 public static interface ArrayEncoding : PrimitiveTypeEncoding!(Object[])
32 {
33 void writeValue(bool[] a);
34 void writeValue(byte[] a);
35 void writeValue(short[] a);
36 void writeValue(int[] a);
37 void writeValue(long[] a);
38 void writeValue(float[] a);
39 void writeValue(double[] a);
40 void writeValue(char[] a);
41
42 void setValue(Object[] val, TypeEncoding<?> encoder, int size);
43
44 int getSizeBytes();
45
46 Object readValueArray();
47 }
48
49 private ArrayEncoding _shortArrayEncoding;
50 private ArrayEncoding _arrayEncoding;
51
52 public ArrayType(EncoderImpl encoder,
53 DecoderImpl decoder, BooleanType boolType,
54 ByteType byteType,
55 ShortType shortType,
56 IntegerType intType,
57 LongType longType,
58 FloatType floatType,
59 DoubleType doubleType,
60 CharacterType characterType)
61 {
62 _encoder = encoder;
63 _boolType = boolType;
64 _byteType = byteType;
65 _shortType = shortType;
66 _integerType = intType;
67 _longType = longType;
68 _floatType = floatType;
69 _doubleType = doubleType;
70 _characterType = characterType;
71
72 _arrayEncoding = new AllArrayEncoding(encoder, decoder);
73 _shortArrayEncoding = new ShortArrayEncoding(encoder, decoder);
74
75 encoder.register(Object[].class, this);
76 decoder.register(this);
77 }
78
79 override
80 public Class!(Object[]) getTypeClass()
81 {
82 return Object[].class;
83 }
84
85 override
86 public ArrayEncoding getEncoding(Object[] val)
87 {
88 TypeEncoding<?> encoder = calculateEncoder(val,_encoder);
89 int size = calculateSize(val, encoder);
90 ArrayEncoding arrayEncoding = (val.length > 255 || size > 254)
91 ? _arrayEncoding
92 : _shortArrayEncoding;
93 arrayEncoding.setValue(val, encoder, size);
94 return arrayEncoding;
95 }
96
97 private static TypeEncoding<?> calculateEncoder(Object[] val, EncoderImpl encoder)
98 {
99 if(val.length == 0)
100 {
101 AMQPType underlyingType = encoder.getTypeFromClass(val.getClass().getComponentType());
102 return underlyingType.getCanonicalEncoding();
103 }
104 else
105 {
106 AMQPType underlyingType = encoder.getTypeFromClass(val.getClass().getComponentType());
107 bool checkTypes = false;
108
109 if(val[0].getClass().isArray() && val[0].getClass().getComponentType().isPrimitive())
110 {
111 Class componentType = val[0].getClass().getComponentType();
112 if(componentType == Boolean.TYPE)
113 {
114 return ((ArrayType)underlyingType).getEncoding((bool[])val[0]);
115 }
116 else if(componentType == Byte.TYPE)
117 {
118 return ((ArrayType)underlyingType).getEncoding((byte[])val[0]);
119 }
120 else if(componentType == Short.TYPE)
121 {
122 return ((ArrayType)underlyingType).getEncoding((short[])val[0]);
123 }
124 else if(componentType == Integer.TYPE)
125 {
126 return ((ArrayType)underlyingType).getEncoding((int[])val[0]);
127 }
128 else if(componentType == Long.TYPE)
129 {
130 return ((ArrayType)underlyingType).getEncoding((long[])val[0]);
131 }
132 else if(componentType == Float.TYPE)
133 {
134 return ((ArrayType)underlyingType).getEncoding((float[])val[0]);
135 }
136 else if(componentType == Double.TYPE)
137 {
138 return ((ArrayType)underlyingType).getEncoding((double[])val[0]);
139 }
140 else if(componentType == Character.TYPE)
141 {
142 return ((ArrayType)underlyingType).getEncoding((char[])val[0]);
143 }
144 else
145 {
146 throw new IllegalArgumentException("Cannot encode arrays of type " ~ componentType.getName());
147 }
148 }
149 else
150 {
151 if(underlyingType is null)
152 {
153 checkTypes = true;
154 underlyingType = encoder.getType(val[0]);
155 }
156 TypeEncoding underlyingEncoding = underlyingType.getEncoding(val[0]);
157 TypeEncoding canonicalEncoding = underlyingType.getCanonicalEncoding();
158
159 for(int i = 0; i < val.length && (checkTypes || underlyingEncoding != canonicalEncoding); i++)
160 {
161 if(checkTypes && encoder.getType(val[i]) != underlyingType)
162 {
163 throw new IllegalArgumentException("Non matching types " ~ underlyingType ~ " and " ~ encoder
164 .getType(val[i]) ~ " in array");
165 }
166
167 TypeEncoding elementEncoding = underlyingType.getEncoding(val[i]);
168 if(elementEncoding != underlyingEncoding && !underlyingEncoding.encodesSuperset(elementEncoding))
169 {
170 if(elementEncoding.encodesSuperset(underlyingEncoding))
171 {
172 underlyingEncoding = elementEncoding;
173 }
174 else
175 {
176 underlyingEncoding = canonicalEncoding;
177 }
178 }
179
180 }
181
182 return underlyingEncoding;
183 }
184 }
185 }
186
187 private static int calculateSize(Object[] val, TypeEncoding encoder)
188 {
189 int size = encoder.getConstructorSize();
190 if(encoder.isFixedSizeVal())
191 {
192 size += val.length * encoder.getValueSize(null);
193 }
194 else
195 {
196 for(Object o : val)
197 {
198 if(o.getClass().isArray() && o.getClass().getComponentType().isPrimitive())
199 {
200 ArrayEncoding arrayEncoding = (ArrayEncoding) encoder;
201 ArrayType arrayType = (ArrayType) arrayEncoding.getType();
202
203 Class componentType = o.getClass().getComponentType();
204
205 size += 2 * arrayEncoding.getSizeBytes();
206
207 TypeEncoding componentEncoding;
208 int componentCount;
209
210 if(componentType == Boolean.TYPE)
211 {
212 bool[] componentArray = (bool[]) o;
213 componentEncoding = arrayType.getUnderlyingEncoding(componentArray);
214 componentCount = componentArray.length;
215 }
216 else if(componentType == Byte.TYPE)
217 {
218 byte[] componentArray = (byte[]) o;
219 componentEncoding = arrayType.getUnderlyingEncoding(componentArray);
220 componentCount = componentArray.length;
221 }
222 else if(componentType == Short.TYPE)
223 {
224 short[] componentArray = (short[]) o;
225 componentEncoding = arrayType.getUnderlyingEncoding(componentArray);
226 componentCount = componentArray.length;
227 }
228 else if(componentType == Integer.TYPE)
229 {
230 int[] componentArray = (int[]) o;
231 componentEncoding = arrayType.getUnderlyingEncoding(componentArray);
232 componentCount = componentArray.length;
233 }
234 else if(componentType == Long.TYPE)
235 {
236 long[] componentArray = (long[]) o;
237 componentEncoding = arrayType.getUnderlyingEncoding(componentArray);
238 componentCount = componentArray.length;
239 }
240 else if(componentType == Float.TYPE)
241 {
242 float[] componentArray = (float[]) o;
243 componentEncoding = arrayType.getUnderlyingEncoding(componentArray);
244 componentCount = componentArray.length;
245 }
246 else if(componentType == Double.TYPE)
247 {
248 double[] componentArray = (double[]) o;
249 componentEncoding = arrayType.getUnderlyingEncoding(componentArray);
250 componentCount = componentArray.length;
251 }
252 else if(componentType == Character.TYPE)
253 {
254 char[] componentArray = (char[]) o;
255 componentEncoding = arrayType.getUnderlyingEncoding(componentArray);
256 componentCount = componentArray.length;
257 }
258 else
259 {
260 throw new IllegalArgumentException("Cannot encode arrays of type " ~ componentType.getName());
261 }
262
263 size += componentEncoding.getConstructorSize()
264 + componentEncoding.getValueSize(null) * componentCount;
265 }
266 else
267 {
268 size += encoder.getValueSize(o);
269 }
270 }
271 }
272
273 return size;
274 }
275
276 override
277 public ArrayEncoding getCanonicalEncoding()
278 {
279 return _arrayEncoding;
280 }
281
282 override
283 public Collection!(ArrayEncoding) getAllEncodings()
284 {
285 return Arrays.asList(_shortArrayEncoding, _arrayEncoding);
286 }
287
288 override
289 public void write(Object[] val)
290 {
291 ArrayEncoding encoding = getEncoding(val);
292 encoding.writeConstructor();
293 encoding.writeValue(val);
294 }
295
296 public void write(bool[] a)
297 {
298 ArrayEncoding encoding = getEncoding(a);
299 encoding.writeConstructor();
300 encoding.writeValue(a);
301 }
302
303 private ArrayEncoding getEncoding(bool[] a)
304 {
305 return a.length < 254 || a.length <= 255 && allSameValue(a) ? _shortArrayEncoding : _arrayEncoding;
306 }
307
308 private bool allSameValue(bool[] a)
309 {
310 bool val = a[0];
311 for(int i = 1; i < a.length; i++)
312 {
313 if(val != a[i])
314 {
315 return false;
316 }
317 }
318 return true;
319 }
320
321 public void write(byte[] a)
322 {
323 ArrayEncoding encoding = getEncoding(a);
324 encoding.writeConstructor();
325 encoding.writeValue(a);
326 }
327
328 private ArrayEncoding getEncoding(byte[] a)
329 {
330 return a.length < 254 ? _shortArrayEncoding : _arrayEncoding;
331 }
332
333 public void write(short[] a)
334 {
335 ArrayEncoding encoding = getEncoding(a);
336 encoding.writeConstructor();
337 encoding.writeValue(a);
338 }
339
340 private ArrayEncoding getEncoding(short[] a)
341 {
342 return a.length < 127 ? _shortArrayEncoding : _arrayEncoding;
343 }
344
345 public void write(int[] a)
346 {
347 ArrayEncoding encoding = getEncoding(a);
348 encoding.writeConstructor();
349 encoding.writeValue(a);
350 }
351
352 private ArrayEncoding getEncoding(int[] a)
353 {
354 return a.length < 63 || (a.length < 254 && allSmallInts(a)) ? _shortArrayEncoding : _arrayEncoding;
355 }
356
357 private bool allSmallInts(int[] a)
358 {
359 for(int i = 0; i < a.length; i++)
360 {
361 if(a[i] < -128 || a[i] > 127)
362 {
363 return false;
364 }
365 }
366 return true;
367 }
368
369 public void write(long[] a)
370 {
371 ArrayEncoding encoding = getEncoding(a);
372 encoding.writeConstructor();
373 encoding.writeValue(a);
374 }
375
376 private ArrayEncoding getEncoding(long[] a)
377 {
378 return a.length < 31 || (a.length < 254 && allSmallLongs(a)) ? _shortArrayEncoding : _arrayEncoding;
379 }
380
381 private bool allSmallLongs(long[] a)
382 {
383 for(int i = 0; i < a.length; i++)
384 {
385 if(a[i] < -128L || a[i] > 127L)
386 {
387 return false;
388 }
389 }
390 return true;
391 }
392
393 public void write(float[] a)
394 {
395 ArrayEncoding encoding = getEncoding(a);
396 encoding.writeConstructor();
397 encoding.writeValue(a);
398 }
399
400 private ArrayEncoding getEncoding(float[] a)
401 {
402 return a.length < 63 ? _shortArrayEncoding : _arrayEncoding;
403 }
404
405 public void write(double[] a)
406 {
407 ArrayEncoding encoding = getEncoding(a);
408 encoding.writeConstructor();
409 encoding.writeValue(a);
410 }
411
412 private ArrayEncoding getEncoding(double[] a)
413 {
414 return a.length < 31 ? _shortArrayEncoding : _arrayEncoding;
415 }
416
417 public void write(char[] a)
418 {
419 ArrayEncoding encoding = getEncoding(a);
420 encoding.writeConstructor();
421 encoding.writeValue(a);
422 }
423
424 private ArrayEncoding getEncoding(char[] a)
425 {
426 return a.length < 63 ? _shortArrayEncoding : _arrayEncoding;
427 }
428
429 private class AllArrayEncoding
430 : LargeFloatingSizePrimitiveTypeEncoding!(Object[])
431 implements ArrayEncoding
432 {
433 private Object[] _val;
434 private TypeEncoding _underlyingEncoder;
435 private int _size;
436
437 AllArrayEncoding(EncoderImpl encoder, DecoderImpl decoder)
438 {
439 super(encoder, decoder);
440 }
441
442 override
443 protected void writeSize(Object[] val)
444 {
445 int encodedValueSize = getEncodedValueSize(val);
446 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
447 getEncoder().writeRaw(encodedValueSize);
448 }
449
450 override
451 public void writeValue(bool[] a)
452 {
453 BooleanType.BooleanEncoding underlyingEncoder = getUnderlyingEncoding(a);
454 int encodedValueSize = 4 + underlyingEncoder.getConstructorSize() +
455 a.length * underlyingEncoder.getValueSize(null);
456 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
457 getEncoder().writeRaw(encodedValueSize);
458 getEncoder().writeRaw(a.length);
459 underlyingEncoder.writeConstructor();
460 for(bool b : a)
461 {
462 underlyingEncoder.writeValue(b);
463 }
464 }
465
466 override
467 public void writeValue(byte[] a)
468 {
469 ByteType.ByteEncoding underlyingEncoder = getUnderlyingEncoding(a);
470 int encodedValueSize = 4 + underlyingEncoder.getConstructorSize() +
471 a.length * underlyingEncoder.getValueSize(null);
472 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
473 getEncoder().writeRaw(encodedValueSize);
474 getEncoder().writeRaw(a.length);
475 underlyingEncoder.writeConstructor();
476 for(byte b : a)
477 {
478 underlyingEncoder.writeValue(b);
479 }
480 }
481
482 override
483 public void writeValue(short[] a)
484 {
485 ShortType.ShortEncoding underlyingEncoder = getUnderlyingEncoding(a);
486 int encodedValueSize = 4 + underlyingEncoder.getConstructorSize() +
487 a.length * underlyingEncoder.getValueSize(null);
488 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
489 getEncoder().writeRaw(encodedValueSize);
490 getEncoder().writeRaw(a.length);
491 underlyingEncoder.writeConstructor();
492 for(short b : a)
493 {
494 underlyingEncoder.writeValue(b);
495 }
496 }
497
498 override
499 public void writeValue(int[] a)
500 {
501 IntegerType.IntegerEncoding underlyingEncoder = getUnderlyingEncoding(a);
502 int encodedValueSize = 4 + underlyingEncoder.getConstructorSize() +
503 a.length * underlyingEncoder.getValueSize(null);
504 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
505 getEncoder().writeRaw(encodedValueSize);
506 getEncoder().writeRaw(a.length);
507 underlyingEncoder.writeConstructor();
508 for(int b : a)
509 {
510 underlyingEncoder.writeValue(b);
511 }
512 }
513
514 override
515 public void writeValue(long[] a)
516 {
517 LongType.LongEncoding underlyingEncoder = getUnderlyingEncoding(a);
518 int encodedValueSize = 4 + underlyingEncoder.getConstructorSize() +
519 a.length * underlyingEncoder.getValueSize(null);
520 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
521 getEncoder().writeRaw(encodedValueSize);
522 getEncoder().writeRaw(a.length);
523 underlyingEncoder.writeConstructor();
524 for(long b : a)
525 {
526 underlyingEncoder.writeValue(b);
527 }
528 }
529
530 override
531 public void writeValue(float[] a)
532 {
533 FloatType.FloatEncoding underlyingEncoder = getUnderlyingEncoding(a);
534 int encodedValueSize = 4 + underlyingEncoder.getConstructorSize() +
535 a.length * underlyingEncoder.getValueSize(null);
536 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
537 getEncoder().writeRaw(encodedValueSize);
538 getEncoder().writeRaw(a.length);
539 underlyingEncoder.writeConstructor();
540 for(float b : a)
541 {
542 underlyingEncoder.writeValue(b);
543 }
544 }
545
546 override
547 public void writeValue(double[] a)
548 {
549 DoubleType.DoubleEncoding underlyingEncoder = getUnderlyingEncoding(a);
550 int encodedValueSize = 4 + underlyingEncoder.getConstructorSize() +
551 a.length * underlyingEncoder.getValueSize(null);
552 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
553 getEncoder().writeRaw(encodedValueSize);
554 getEncoder().writeRaw(a.length);
555 underlyingEncoder.writeConstructor();
556 for(double b : a)
557 {
558 underlyingEncoder.writeValue(b);
559 }
560 }
561
562 override
563 public void writeValue(char[] a)
564 {
565 CharacterType.CharacterEncoding underlyingEncoder = getUnderlyingEncoding(a);
566 int encodedValueSize = 4 + underlyingEncoder.getConstructorSize() +
567 a.length * underlyingEncoder.getValueSize(null);
568 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
569 getEncoder().writeRaw(encodedValueSize);
570 getEncoder().writeRaw(a.length);
571 underlyingEncoder.writeConstructor();
572 for(char b : a)
573 {
574 underlyingEncoder.writeValue(b);
575 }
576 }
577
578 override
579 public void setValue(Object[] val, TypeEncoding encoder, int size)
580 {
581 _val = val;
582 _underlyingEncoder = encoder;
583 _size = size;
584 }
585
586 override
587 protected void writeEncodedValue(Object[] val)
588 {
589 TypeEncoding underlyingEncoder;
590
591 if(_val != val)
592 {
593 _val = val;
594 _underlyingEncoder = underlyingEncoder = calculateEncoder(val, getEncoder());
595 _size = calculateSize(val, underlyingEncoder);
596 }
597 else
598 {
599 underlyingEncoder = _underlyingEncoder;
600 }
601 getEncoder().writeRaw(val.length);
602 underlyingEncoder.writeConstructor();
603 for(Object o : val)
604 {
605 underlyingEncoder.writeValue(o);
606 }
607 }
608
609 override
610 protected int getEncodedValueSize(Object[] val)
611 {
612 if(_val != val)
613 {
614 _val = val;
615 _underlyingEncoder = calculateEncoder(val, getEncoder());
616 _size = calculateSize(val, _underlyingEncoder);
617 }
618 return 4 + _size;
619 }
620
621 override
622 public byte getEncodingCode()
623 {
624 return EncodingCodes.ARRAY32;
625 }
626
627 override
628 public ArrayType getType()
629 {
630 return ArrayType.this;
631 }
632
633 override
634 public bool encodesSuperset(TypeEncoding!(Object[]) encoding)
635 {
636 return getType() == encoding.getType();
637 }
638
639 override
640 public Object[] readValue()
641 {
642 DecoderImpl decoder = getDecoder();
643 int size = decoder.readRawInt();
644 int count = decoder.readRawInt();
645 return decodeArray(decoder, count);
646 }
647
648 override
649 public Object readValueArray()
650 {
651 DecoderImpl decoder = getDecoder();
652 int size = decoder.readRawInt();
653 int count = decoder.readRawInt();
654 return decodeArrayAsObject(decoder, count);
655 }
656
657 override
658 public void skipValue()
659 {
660 DecoderImpl decoder = getDecoder();
661 ReadableBuffer buffer = decoder.getBuffer();
662 int size = decoder.readRawInt();
663 buffer.position(buffer.position() + size);
664 }
665 }
666
667 private class ShortArrayEncoding
668 : SmallFloatingSizePrimitiveTypeEncoding!(Object[])
669 implements ArrayEncoding
670 {
671 private Object[] _val;
672 private TypeEncoding _underlyingEncoder;
673 private int _size;
674
675 ShortArrayEncoding(EncoderImpl encoder, DecoderImpl decoder)
676 {
677 super(encoder, decoder);
678 }
679
680 override
681 protected void writeSize(Object[] val)
682 {
683 int encodedValueSize = getEncodedValueSize(val);
684 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
685 getEncoder().writeRaw((byte) encodedValueSize);
686 }
687
688 override
689 public void writeValue(bool[] a)
690 {
691 BooleanType.BooleanEncoding underlyingEncoder = getUnderlyingEncoding(a);
692 int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
693 a.length * underlyingEncoder.getValueSize(null);
694 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
695 getEncoder().writeRaw((byte)encodedValueSize);
696 getEncoder().writeRaw((byte)a.length);
697 underlyingEncoder.writeConstructor();
698 for(bool b : a)
699 {
700 underlyingEncoder.writeValue(b);
701 }
702 }
703
704 override
705 public void writeValue(byte[] a)
706 {
707 ByteType.ByteEncoding underlyingEncoder = getUnderlyingEncoding(a);
708 int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
709 a.length * underlyingEncoder.getValueSize(null);
710 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
711 getEncoder().writeRaw((byte)encodedValueSize);
712 getEncoder().writeRaw((byte)a.length);
713 underlyingEncoder.writeConstructor();
714 for(byte b : a)
715 {
716 underlyingEncoder.writeValue(b);
717 }
718 }
719
720 override
721 public void writeValue(short[] a)
722 {
723 ShortType.ShortEncoding underlyingEncoder = getUnderlyingEncoding(a);
724 int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
725 a.length * underlyingEncoder.getValueSize(null);
726 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
727 getEncoder().writeRaw((byte)encodedValueSize);
728 getEncoder().writeRaw((byte)a.length);
729 underlyingEncoder.writeConstructor();
730 for(short b : a)
731 {
732 underlyingEncoder.writeValue(b);
733 }
734 }
735
736 override
737 public void writeValue(int[] a)
738 {
739 IntegerType.IntegerEncoding underlyingEncoder = getUnderlyingEncoding(a);
740 int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
741 a.length * underlyingEncoder.getValueSize(null);
742 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
743 getEncoder().writeRaw((byte)encodedValueSize);
744 getEncoder().writeRaw((byte)a.length);
745 underlyingEncoder.writeConstructor();
746 for(int b : a)
747 {
748 underlyingEncoder.writeValue(b);
749 }
750 }
751
752 override
753 public void writeValue(long[] a)
754 {
755 LongType.LongEncoding underlyingEncoder = getUnderlyingEncoding(a);
756 int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
757 a.length * underlyingEncoder.getValueSize(null);
758 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
759 getEncoder().writeRaw((byte)encodedValueSize);
760 getEncoder().writeRaw((byte)a.length);
761 underlyingEncoder.writeConstructor();
762 for(long b : a)
763 {
764 underlyingEncoder.writeValue(b);
765 }
766 }
767
768 override
769 public void writeValue(float[] a)
770 {
771 FloatType.FloatEncoding underlyingEncoder = getUnderlyingEncoding(a);
772 int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
773 a.length * underlyingEncoder.getValueSize(null);
774 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
775 getEncoder().writeRaw((byte)encodedValueSize);
776 getEncoder().writeRaw((byte)a.length);
777 underlyingEncoder.writeConstructor();
778 for(float b : a)
779 {
780 underlyingEncoder.writeValue(b);
781 }
782 }
783
784 override
785 public void writeValue(double[] a)
786 {
787 DoubleType.DoubleEncoding underlyingEncoder = getUnderlyingEncoding(a);
788 int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
789 a.length * underlyingEncoder.getValueSize(null);
790 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
791 getEncoder().writeRaw((byte)encodedValueSize);
792 getEncoder().writeRaw((byte)a.length);
793 underlyingEncoder.writeConstructor();
794 for(double b : a)
795 {
796 underlyingEncoder.writeValue(b);
797 }
798 }
799
800 override
801 public void writeValue(char[] a)
802 {
803 CharacterType.CharacterEncoding underlyingEncoder = getUnderlyingEncoding(a);
804 int encodedValueSize = 1 + underlyingEncoder.getConstructorSize() +
805 a.length * underlyingEncoder.getValueSize(null);
806 getEncoder().getBuffer().ensureRemaining(encodedValueSize);
807 getEncoder().writeRaw((byte)encodedValueSize);
808 getEncoder().writeRaw((byte)a.length);
809 underlyingEncoder.writeConstructor();
810 for(char b : a)
811 {
812 underlyingEncoder.writeValue(b);
813 }
814 }
815
816 override
817 public void setValue(Object[] val, TypeEncoding encoder, int size)
818 {
819 _val = val;
820 _underlyingEncoder = encoder;
821 _size = size;
822 }
823
824 override
825 protected void writeEncodedValue(Object[] val)
826 {
827 TypeEncoding underlyingEncoder;
828
829 if(_val != val)
830 {
831 _val = val;
832 _underlyingEncoder = underlyingEncoder = calculateEncoder(val, getEncoder());
833 _size = calculateSize(val, underlyingEncoder);
834 }
835 else
836 {
837 underlyingEncoder = _underlyingEncoder;
838 }
839 getEncoder().writeRaw((byte)val.length);
840 underlyingEncoder.writeConstructor();
841 for(Object o : val)
842 {
843 if(o.getClass().isArray() && o.getClass().getComponentType().isPrimitive())
844 {
845 ArrayEncoding arrayEncoding = (ArrayEncoding) underlyingEncoder;
846 ArrayType arrayType = (ArrayType) arrayEncoding.getType();
847
848 Class componentType = o.getClass().getComponentType();
849
850 if(componentType == Boolean.TYPE)
851 {
852 bool[] componentArray = (bool[]) o;
853 arrayEncoding.writeValue(componentArray);
854 }
855 else if(componentType == Byte.TYPE)
856 {
857 byte[] componentArray = (byte[]) o;
858 arrayEncoding.writeValue(componentArray);
859 }
860 else if(componentType == Short.TYPE)
861 {
862 short[] componentArray = (short[]) o;
863 arrayEncoding.writeValue(componentArray);
864 }
865 else if(componentType == Integer.TYPE)
866 {
867 int[] componentArray = (int[]) o;
868 arrayEncoding.writeValue(componentArray);
869 }
870 else if(componentType == Long.TYPE)
871 {
872 long[] componentArray = (long[]) o;
873 arrayEncoding.writeValue(componentArray);
874 }
875 else if(componentType == Float.TYPE)
876 {
877 float[] componentArray = (float[]) o;
878 arrayEncoding.writeValue(componentArray);
879 }
880 else if(componentType == Double.TYPE)
881 {
882 double[] componentArray = (double[]) o;
883 arrayEncoding.writeValue(componentArray);
884 }
885 else if(componentType == Character.TYPE)
886 {
887 char[] componentArray = (char[]) o;
888 arrayEncoding.writeValue(componentArray);
889 }
890 else
891 {
892 throw new IllegalArgumentException("Cannot encode arrays of type " ~ componentType.getName());
893 }
894 }
895 else
896 {
897 underlyingEncoder.writeValue(o);
898 }
899 }
900 }
901
902 override
903 protected int getEncodedValueSize(Object[] val)
904 {
905 if(_val != val)
906 {
907 _val = val;
908 _underlyingEncoder = calculateEncoder(val, getEncoder());
909 _size = calculateSize(val, _underlyingEncoder);
910 }
911 return 1 + _size;
912 }
913
914 override
915 public byte getEncodingCode()
916 {
917 return EncodingCodes.ARRAY8;
918 }
919
920 override
921 public ArrayType getType()
922 {
923 return ArrayType.this;
924 }
925
926 override
927 public bool encodesSuperset(TypeEncoding!(Object[]) encoding)
928 {
929 return getType() == encoding.getType();
930 }
931
932 override
933 public Object[] readValue()
934 {
935 DecoderImpl decoder = getDecoder();
936 int size = ((int)decoder.readRawByte()) & 0xFF;
937 int count = ((int)decoder.readRawByte()) & 0xFF;
938 return decodeArray(decoder, count);
939 }
940
941 override
942 public Object readValueArray()
943 {
944 DecoderImpl decoder = getDecoder();
945 int size = ((int)decoder.readRawByte()) & 0xFF;
946 int count = ((int)decoder.readRawByte()) & 0xFF;
947 return decodeArrayAsObject(decoder, count);
948 }
949
950 override
951 public void skipValue()
952 {
953 DecoderImpl decoder = getDecoder();
954 ReadableBuffer buffer = decoder.getBuffer();
955 int size = ((int)decoder.readRawByte()) & 0xFF;
956 buffer.position(buffer.position() + size);
957 }
958 }
959
960 private BooleanType.BooleanEncoding getUnderlyingEncoding(bool[] a)
961 {
962 if(a.length == 0)
963 {
964 return _boolType.getCanonicalEncoding();
965 }
966 else
967 {
968 bool val = a[0];
969 for(int i = 1; i < a.length; i++)
970 {
971 if(val != a[i])
972 {
973 return _boolType.getCanonicalEncoding();
974 }
975 }
976 return _boolType.getEncoding(val);
977 }
978 }
979
980 private ByteType.ByteEncoding getUnderlyingEncoding(byte[] a)
981 {
982 return _byteType.getCanonicalEncoding();
983 }
984
985 private ShortType.ShortEncoding getUnderlyingEncoding(short[] a)
986 {
987 return _shortType.getCanonicalEncoding();
988 }
989
990 private IntegerType.IntegerEncoding getUnderlyingEncoding(int[] a)
991 {
992 if(a.length == 0 || !allSmallInts(a))
993 {
994 return _integerType.getCanonicalEncoding();
995 }
996 else
997 {
998 return _integerType.getEncoding(a[0]);
999 }
1000 }
1001
1002 private LongType.LongEncoding getUnderlyingEncoding(long[] a)
1003 {
1004 if(a.length == 0 || !allSmallLongs(a))
1005 {
1006 return _longType.getCanonicalEncoding();
1007 }
1008 else
1009 {
1010 return _longType.getEncoding(a[0]);
1011 }
1012 }
1013
1014 private FloatType.FloatEncoding getUnderlyingEncoding(float[] a)
1015 {
1016 return _floatType.getCanonicalEncoding();
1017 }
1018
1019 private DoubleType.DoubleEncoding getUnderlyingEncoding(double[] a)
1020 {
1021 return _doubleType.getCanonicalEncoding();
1022 }
1023
1024 private CharacterType.CharacterEncoding getUnderlyingEncoding(char[] a)
1025 {
1026 return _characterType.getCanonicalEncoding();
1027 }
1028
1029 private static Object[] decodeArray(DecoderImpl decoder, int count)
1030 {
1031 TypeConstructor constructor = decoder.readConstructor(true);
1032 return decodeNonPrimitive(decoder, constructor, count);
1033 }
1034
1035 private static Object[] decodeNonPrimitive(DecoderImpl decoder,
1036 TypeConstructor constructor,
1037 int count)
1038 {
1039 if (count > decoder.getByteBufferRemaining()) {
1040 throw new IllegalArgumentException("Array element count "+count+" is specified to be greater than the amount of data available ("+
1041 decoder.getByteBufferRemaining()+")");
1042 }
1043
1044 if(constructor instanceof ArrayEncoding)
1045 {
1046 ArrayEncoding arrayEncoding = (ArrayEncoding) constructor;
1047
1048 Object[] array = new Object[count];
1049 for(int i = 0; i < count; i++)
1050 {
1051 array[i] = arrayEncoding.readValueArray();
1052 }
1053
1054 return array;
1055 }
1056 else
1057 {
1058 Object[] array = (Object[]) Array.newInstance(constructor.getTypeClass(), count);
1059
1060 for(int i = 0; i < count; i++)
1061 {
1062 array[i] = constructor.readValue();
1063 }
1064
1065 return array;
1066 }
1067 }
1068
1069 private static Object decodeArrayAsObject(DecoderImpl decoder, int count)
1070 {
1071 TypeConstructor constructor = decoder.readConstructor(true);
1072 if(constructor.encodesJavaPrimitive())
1073 {
1074 if (count > decoder.getByteBufferRemaining()) {
1075 throw new IllegalArgumentException("Array element count "+count+" is specified to be greater than the amount of data available ("+
1076 decoder.getByteBufferRemaining()+")");
1077 }
1078
1079 if(constructor instanceof BooleanType.BooleanEncoding)
1080 {
1081 return decodeBooleanArray((BooleanType.BooleanEncoding) constructor, count);
1082 }
1083 else if(constructor instanceof ByteType.ByteEncoding)
1084 {
1085 return decodeByteArray((ByteType.ByteEncoding)constructor, count);
1086 }
1087 else if(constructor instanceof ShortType.ShortEncoding)
1088 {
1089 return decodeShortArray((ShortType.ShortEncoding)constructor, count);
1090 }
1091 else if(constructor instanceof IntegerType.IntegerEncoding)
1092 {
1093 return decodeIntArray((IntegerType.IntegerEncoding)constructor, count);
1094 }
1095 else if(constructor instanceof LongType.LongEncoding)
1096 {
1097 return decodeLongArray((LongType.LongEncoding) constructor, count);
1098 }
1099 else if(constructor instanceof FloatType.FloatEncoding)
1100 {
1101 return decodeFloatArray((FloatType.FloatEncoding) constructor, count);
1102 }
1103 else if(constructor instanceof DoubleType.DoubleEncoding)
1104 {
1105 return decodeDoubleArray((DoubleType.DoubleEncoding)constructor, count);
1106 }
1107 else if(constructor instanceof CharacterType.CharacterEncoding)
1108 {
1109 return decodeCharArray((CharacterType.CharacterEncoding)constructor, count);
1110 }
1111 else
1112 {
1113 throw new ClassCastException("Unexpected class " ~ constructor.getClass().getName());
1114 }
1115 }
1116 else
1117 {
1118 return decodeNonPrimitive(decoder, constructor, count);
1119 }
1120 }
1121
1122 private static bool[] decodeBooleanArray(BooleanType.BooleanEncoding constructor, int count)
1123 {
1124 bool[] array = new bool[count];
1125
1126 for(int i = 0; i < count; i++)
1127 {
1128 array[i] = constructor.readPrimitiveValue();
1129 }
1130
1131 return array;
1132 }
1133
1134 private static byte[] decodeByteArray(ByteType.ByteEncoding constructor , int count)
1135 {
1136 byte[] array = new byte[count];
1137
1138 for(int i = 0; i < count; i++)
1139 {
1140 array[i] = constructor.readPrimitiveValue();
1141 }
1142
1143 return array;
1144 }
1145
1146 private static short[] decodeShortArray(ShortType.ShortEncoding constructor, int count)
1147 {
1148 short[] array = new short[count];
1149
1150 for(int i = 0; i < count; i++)
1151 {
1152 array[i] = constructor.readPrimitiveValue();
1153 }
1154
1155 return array;
1156 }
1157
1158 private static int[] decodeIntArray(IntegerType.IntegerEncoding constructor, int count)
1159 {
1160 int[] array = new int[count];
1161
1162 for(int i = 0; i < count; i++)
1163 {
1164 array[i] = constructor.readPrimitiveValue();
1165 }
1166
1167 return array;
1168 }
1169
1170 private static long[] decodeLongArray(LongType.LongEncoding constructor, int count)
1171 {
1172 long[] array = new long[count];
1173
1174 for(int i = 0; i < count; i++)
1175 {
1176 array[i] = constructor.readPrimitiveValue();
1177 }
1178
1179 return array;
1180 }
1181
1182 private static float[] decodeFloatArray(FloatType.FloatEncoding constructor, int count)
1183 {
1184 float[] array = new float[count];
1185
1186 for(int i = 0; i < count; i++)
1187 {
1188 array[i] = constructor.readPrimitiveValue();
1189 }
1190
1191 return array;
1192 }
1193
1194 private static double[] decodeDoubleArray(DoubleType.DoubleEncoding constructor, int count)
1195 {
1196 double[] array = new double[count];
1197
1198 for(int i = 0; i < count; i++)
1199 {
1200 array[i] = constructor.readPrimitiveValue();
1201 }
1202
1203 return array;
1204 }
1205
1206 private static char[] decodeCharArray(CharacterType.CharacterEncoding constructor, int count)
1207 {
1208 char[] array = new char[count];
1209
1210 for(int i = 0; i < count; i++)
1211 {
1212 array[i] = constructor.readPrimitiveValue();
1213 }
1214
1215 return array;
1216 }
1217 }
1218
1219 */