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 */