@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) {
   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");
     }
   }
 }