@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> 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;
   }
 }