Skip to content

Commit cfc207f

Browse files
authored
Merge pull request #9 from vp-elitnet/decode_ext_enum
Add support for extensible enum decoding
2 parents e2aed57 + 194de93 commit cfc207f

File tree

2 files changed

+61
-16
lines changed

2 files changed

+61
-16
lines changed

asn1-uper/src/main/java/net/gcdc/asn1/uper/EnumCoder.java

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,23 +64,31 @@ class EnumCoder implements Decoder, Encoder {
6464
AnnotationStore annotations = new AnnotationStore(classOfT.getAnnotations(),
6565
extraAnnotations);
6666
UperEncoder.logger.debug("ENUM");
67-
if (UperEncoder.hasExtensionMarker(annotations)) {
68-
boolean extensionPresent = bitbuffer.get();
69-
UperEncoder.logger.debug("with extension marker, {}", extensionPresent ? "present" : "absent");
70-
if (extensionPresent) {
71-
throw new UnsupportedOperationException(
72-
"choice extension is not implemented yet");
67+
T value = null;
68+
if (UperEncoder.hasExtensionMarker(annotations)
69+
&& bitbuffer.get()) { // extension present
70+
UperEncoder.logger.debug("with extension marker, extension present");
71+
boolean isGreaterThan64 = bitbuffer.get();
72+
// The decoded value is discarded - no way to return an undefined enum value, just consuming the bits.
73+
if (!isGreaterThan64) {
74+
UperEncoder.decodeConstrainedInt(bitbuffer, UperEncoder.newRange(0, uintMax(6), false));
7375
} else {
74-
// We already consumed the bit, keep processing as if there were no extension.
76+
int numOctets = (int) UperEncoder.decodeLengthDeterminant(bitbuffer);
77+
UperEncoder.decodeConstrainedInt(bitbuffer, UperEncoder.newRange(0, uintMax(numOctets * 8), false));
7578
}
79+
} else {
80+
T[] enumValues = classOfT.getEnumConstants();
81+
int index = (int) UperEncoder.decodeConstrainedInt(bitbuffer,
82+
UperEncoder.newRange(0, enumValues.length - 1, false));
83+
if (index > enumValues.length - 1) { throw new IllegalArgumentException(
84+
"decoded enum index " + index + " is larger than number of elements (0.."
85+
+ enumValues.length + ") in " + classOfT.getName()); }
86+
value = enumValues[index];
7687
}
77-
T[] enumValues = classOfT.getEnumConstants();
78-
int index = (int) UperEncoder.decodeConstrainedInt(bitbuffer,
79-
UperEncoder.newRange(0, enumValues.length - 1, false));
80-
if (index > enumValues.length - 1) { throw new IllegalArgumentException(
81-
"decoded enum index " + index + " is larger then number of elements (0.."
82-
+ enumValues.length + ") in " + classOfT.getName()); }
83-
T value = enumValues[index];
84-
return value; }
88+
return value;
89+
}
8590

86-
}
91+
private static int uintMax(int bits) {
92+
return (int) Math.pow(2, bits) - 1;
93+
}
94+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package net.gcdc.asn1.uper;
2+
3+
import static org.junit.Assert.assertEquals;
4+
import static org.junit.Assert.assertNull;
5+
6+
import org.junit.Test;
7+
8+
import net.gcdc.asn1.datatypes.HasExtensionMarker;
9+
10+
public class EnumCoderTest {
11+
@HasExtensionMarker
12+
private enum ConstructedType {
13+
CHOICE(1), SEQUENCE(2), SET(3), SEQUENCE_OF(4), SET_OF(5);
14+
15+
private final int value;
16+
17+
private ConstructedType(int value) {
18+
this.value = value;
19+
}
20+
}
21+
22+
@Test
23+
public void extensibleNoExt() {
24+
assertEquals(ConstructedType.SEQUENCE,
25+
UperEncoder.decode(new byte[] {0x10}, ConstructedType.class));
26+
}
27+
28+
@Test
29+
public void extensibleExtSmall() {
30+
assertNull(UperEncoder.decode(new byte[] {(byte) 0xA9}, ConstructedType.class));
31+
}
32+
33+
@Test
34+
public void extensibleWithLength() {
35+
assertNull(UperEncoder.decode(new byte[] {(byte) 0xC0, 0x50, 0x00}, ConstructedType.class));
36+
}
37+
}

0 commit comments

Comments
 (0)