@Override public <T> T decode(BitBuffer bitbuffer, Class<T> classOfT, Annotation[] extraAnnotations) { UperEncoder.logger.debug("BYTE"); return (T) new Byte( (byte) UperEncoder.decodeConstrainedInt(bitbuffer, UperEncoder.newRange(0, 255, false))); }
@Override public <T> void encode(BitBuffer bitbuffer, T obj, Annotation[] extraAnnotations) { UperEncoder.encodeConstrainedInt(bitbuffer, ((Byte) obj).byteValue() & 0xff, 0, 255); UperEncoder.logger.debug("BYTE {}", ((Byte) obj).byteValue()); }
@Override public <T> void encode(BitBuffer bitbuffer, T obj, Annotation[] extraAnnotations) throws Asn1EncodingException { Class<?> type = obj.getClass(); AnnotationStore annotations = new AnnotationStore(type.getAnnotations(), extraAnnotations); UperEncoder.logger.debug("SEQUENCE {}", type.getName()); Asn1ContainerFieldSorter sorter = new Asn1ContainerFieldSorter(type); try { if (UperEncoder.hasExtensionMarker(annotations)) { boolean extensionsPresent = !sorter.extensionFields.isEmpty() && UperEncoder.hasNonNullExtensions(obj, sorter); UperEncoder.logger.debug( "with extension marker, {} extensions, extensionBit: <{}>", extensionsPresent ? "with" : "without", extensionsPresent); bitbuffer.put(extensionsPresent); } // Bitmask for optional fields. for (Field f : sorter.optionalOrdinaryFields) { boolean fieldPresent = f.get(obj) != null; UperEncoder.logger.debug( "with optional field {} {}, presence encoded as bit <{}>", f.getName(), fieldPresent ? "present" : "absent", fieldPresent); bitbuffer.put(fieldPresent); // null means the field is absent. } // All ordinary fields (fields within extension root). for (Field f : sorter.ordinaryFields) { if ((UperEncoder.isMandatory(f) || f.get(obj) != null) && !UperEncoder.isTestInstrumentation(f)) { UperEncoder.logger.debug("Field : {}", f.getName()); try { UperEncoder.encode2(bitbuffer, f.get(obj), f.getAnnotations()); } catch (Asn1EncodingException e) { throw new Asn1EncodingException("." + f.getName(), e); } catch (IllegalArgumentException e) { throw new IllegalArgumentException("Illegal value for field " + f.getName(), e); } } } // Extension fields. if (UperEncoder.hasExtensionMarker(annotations) && !sorter.extensionFields.isEmpty() && UperEncoder.hasNonNullExtensions(obj, sorter)) { // Total extensions count. int numExtensions = sorter.extensionFields.size(); UperEncoder.logger.debug( "continuing sequence : {} extension(s) are present, encoding length determinant for them...", numExtensions); UperEncoder.encodeLengthOfBitmask(bitbuffer, numExtensions); // Bitmask for present extensions. for (Field f : sorter.extensionFields) { boolean fieldIsPresent = f.get(obj) != null; UperEncoder.logger.debug( "Extension {} is {}, presence encoded as <{}>", f.getName(), fieldIsPresent ? "present" : "absent", fieldIsPresent ? "1" : "0"); bitbuffer.put(fieldIsPresent); } // Values of extensions themselves. for (Field f : sorter.extensionFields) { if (f.get(obj) != null) { UperEncoder.logger.debug("Encoding extension field {}", f.getName()); try { UperEncoder.encodeAsOpenType(bitbuffer, f.get(obj), f.getAnnotations()); } catch (IllegalArgumentException e) { throw new IllegalArgumentException( "Illegal value for extension field " + f.getName(), e); } } } } } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalArgumentException("can't encode " + obj, e); } sorter.revertAccess(); }
@Override public <T> T decode(BitBuffer bitbuffer, Class<T> classOfT, Annotation[] extraAnnotations) { AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(), extraAnnotations); UperEncoder.logger.debug("SEQUENCE"); T result = UperEncoder.instantiate(classOfT); Asn1ContainerFieldSorter sorter = new Asn1ContainerFieldSorter(classOfT); boolean extensionPresent = false; if (UperEncoder.hasExtensionMarker(annotations)) { extensionPresent = bitbuffer.get(); UperEncoder.logger.debug( "with extension marker, extension {}", extensionPresent ? "present!" : "absent"); } // Bitmask for optional fields. Deque<Boolean> optionalFieldsMask = new ArrayDeque<>(sorter.optionalOrdinaryFields.size()); for (Field f : sorter.optionalOrdinaryFields) { optionalFieldsMask.add(bitbuffer.get()); UperEncoder.logger.debug( "with optional field {} {}", f.getName(), optionalFieldsMask.getLast() ? "present" : "absent"); } // All ordinary fields (fields within extension root). for (Field f : sorter.ordinaryFields) { if (!UperEncoder.isTestInstrumentation(f) && (UperEncoder.isMandatory(f) || (UperEncoder.isOptional(f) && optionalFieldsMask.pop()))) { UperEncoder.logger.debug("Field : {}", f.getName()); try { f.set(result, UperEncoder.decode2(bitbuffer, f.getType(), f.getAnnotations())); } catch (IllegalAccessException e) { throw new IllegalArgumentException( "can't access 'set method' for field " + f + " of class " + classOfT + " " + e, e); } } } // Extension fields. if (UperEncoder.hasExtensionMarker(annotations) && extensionPresent) { // Number of extensions. int numExtensions = (int) UperEncoder.decodeLengthOfBitmask(bitbuffer); UperEncoder.logger.debug("sequence has {} extension(s)", numExtensions); // Bitmask for extensions. boolean[] bitmaskValueIsPresent = new boolean[numExtensions]; for (int i = 0; i < numExtensions; i++) { bitmaskValueIsPresent[i] = bitbuffer.get(); UperEncoder.logger.debug( "extension {} is {}", i, bitmaskValueIsPresent[i] ? "present" : "absent"); } // Values. UperEncoder.logger.debug("decoding extensions values..."); for (int i = 0; i < numExtensions; i++) { UperEncoder.logger.debug( "sequence extension {} {}", i, bitmaskValueIsPresent[i] ? "present" : "absent"); if (bitmaskValueIsPresent[i]) { UperEncoder.logger.debug("decoding extension {}...", i); Field field = sorter.extensionFields.size() > i ? sorter.extensionFields.get(i) : null; Class<?> classOfElement = field != null ? field.getType() : null; try { Object decodedValue = UperEncoder.decodeAsOpenType(bitbuffer, classOfElement, field.getAnnotations()); if (field != null) { field.set(result, decodedValue); } } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalArgumentException("can't decode " + classOfT, e); } } } } sorter.revertAccess(); return result; }
@Override public <T> void encode(BitBuffer bitbuffer, T obj, Annotation[] extraAnnotations) { Class<?> type = obj.getClass(); AnnotationStore annotations = new AnnotationStore(type.getAnnotations(), extraAnnotations); if (!(obj instanceof Asn1VarSizeBitstring)) { if (UperEncoder.hasExtensionMarker(annotations)) { throw new UnsupportedOperationException("Bitstring with extensions is not implemented yet"); } FixedSize size = type.getAnnotation(FixedSize.class); int position = bitbuffer.position(); if (size != null) { Asn1ContainerFieldSorter sorter = new Asn1ContainerFieldSorter(type); if (sorter.ordinaryFields.size() != size.value()) { throw new AssertionError( "Declared size (" + size.value() + ") and number of fields (" + sorter.ordinaryFields.size() + ") do not match!"); } for (Field f : sorter.ordinaryFields) { try { bitbuffer.put(f.getBoolean(obj)); } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalArgumentException("can't encode" + obj, e); } } UperEncoder.logger.debug( "BITSTRING {}, encoded as <{}>", obj.getClass().getName(), bitbuffer.toBooleanStringFromPosition(position)); return; } else { throw new UnsupportedOperationException( "Bitstrings of variable size are not implemented yet"); } } else if (obj instanceof Asn1VarSizeBitstring) { int position = bitbuffer.position(); if (UperEncoder.hasExtensionMarker(annotations)) { throw new UnsupportedOperationException("Bitstring with extensions is not implemented yet"); } Asn1VarSizeBitstring bitstring = (Asn1VarSizeBitstring) obj; FixedSize fixedSize = annotations.getAnnotation(FixedSize.class); SizeRange sizeRange = annotations.getAnnotation(SizeRange.class); if (fixedSize != null) { for (int i = 0; i < fixedSize.value(); i++) { bitbuffer.put(bitstring.getBit(i)); } UperEncoder.logger.debug( "BITSTRING {}: {}", obj.getClass().getName(), bitbuffer.toBooleanStringFromPosition(position)); return; } else if (sizeRange != null) { int position1 = bitbuffer.position(); UperEncoder.encodeConstrainedInt( bitbuffer, bitstring.size(), sizeRange.minValue(), sizeRange.maxValue()); int position2 = bitbuffer.position(); for (int i = 0; i < bitstring.size(); i++) { bitbuffer.put(bitstring.getBit(i)); } UperEncoder.logger.debug( "BITSTRING {} size {}: {}", obj.getClass().getName(), bitbuffer.toBooleanString(position1, position2 - position1), bitbuffer.toBooleanStringFromPosition(position2)); return; } else { throw new IllegalArgumentException("Both SizeRange and FixedSize are null"); } } }
@Override public <T> T decode(BitBuffer bitbuffer, Class<T> classOfT, Annotation[] extraAnnotations) { AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(), extraAnnotations); if (!Asn1VarSizeBitstring.class.isAssignableFrom(classOfT)) { UperEncoder.logger.debug("Bitlist(fixed-size, all-named)"); FixedSize fixedSize = annotations.getAnnotation(FixedSize.class); if (fixedSize == null) { throw new UnsupportedOperationException( "bitstrings of non-fixed size that do not extend Asn1VarSizeBitstring are not supported yet"); } Asn1ContainerFieldSorter sorter = new Asn1ContainerFieldSorter(classOfT); if (fixedSize.value() != sorter.ordinaryFields.size()) { throw new IllegalArgumentException( "Fixed size annotation " + fixedSize.value() + " does not match the number of fields " + sorter.ordinaryFields.size() + " in " + classOfT.getName()); } if (UperEncoder.hasExtensionMarker(annotations)) { boolean extensionPresent = bitbuffer.get(); if (extensionPresent) { throw new UnsupportedOperationException( "extensions in fixed-size bitlist are not supported yet"); } } T result = UperEncoder.instantiate(classOfT); for (Field f : sorter.ordinaryFields) { boolean value = bitbuffer.get(); UperEncoder.logger.debug("Field {} set to {}", f.getName(), value); try { f.set(result, value); } catch (IllegalArgumentException | IllegalAccessException e) { throw new IllegalArgumentException("can't decode " + classOfT, e); } } return result; } else { UperEncoder.logger.debug("Bitlist(var-size)"); FixedSize fixedSize = annotations.getAnnotation(FixedSize.class); SizeRange sizeRange = annotations.getAnnotation(SizeRange.class); // We use reflection here to access protected method of Asn1VarSizeBitstring. // Alternative would be to mandate BitSet constructors for all subclasses of // Asn1VarSizeBitstring. Method setBitMethod; try { setBitMethod = Asn1VarSizeBitstring.class.getDeclaredMethod("setBit", int.class, boolean.class); setBitMethod.setAccessible(true); } catch (SecurityException | NoSuchMethodException e) { throw new AssertionError("Can't find/access setBit " + e); } long size = (fixedSize != null) ? fixedSize.value() : (sizeRange != null) ? UperEncoder.decodeConstrainedInt( bitbuffer, UperEncoder.intRangeFromSizeRange(sizeRange)) : badSize(classOfT); T result = UperEncoder.instantiate(classOfT); for (int i = 0; i < size; i++) { try { setBitMethod.invoke(result, i, bitbuffer.get()); } catch (IllegalArgumentException | InvocationTargetException | IllegalAccessException e) { throw new IllegalArgumentException("Can't invoke setBit", e); } } return result; } }