Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 24 additions & 16 deletions asn1-uper/src/main/java/net/gcdc/asn1/uper/EnumCoder.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,23 +64,31 @@ class EnumCoder implements Decoder, Encoder {
AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),
extraAnnotations);
UperEncoder.logger.debug("ENUM");
if (UperEncoder.hasExtensionMarker(annotations)) {
boolean extensionPresent = bitbuffer.get();
UperEncoder.logger.debug("with extension marker, {}", extensionPresent ? "present" : "absent");
if (extensionPresent) {
throw new UnsupportedOperationException(
"choice extension is not implemented yet");
T value = null;
if (UperEncoder.hasExtensionMarker(annotations)
&& bitbuffer.get()) { // extension present
UperEncoder.logger.debug("with extension marker, extension present");
boolean isGreaterThan64 = bitbuffer.get();
// The decoded value is discarded - no way to return an undefined enum value, just consuming the bits.
if (!isGreaterThan64) {
UperEncoder.decodeConstrainedInt(bitbuffer, UperEncoder.newRange(0, uintMax(6), false));
} else {
// We already consumed the bit, keep processing as if there were no extension.
int numOctets = (int) UperEncoder.decodeLengthDeterminant(bitbuffer);
UperEncoder.decodeConstrainedInt(bitbuffer, UperEncoder.newRange(0, uintMax(numOctets * 8), false));
}
} else {
T[] enumValues = classOfT.getEnumConstants();
int index = (int) UperEncoder.decodeConstrainedInt(bitbuffer,
UperEncoder.newRange(0, enumValues.length - 1, false));
if (index > enumValues.length - 1) { throw new IllegalArgumentException(
"decoded enum index " + index + " is larger than number of elements (0.."
+ enumValues.length + ") in " + classOfT.getName()); }
value = enumValues[index];
}
T[] enumValues = classOfT.getEnumConstants();
int index = (int) UperEncoder.decodeConstrainedInt(bitbuffer,
UperEncoder.newRange(0, enumValues.length - 1, false));
if (index > enumValues.length - 1) { throw new IllegalArgumentException(
"decoded enum index " + index + " is larger then number of elements (0.."
+ enumValues.length + ") in " + classOfT.getName()); }
T value = enumValues[index];
return value; }
return value;
}

}
private static int uintMax(int bits) {
return (int) Math.pow(2, bits) - 1;
}
}
37 changes: 37 additions & 0 deletions asn1-uper/src/test/java/net/gcdc/asn1/uper/EnumCoderTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package net.gcdc.asn1.uper;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import org.junit.Test;

import net.gcdc.asn1.datatypes.HasExtensionMarker;

public class EnumCoderTest {
@HasExtensionMarker
private enum ConstructedType {
CHOICE(1), SEQUENCE(2), SET(3), SEQUENCE_OF(4), SET_OF(5);

private final int value;

private ConstructedType(int value) {
this.value = value;
}
}

@Test
public void extensibleNoExt() {
assertEquals(ConstructedType.SEQUENCE,
UperEncoder.decode(new byte[] {0x10}, ConstructedType.class));
}

@Test
public void extensibleExtSmall() {
assertNull(UperEncoder.decode(new byte[] {(byte) 0xA9}, ConstructedType.class));
}

@Test
public void extensibleWithLength() {
assertNull(UperEncoder.decode(new byte[] {(byte) 0xC0, 0x50, 0x00}, ConstructedType.class));
}
}