aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Scull <ascull@google.com>2023-09-16 21:34:41 +0000
committerAndrew Scull <ascull@google.com>2023-09-17 15:51:09 +0000
commitcfa8759c7e3d29aa6873873d34eeb5b54ea6a86b (patch)
tree1b75cefeb7703caff9dffb5c2877c869d511df77
parent09ccb20563eec641376f3f7d1fbe88db721b504b (diff)
downloadcbor-java-cfa8759c7e3d29aa6873873d34eeb5b54ea6a86b.tar.gz
Refactor the encoder implementation into CborOutputStream
Merge the encoder implementation into a single class rather than having to instantiate 11 classes that hold the same state. This class uses an OutputStream abstraction for outputing CBOR items to an underlying stream. The CborReader interface is unchanged and the CborOutputStream is not made part of the library's public interface.
-rw-r--r--src/main/java/co/nstant/in/cbor/CborEncoder.java74
-rw-r--r--src/main/java/co/nstant/in/cbor/CborOutputStream.java422
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/AbstractEncoder.java109
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/ArrayEncoder.java31
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/ByteStringEncoder.java33
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/DoublePrecisionFloatEncoder.java23
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/HalfPrecisionFloatEncoder.java56
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/MapEncoder.java116
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/NegativeIntegerEncoder.java24
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/SinglePrecisionFloatEncoder.java22
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/SpecialEncoder.java68
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/TagEncoder.java21
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/UnicodeStringEncoder.java36
-rw-r--r--src/main/java/co/nstant/in/cbor/encoder/UnsignedIntegerEncoder.java21
14 files changed, 432 insertions, 624 deletions
diff --git a/src/main/java/co/nstant/in/cbor/CborEncoder.java b/src/main/java/co/nstant/in/cbor/CborEncoder.java
index 241cbd4..3f208c4 100644
--- a/src/main/java/co/nstant/in/cbor/CborEncoder.java
+++ b/src/main/java/co/nstant/in/cbor/CborEncoder.java
@@ -1,17 +1,10 @@
package co.nstant.in.cbor;
+import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import java.util.Objects;
-import co.nstant.in.cbor.encoder.ArrayEncoder;
-import co.nstant.in.cbor.encoder.ByteStringEncoder;
-import co.nstant.in.cbor.encoder.MapEncoder;
-import co.nstant.in.cbor.encoder.NegativeIntegerEncoder;
-import co.nstant.in.cbor.encoder.SpecialEncoder;
-import co.nstant.in.cbor.encoder.TagEncoder;
-import co.nstant.in.cbor.encoder.UnicodeStringEncoder;
-import co.nstant.in.cbor.encoder.UnsignedIntegerEncoder;
import co.nstant.in.cbor.model.Array;
import co.nstant.in.cbor.model.ByteString;
import co.nstant.in.cbor.model.DataItem;
@@ -28,32 +21,17 @@ import co.nstant.in.cbor.model.UnsignedInteger;
*/
public class CborEncoder {
- private final UnsignedIntegerEncoder unsignedIntegerEncoder;
- private final NegativeIntegerEncoder negativeIntegerEncoder;
- private final ByteStringEncoder byteStringEncoder;
- private final UnicodeStringEncoder unicodeStringEncoder;
- private final ArrayEncoder arrayEncoder;
- private final MapEncoder mapEncoder;
- private final TagEncoder tagEncoder;
- private final SpecialEncoder specialEncoder;
- private boolean canonical = true;
+ private CborOutputStream cborOutputStream;
/**
* Initialize a new encoder which writes the binary encoded data to an
* {@link OutputStream}.
- *
+ *
* @param outputStream the {@link OutputStream} to write the encoded data to
*/
public CborEncoder(OutputStream outputStream) {
Objects.requireNonNull(outputStream);
- unsignedIntegerEncoder = new UnsignedIntegerEncoder(this, outputStream);
- negativeIntegerEncoder = new NegativeIntegerEncoder(this, outputStream);
- byteStringEncoder = new ByteStringEncoder(this, outputStream);
- unicodeStringEncoder = new UnicodeStringEncoder(this, outputStream);
- arrayEncoder = new ArrayEncoder(this, outputStream);
- mapEncoder = new MapEncoder(this, outputStream);
- tagEncoder = new TagEncoder(this, outputStream);
- specialEncoder = new SpecialEncoder(this, outputStream);
+ cborOutputStream = new CborOutputStream(outputStream);
}
/**
@@ -78,51 +56,19 @@ public class CborEncoder {
* an problem with the {@link OutputStream}.
*/
public void encode(DataItem dataItem) throws CborException {
- if (dataItem == null) {
- dataItem = SimpleValue.NULL;
- }
-
- if (dataItem.hasTag()) {
- Tag tagDi = dataItem.getTag();
- encode(tagDi);
- }
-
- switch (dataItem.getMajorType()) {
- case UNSIGNED_INTEGER:
- unsignedIntegerEncoder.encode((UnsignedInteger) dataItem);
- break;
- case NEGATIVE_INTEGER:
- negativeIntegerEncoder.encode((NegativeInteger) dataItem);
- break;
- case BYTE_STRING:
- byteStringEncoder.encode((ByteString) dataItem);
- break;
- case UNICODE_STRING:
- unicodeStringEncoder.encode((UnicodeString) dataItem);
- break;
- case ARRAY:
- arrayEncoder.encode((Array) dataItem);
- break;
- case MAP:
- mapEncoder.encode((Map) dataItem);
- break;
- case SPECIAL:
- specialEncoder.encode((Special) dataItem);
- break;
- case TAG:
- tagEncoder.encode((Tag) dataItem);
- break;
- default:
- throw new AssertionError("Unknown major type");
+ try {
+ cborOutputStream.writeDataItem(dataItem);
+ } catch (IOException ioException) {
+ throw new CborException(ioException);
}
}
public boolean isCanonical() {
- return canonical;
+ return cborOutputStream.isCanonical();
}
public CborEncoder nonCanonical() {
- canonical = false;
+ cborOutputStream.setCanonical(false);
return this;
}
diff --git a/src/main/java/co/nstant/in/cbor/CborOutputStream.java b/src/main/java/co/nstant/in/cbor/CborOutputStream.java
new file mode 100644
index 0000000..deb5e3a
--- /dev/null
+++ b/src/main/java/co/nstant/in/cbor/CborOutputStream.java
@@ -0,0 +1,422 @@
+package co.nstant.in.cbor;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.TreeMap;
+
+import co.nstant.in.cbor.model.AdditionalInformation;
+import co.nstant.in.cbor.model.Array;
+import co.nstant.in.cbor.model.ByteString;
+import co.nstant.in.cbor.model.DataItem;
+import co.nstant.in.cbor.model.DoublePrecisionFloat;
+import co.nstant.in.cbor.model.HalfPrecisionFloat;
+import co.nstant.in.cbor.model.MajorType;
+import co.nstant.in.cbor.model.Map;
+import co.nstant.in.cbor.model.NegativeInteger;
+import co.nstant.in.cbor.model.SimpleValue;
+import co.nstant.in.cbor.model.SimpleValueType;
+import co.nstant.in.cbor.model.SinglePrecisionFloat;
+import co.nstant.in.cbor.model.Special;
+import co.nstant.in.cbor.model.Tag;
+import co.nstant.in.cbor.model.UnicodeString;
+import co.nstant.in.cbor.model.UnsignedInteger;
+
+class CborOutputStream extends OutputStream {
+
+ private static final BigInteger MINUS_ONE = BigInteger.valueOf(-1);
+ private static final BigInteger UINT64_MAX_PLUS_ONE = new BigInteger("18446744073709551616");
+
+ private final OutputStream outputStream;
+ private boolean canonical = true;
+
+ public CborOutputStream(OutputStream outputStream) {
+ this.outputStream = outputStream;
+ }
+
+ public boolean isCanonical() {
+ return canonical;
+ }
+
+ public void setCanonical(boolean canonical) {
+ this.canonical = canonical;
+ }
+
+ public void writeDataItem(DataItem dataItem) throws IOException {
+ if (dataItem == null) {
+ dataItem = SimpleValue.NULL;
+ }
+
+ if (dataItem.hasTag()) {
+ writeDataItem(dataItem.getTag());
+ }
+
+ switch (dataItem.getMajorType()) {
+ case UNSIGNED_INTEGER:
+ writeUnsignedInteger((UnsignedInteger) dataItem);
+ break;
+ case NEGATIVE_INTEGER:
+ writeNegativeInteger((NegativeInteger) dataItem);
+ break;
+ case BYTE_STRING:
+ writeByteString((ByteString) dataItem);
+ break;
+ case UNICODE_STRING:
+ writeUnicodeString((UnicodeString) dataItem);
+ break;
+ case ARRAY:
+ writeArray((Array) dataItem);
+ break;
+ case MAP:
+ writeMap((Map) dataItem);
+ break;
+ case SPECIAL:
+ writeSpecial((Special) dataItem);
+ break;
+ case TAG:
+ writeTag((Tag) dataItem);
+ break;
+ default:
+ throw new AssertionError("Unknown major type");
+ }
+ }
+
+ private void writeUnsignedInteger(UnsignedInteger dataItem) throws IOException {
+ writeType(MajorType.UNSIGNED_INTEGER, dataItem.getValue());
+ }
+
+ private void writeNegativeInteger(NegativeInteger dataItem) throws IOException {
+ writeType(MajorType.NEGATIVE_INTEGER, MINUS_ONE.subtract(dataItem.getValue()).abs());
+ }
+
+ private void writeByteString(ByteString byteString) throws IOException {
+ byte[] bytes = byteString.getBytes();
+ if (byteString.isChunked()) {
+ writeIndefiniteLengthType(MajorType.BYTE_STRING);
+ if (bytes == null) {
+ return;
+ }
+ } else if (bytes == null) {
+ writeSpecial(SimpleValue.NULL);
+ return;
+ }
+ writeType(MajorType.BYTE_STRING, bytes.length);
+ write(bytes);
+ }
+
+ private void writeUnicodeString(UnicodeString dataItem) throws IOException {
+ String string = dataItem.getString();
+ if (dataItem.isChunked()) {
+ writeIndefiniteLengthType(MajorType.UNICODE_STRING);
+ if (string == null) {
+ return;
+ }
+ } else if (string == null) {
+ writeSpecial(SimpleValue.NULL);
+ return;
+ }
+ byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
+ writeType(MajorType.UNICODE_STRING, bytes.length);
+ write(bytes);
+ }
+
+ private void writeArray(Array array) throws IOException {
+ List<DataItem> dataItems = array.getDataItems();
+ if (array.isChunked()) {
+ writeIndefiniteLengthType(MajorType.ARRAY);
+ } else {
+ writeType(MajorType.ARRAY, dataItems.size());
+ }
+ for (DataItem dataItem : dataItems) {
+ writeDataItem(dataItem);
+ }
+ }
+
+ private void writeMap(Map map) throws IOException {
+ Collection<DataItem> keys = map.getKeys();
+
+ if (map.isChunked()) {
+ writeIndefiniteLengthType(MajorType.MAP);
+ } else {
+ writeType(MajorType.MAP, keys.size());
+ }
+
+ if (keys.isEmpty()) {
+ return;
+ }
+
+ if (map.isChunked()) {
+ writeNonCanonicalMap(map);
+ writeSpecial(SimpleValue.BREAK);
+ } else {
+ if (canonical) {
+ writeCanonicalMap(map);
+ } else {
+ writeNonCanonicalMap(map);
+ }
+ }
+ }
+
+ private void writeNonCanonicalMap(Map map) throws IOException {
+ for (DataItem key : map.getKeys()) {
+ writeDataItem(key);
+ writeDataItem(map.get(key));
+ }
+ }
+
+ /**
+ * Writes the map in the canonical CBOR format.
+ *
+ * <p>From <a href="https://tools.ietf.org/html/rfc7049#section-3.9">RFC 7049</a>:
+ *
+ * <p>The keys in every map must be sorted lowest value to highest. Sorting is performed on the
+ * bytes of the representation of the key data items without paying attention to the 3/5 bit
+ * splitting for major types. (Note that this rule allows maps that have keys of different
+ * types, even though that is probably a bad practice that could lead to errors in some
+ * canonicalization implementations.) The sorting rules are:
+ *
+ * <p>If two keys have different lengths, the shorter one sorts earlier;
+ *
+ * <p>If two keys have the same length, the one with the lower value in (byte-wise) lexical order
+ * sorts earlier.
+ */
+ private void writeCanonicalMap(Map map) throws IOException {
+ TreeMap<byte[], byte[]> sortedMap = new TreeMap<>(new Comparator<byte[]>() {
+
+ @Override
+ public int compare(byte[] o1, byte[] o2) {
+ if (o1.length < o2.length) {
+ return -1;
+ }
+ if (o1.length > o2.length) {
+ return 1;
+ }
+ for (int i = 0; i < o1.length; i++) {
+ if (o1[i] < o2[i]) {
+ return -1;
+ }
+ if (o1[i] > o2[i]) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+
+ });
+
+ ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+ CborOutputStream cborOutputStream = new CborOutputStream(byteArrayOutputStream);
+ for (DataItem key : map.getKeys()) {
+ // Key
+ cborOutputStream.writeDataItem(key);
+ byte[] keyBytes = byteArrayOutputStream.toByteArray();
+ byteArrayOutputStream.reset();
+ // Value
+ cborOutputStream.writeDataItem(map.get(key));
+ byte[] valueBytes = byteArrayOutputStream.toByteArray();
+ byteArrayOutputStream.reset();
+ sortedMap.put(keyBytes, valueBytes);
+ }
+ for (java.util.Map.Entry<byte[], byte[]> entry : sortedMap.entrySet()) {
+ write(entry.getKey());
+ write(entry.getValue());
+ }
+ }
+
+ void writeSpecial(Special dataItem) throws IOException{
+ switch (dataItem.getSpecialType()) {
+ case BREAK:
+ write((7 << 5) | 31);
+ break;
+ case SIMPLE_VALUE:
+ SimpleValue simpleValue = (SimpleValue) dataItem;
+ switch (simpleValue.getSimpleValueType()) {
+ case FALSE:
+ case NULL:
+ case TRUE:
+ case UNDEFINED:
+ SimpleValueType type = simpleValue.getSimpleValueType();
+ write((7 << 5) | type.getValue());
+ break;
+ case UNALLOCATED:
+ write((7 << 5) | simpleValue.getValue());
+ break;
+ case RESERVED:
+ break;
+ }
+ break;
+ case IEEE_754_HALF_PRECISION_FLOAT:
+ writeHalfPrecisionFloat((HalfPrecisionFloat) dataItem);
+ break;
+ case IEEE_754_SINGLE_PRECISION_FLOAT:
+ writeSinglePrecisionFloat((SinglePrecisionFloat) dataItem);
+ break;
+ case IEEE_754_DOUBLE_PRECISION_FLOAT:
+ writeDoublePrecisionFloat((DoublePrecisionFloat) dataItem);
+ break;
+ case SIMPLE_VALUE_NEXT_BYTE:
+ SimpleValue simpleValueNextByte = (SimpleValue) dataItem;
+ writeBytes((byte) ((7 << 5) | 24), (byte) simpleValueNextByte.getValue());
+ break;
+ default:
+ throw new AssertionError("Unknown special value type");
+ }
+ }
+
+ private void writeHalfPrecisionFloat(HalfPrecisionFloat dataItem) throws IOException {
+ int bits = fromFloat(dataItem.getValue());
+ writeBytes((byte) ((7 << 5) | 25), (byte) ((bits >> 8) & 0xFF), (byte) ((bits >> 0) & 0xFF));
+ }
+
+ /**
+ * @param fval the float value
+ * @return all higher 16 bits as 0 for all results
+ * @see <a href="http://stackoverflow.com/a/6162687">Stack Overflow</a>
+ */
+ private static int fromFloat(float fval) {
+ int fbits = Float.floatToIntBits(fval);
+ int sign = fbits >>> 16 & 0x8000; // sign only
+ int val = 0x1000 + fbits & 0x7fffffff; // rounded value
+
+ if (val >= 0x47800000) // might be or become NaN/Inf
+ { // avoid Inf due to rounding
+ if ((fbits & 0x7fffffff) >= 0x47800000) { // is or must become
+ // NaN/Inf
+ if (val < 0x7f800000) {// was value but too large
+ return sign | 0x7c00; // make it +/-Inf
+ }
+ return sign | 0x7c00 | // remains +/-Inf or NaN
+ (fbits & 0x007fffff) >>> 13; // keep NaN (and
+ // Inf) bits
+ }
+ return sign | 0x7bff; // unrounded not quite Inf
+ }
+ if (val >= 0x38800000) { // remains normalized value
+ return sign | val - 0x38000000 >>> 13; // exp - 127 + 15
+ }
+ if (val < 0x33000000) { // too small for subnormal
+ return sign; // becomes +/-0
+ }
+ val = (fbits & 0x7fffffff) >>> 23; // tmp exp for subnormal calc
+ return sign | ((fbits & 0x7fffff | 0x800000) // add subnormal bit
+ + (0x800000 >>> val - 102) // round depending on cut off
+ >>> 126 - val); // div by 2^(1-(exp-127+15)) and >> 13 | exp=0
+ }
+
+ public void writeSinglePrecisionFloat(SinglePrecisionFloat dataItem) throws IOException {
+ int bits = Float.floatToRawIntBits(dataItem.getValue());
+ writeBytes((byte) ((7 << 5) | 26), (byte) ((bits >> 24) & 0xFF), (byte) ((bits >> 16) & 0xFF),
+ (byte) ((bits >> 8) & 0xFF), (byte) ((bits >> 0) & 0xFF));
+ }
+
+ public void writeDoublePrecisionFloat(DoublePrecisionFloat dataItem) throws IOException {
+ long bits = Double.doubleToRawLongBits(dataItem.getValue());
+ writeBytes((byte) ((7 << 5) | 27), (byte) ((bits >> 56) & 0xFF), (byte) ((bits >> 48) & 0xFF),
+ (byte) ((bits >> 40) & 0xFF), (byte) ((bits >> 32) & 0xFF), (byte) ((bits >> 24) & 0xFF),
+ (byte) ((bits >> 16) & 0xFF), (byte) ((bits >> 8) & 0xFF), (byte) ((bits >> 0) & 0xFF));
+ }
+
+ private void writeTag(Tag tag) throws IOException {
+ writeType(MajorType.TAG, tag.getValue());
+ }
+
+ private void writeIndefiniteLengthType(MajorType majorType) throws IOException {
+ int symbol = majorType.getValue() << 5;
+ symbol |= AdditionalInformation.INDEFINITE.getValue();
+ outputStream.write(symbol);
+ }
+
+ private void writeType(MajorType majorType, long length) throws IOException {
+ int symbol = majorType.getValue() << 5;
+ if (length <= 23L) {
+ write((byte) (symbol | length));
+ } else if (length <= 255L) {
+ symbol |= AdditionalInformation.ONE_BYTE.getValue();
+ writeBytes((byte) symbol, (byte) length);
+ } else if (length <= 65535L) {
+ symbol |= AdditionalInformation.TWO_BYTES.getValue();
+ writeBytes((byte) symbol, (byte) (length >> 8), (byte) (length & 0xFF));
+ } else if (length <= 4294967295L) {
+ symbol |= AdditionalInformation.FOUR_BYTES.getValue();
+ writeBytes((byte) symbol, (byte) ((length >> 24) & 0xFF), (byte) ((length >> 16) & 0xFF),
+ (byte) ((length >> 8) & 0xFF), (byte) (length & 0xFF));
+ } else {
+ symbol |= AdditionalInformation.EIGHT_BYTES.getValue();
+ writeBytes((byte) symbol, (byte) ((length >> 56) & 0xFF), (byte) ((length >> 48) & 0xFF),
+ (byte) ((length >> 40) & 0xFF), (byte) ((length >> 32) & 0xFF), (byte) ((length >> 24) & 0xFF),
+ (byte) ((length >> 16) & 0xFF), (byte) ((length >> 8) & 0xFF), (byte) (length & 0xFF));
+ }
+ }
+
+ private void writeType(MajorType majorType, BigInteger length) throws IOException {
+ boolean negative = majorType == MajorType.NEGATIVE_INTEGER;
+ int symbol = majorType.getValue() << 5;
+ if (length.compareTo(BigInteger.valueOf(24)) < 0) {
+ write(symbol | length.intValue());
+ } else if (length.compareTo(BigInteger.valueOf(256)) < 0) {
+ symbol |= AdditionalInformation.ONE_BYTE.getValue();
+ writeBytes((byte) symbol, (byte) length.intValue());
+ } else if (length.compareTo(BigInteger.valueOf(65536L)) < 0) {
+ symbol |= AdditionalInformation.TWO_BYTES.getValue();
+ long twoByteValue = length.longValue();
+ writeBytes((byte) symbol, (byte) (twoByteValue >> 8), (byte) (twoByteValue & 0xFF));
+ } else if (length.compareTo(BigInteger.valueOf(4294967296L)) < 0) {
+ symbol |= AdditionalInformation.FOUR_BYTES.getValue();
+ long fourByteValue = length.longValue();
+ writeBytes((byte) symbol, (byte) ((fourByteValue >> 24) & 0xFF), (byte) ((fourByteValue >> 16) & 0xFF),
+ (byte) ((fourByteValue >> 8) & 0xFF), (byte) (fourByteValue & 0xFF));
+ } else if (length.compareTo(UINT64_MAX_PLUS_ONE) < 0) {
+ symbol |= AdditionalInformation.EIGHT_BYTES.getValue();
+ BigInteger mask = BigInteger.valueOf(0xFF);
+ writeBytes((byte) symbol, length.shiftRight(56).and(mask).byteValue(),
+ length.shiftRight(48).and(mask).byteValue(), length.shiftRight(40).and(mask).byteValue(),
+ length.shiftRight(32).and(mask).byteValue(), length.shiftRight(24).and(mask).byteValue(),
+ length.shiftRight(16).and(mask).byteValue(), length.shiftRight(8).and(mask).byteValue(),
+ length.and(mask).byteValue());
+ } else {
+ if (negative) {
+ writeType(MajorType.TAG, 3);
+ } else {
+ writeType(MajorType.TAG, 2);
+ }
+ byte[] bytes = length.toByteArray();
+ writeType(MajorType.BYTE_STRING, bytes.length);
+ write(bytes);
+ }
+ }
+
+ private void writeBytes(byte... bytes) throws IOException {
+ outputStream.write(bytes);
+ }
+
+ @Override
+ public void write(int b) throws IOException {
+ outputStream.write(b);
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ outputStream.write(b);
+ }
+
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+ outputStream.write(b, off, len);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ outputStream.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ outputStream.close();
+ }
+
+}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/AbstractEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/AbstractEncoder.java
deleted file mode 100644
index 25d0d19..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/AbstractEncoder.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.math.BigInteger;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.AdditionalInformation;
-import co.nstant.in.cbor.model.ByteString;
-import co.nstant.in.cbor.model.MajorType;
-import co.nstant.in.cbor.model.Tag;
-
-public abstract class AbstractEncoder<T> {
-
- private final OutputStream outputStream;
- protected final CborEncoder encoder;
-
- public AbstractEncoder(CborEncoder encoder, OutputStream outputStream) {
- this.encoder = encoder;
- this.outputStream = outputStream;
- }
-
- public abstract void encode(T dataItem) throws CborException;
-
- protected void encodeTypeChunked(MajorType majorType) throws CborException {
- int symbol = majorType.getValue() << 5;
- symbol |= AdditionalInformation.INDEFINITE.getValue();
- try {
- outputStream.write(symbol);
- } catch (IOException ioException) {
- throw new CborException(ioException);
- }
- }
-
- protected void encodeTypeAndLength(MajorType majorType, long length) throws CborException {
- int symbol = majorType.getValue() << 5;
- if (length <= 23L) {
- write((byte) (symbol | length));
- } else if (length <= 255L) {
- symbol |= AdditionalInformation.ONE_BYTE.getValue();
- write((byte) symbol, (byte) length);
- } else if (length <= 65535L) {
- symbol |= AdditionalInformation.TWO_BYTES.getValue();
- write((byte) symbol, (byte) (length >> 8), (byte) (length & 0xFF));
- } else if (length <= 4294967295L) {
- symbol |= AdditionalInformation.FOUR_BYTES.getValue();
- write((byte) symbol, (byte) ((length >> 24) & 0xFF), (byte) ((length >> 16) & 0xFF),
- (byte) ((length >> 8) & 0xFF), (byte) (length & 0xFF));
- } else {
- symbol |= AdditionalInformation.EIGHT_BYTES.getValue();
- write((byte) symbol, (byte) ((length >> 56) & 0xFF), (byte) ((length >> 48) & 0xFF),
- (byte) ((length >> 40) & 0xFF), (byte) ((length >> 32) & 0xFF), (byte) ((length >> 24) & 0xFF),
- (byte) ((length >> 16) & 0xFF), (byte) ((length >> 8) & 0xFF), (byte) (length & 0xFF));
- }
- }
-
- protected void encodeTypeAndLength(MajorType majorType, BigInteger length) throws CborException {
- boolean negative = majorType == MajorType.NEGATIVE_INTEGER;
- int symbol = majorType.getValue() << 5;
- if (length.compareTo(BigInteger.valueOf(24)) < 0) {
- write(symbol | length.intValue());
- } else if (length.compareTo(BigInteger.valueOf(256)) < 0) {
- symbol |= AdditionalInformation.ONE_BYTE.getValue();
- write((byte) symbol, (byte) length.intValue());
- } else if (length.compareTo(BigInteger.valueOf(65536L)) < 0) {
- symbol |= AdditionalInformation.TWO_BYTES.getValue();
- long twoByteValue = length.longValue();
- write((byte) symbol, (byte) (twoByteValue >> 8), (byte) (twoByteValue & 0xFF));
- } else if (length.compareTo(BigInteger.valueOf(4294967296L)) < 0) {
- symbol |= AdditionalInformation.FOUR_BYTES.getValue();
- long fourByteValue = length.longValue();
- write((byte) symbol, (byte) ((fourByteValue >> 24) & 0xFF), (byte) ((fourByteValue >> 16) & 0xFF),
- (byte) ((fourByteValue >> 8) & 0xFF), (byte) (fourByteValue & 0xFF));
- } else if (length.compareTo(new BigInteger("18446744073709551616")) < 0) {
- symbol |= AdditionalInformation.EIGHT_BYTES.getValue();
- BigInteger mask = BigInteger.valueOf(0xFF);
- write((byte) symbol, length.shiftRight(56).and(mask).byteValue(),
- length.shiftRight(48).and(mask).byteValue(), length.shiftRight(40).and(mask).byteValue(),
- length.shiftRight(32).and(mask).byteValue(), length.shiftRight(24).and(mask).byteValue(),
- length.shiftRight(16).and(mask).byteValue(), length.shiftRight(8).and(mask).byteValue(),
- length.and(mask).byteValue());
- } else {
- if (negative) {
- encoder.encode(new Tag(3));
- } else {
- encoder.encode(new Tag(2));
- }
- encoder.encode(new ByteString(length.toByteArray()));
- }
- }
-
- protected void write(int b) throws CborException {
- try {
- outputStream.write(b);
- } catch (IOException ioException) {
- throw new CborException(ioException);
- }
- }
-
- protected void write(byte... bytes) throws CborException {
- try {
- outputStream.write(bytes);
- } catch (IOException ioException) {
- throw new CborException(ioException);
- }
- }
-
-}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/ArrayEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/ArrayEncoder.java
deleted file mode 100644
index ae0ddbe..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/ArrayEncoder.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.OutputStream;
-import java.util.List;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.Array;
-import co.nstant.in.cbor.model.DataItem;
-import co.nstant.in.cbor.model.MajorType;
-
-public class ArrayEncoder extends AbstractEncoder<Array> {
-
- public ArrayEncoder(CborEncoder encoder, OutputStream outputStream) {
- super(encoder, outputStream);
- }
-
- @Override
- public void encode(Array array) throws CborException {
- List<DataItem> dataItems = array.getDataItems();
- if (array.isChunked()) {
- encodeTypeChunked(MajorType.ARRAY);
- } else {
- encodeTypeAndLength(MajorType.ARRAY, dataItems.size());
- }
- for (DataItem dataItem : dataItems) {
- encoder.encode(dataItem);
- }
- }
-
-}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/ByteStringEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/ByteStringEncoder.java
deleted file mode 100644
index 6c1ca19..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/ByteStringEncoder.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.OutputStream;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.ByteString;
-import co.nstant.in.cbor.model.MajorType;
-import co.nstant.in.cbor.model.SimpleValue;
-
-public class ByteStringEncoder extends AbstractEncoder<ByteString> {
-
- public ByteStringEncoder(CborEncoder encoder, OutputStream outputStream) {
- super(encoder, outputStream);
- }
-
- @Override
- public void encode(ByteString byteString) throws CborException {
- byte[] bytes = byteString.getBytes();
- if (byteString.isChunked()) {
- encodeTypeChunked(MajorType.BYTE_STRING);
- if (bytes != null) {
- encode(new ByteString(bytes));
- }
- } else if (bytes == null) {
- encoder.encode(SimpleValue.NULL);
- } else {
- encodeTypeAndLength(MajorType.BYTE_STRING, bytes.length);
- write(bytes);
- }
- }
-
-}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/DoublePrecisionFloatEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/DoublePrecisionFloatEncoder.java
deleted file mode 100644
index 26b84ec..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/DoublePrecisionFloatEncoder.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.OutputStream;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.DoublePrecisionFloat;
-
-public class DoublePrecisionFloatEncoder extends AbstractEncoder<DoublePrecisionFloat> {
-
- public DoublePrecisionFloatEncoder(CborEncoder encoder, OutputStream outputStream) {
- super(encoder, outputStream);
- }
-
- @Override
- public void encode(DoublePrecisionFloat dataItem) throws CborException {
- long bits = Double.doubleToRawLongBits(dataItem.getValue());
- write((byte) ((7 << 5) | 27), (byte) ((bits >> 56) & 0xFF), (byte) ((bits >> 48) & 0xFF),
- (byte) ((bits >> 40) & 0xFF), (byte) ((bits >> 32) & 0xFF), (byte) ((bits >> 24) & 0xFF),
- (byte) ((bits >> 16) & 0xFF), (byte) ((bits >> 8) & 0xFF), (byte) ((bits >> 0) & 0xFF));
- }
-
-}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/HalfPrecisionFloatEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/HalfPrecisionFloatEncoder.java
deleted file mode 100644
index d805c99..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/HalfPrecisionFloatEncoder.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.OutputStream;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.HalfPrecisionFloat;
-
-public class HalfPrecisionFloatEncoder extends AbstractEncoder<HalfPrecisionFloat> {
-
- public HalfPrecisionFloatEncoder(CborEncoder encoder, OutputStream outputStream) {
- super(encoder, outputStream);
- }
-
- @Override
- public void encode(HalfPrecisionFloat dataItem) throws CborException {
- int bits = fromFloat(dataItem.getValue());
- write((byte) ((7 << 5) | 25), (byte) ((bits >> 8) & 0xFF), (byte) ((bits >> 0) & 0xFF));
- }
-
- /**
- * @param fval the float value
- * @return all higher 16 bits as 0 for all results
- * @see <a href="http://stackoverflow.com/a/6162687">Stack Overflow</a>
- */
- public static int fromFloat(float fval) {
- int fbits = Float.floatToIntBits(fval);
- int sign = fbits >>> 16 & 0x8000; // sign only
- int val = 0x1000 + fbits & 0x7fffffff; // rounded value
-
- if (val >= 0x47800000) // might be or become NaN/Inf
- { // avoid Inf due to rounding
- if ((fbits & 0x7fffffff) >= 0x47800000) { // is or must become
- // NaN/Inf
- if (val < 0x7f800000) {// was value but too large
- return sign | 0x7c00; // make it +/-Inf
- }
- return sign | 0x7c00 | // remains +/-Inf or NaN
- (fbits & 0x007fffff) >>> 13; // keep NaN (and
- // Inf) bits
- }
- return sign | 0x7bff; // unrounded not quite Inf
- }
- if (val >= 0x38800000) { // remains normalized value
- return sign | val - 0x38000000 >>> 13; // exp - 127 + 15
- }
- if (val < 0x33000000) { // too small for subnormal
- return sign; // becomes +/-0
- }
- val = (fbits & 0x7fffffff) >>> 23; // tmp exp for subnormal calc
- return sign | ((fbits & 0x7fffff | 0x800000) // add subnormal bit
- + (0x800000 >>> val - 102) // round depending on cut off
- >>> 126 - val); // div by 2^(1-(exp-127+15)) and >> 13 | exp=0
- }
-
-}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/MapEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/MapEncoder.java
deleted file mode 100644
index c54d023..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/MapEncoder.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.ByteArrayOutputStream;
-import java.io.OutputStream;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.TreeMap;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.DataItem;
-import co.nstant.in.cbor.model.MajorType;
-import co.nstant.in.cbor.model.Map;
-import co.nstant.in.cbor.model.SimpleValue;
-
-public class MapEncoder extends AbstractEncoder<Map> {
-
- public MapEncoder(CborEncoder encoder, OutputStream outputStream) {
- super(encoder, outputStream);
- }
-
- @Override
- public void encode(Map map) throws CborException {
- Collection<DataItem> keys = map.getKeys();
-
- if (map.isChunked()) {
- encodeTypeChunked(MajorType.MAP);
- } else {
- encodeTypeAndLength(MajorType.MAP, keys.size());
- }
-
- if (keys.isEmpty()) {
- return;
- }
-
- if (map.isChunked()) {
- encodeNonCanonical(map);
- encoder.encode(SimpleValue.BREAK);
- } else {
- if (encoder.isCanonical()) {
- encodeCanonical(map);
- } else {
- encodeNonCanonical(map);
- }
- }
- }
-
- private void encodeNonCanonical(Map map) throws CborException {
- for (DataItem key : map.getKeys()) {
- encoder.encode(key);
- encoder.encode(map.get(key));
- }
- }
-
- private void encodeCanonical(Map map) throws CborException {
- /**
- * From https://tools.ietf.org/html/rfc7049#section-3.9
- *
- * Canonical CBOR
- *
- * The keys in every map must be sorted lowest value to highest. Sorting is
- * performed on the bytes of the representation of the key data items without
- * paying attention to the 3/5 bit splitting for major types. (Note that this
- * rule allows maps that have keys of different types, even though that is
- * probably a bad practice that could lead to errors in some canonicalization
- * implementations.) The sorting rules are:
- *
- * If two keys have different lengths, the shorter one sorts earlier;
- *
- * If two keys have the same length, the one with the lower value in (byte-wise)
- * lexical order sorts earlier.
- */
-
- TreeMap<byte[], byte[]> sortedMap = new TreeMap<>(new Comparator<byte[]>() {
-
- @Override
- public int compare(byte[] o1, byte[] o2) {
- if (o1.length < o2.length) {
- return -1;
- }
- if (o1.length > o2.length) {
- return 1;
- }
- for (int i = 0; i < o1.length; i++) {
- if (o1[i] < o2[i]) {
- return -1;
- }
- if (o1[i] > o2[i]) {
- return 1;
- }
- }
- return 0;
- }
-
- });
-
- ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
- CborEncoder e = new CborEncoder(byteArrayOutputStream);
- for (DataItem key : map.getKeys()) {
- // Key
- e.encode(key);
- byte[] keyBytes = byteArrayOutputStream.toByteArray();
- byteArrayOutputStream.reset();
- // Value
- e.encode(map.get(key));
- byte[] valueBytes = byteArrayOutputStream.toByteArray();
- byteArrayOutputStream.reset();
- sortedMap.put(keyBytes, valueBytes);
- }
- for (java.util.Map.Entry<byte[], byte[]> entry : sortedMap.entrySet()) {
- write(entry.getKey());
- write(entry.getValue());
- }
- }
-
-}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/NegativeIntegerEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/NegativeIntegerEncoder.java
deleted file mode 100644
index 9b9eb64..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/NegativeIntegerEncoder.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.OutputStream;
-import java.math.BigInteger;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.MajorType;
-import co.nstant.in.cbor.model.NegativeInteger;
-
-public class NegativeIntegerEncoder extends AbstractEncoder<NegativeInteger> {
-
- private static final BigInteger MINUS_ONE = BigInteger.valueOf(-1);
-
- public NegativeIntegerEncoder(CborEncoder encoder, OutputStream outputStream) {
- super(encoder, outputStream);
- }
-
- @Override
- public void encode(NegativeInteger dataItem) throws CborException {
- encodeTypeAndLength(MajorType.NEGATIVE_INTEGER, MINUS_ONE.subtract(dataItem.getValue()).abs());
- }
-
-}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/SinglePrecisionFloatEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/SinglePrecisionFloatEncoder.java
deleted file mode 100644
index 5c36b90..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/SinglePrecisionFloatEncoder.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.OutputStream;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.SinglePrecisionFloat;
-
-public class SinglePrecisionFloatEncoder extends AbstractEncoder<SinglePrecisionFloat> {
-
- public SinglePrecisionFloatEncoder(CborEncoder encoder, OutputStream outputStream) {
- super(encoder, outputStream);
- }
-
- @Override
- public void encode(SinglePrecisionFloat dataItem) throws CborException {
- int bits = Float.floatToRawIntBits(dataItem.getValue());
- write((byte) ((7 << 5) | 26), (byte) ((bits >> 24) & 0xFF), (byte) ((bits >> 16) & 0xFF),
- (byte) ((bits >> 8) & 0xFF), (byte) ((bits >> 0) & 0xFF));
- }
-
-}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/SpecialEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/SpecialEncoder.java
deleted file mode 100644
index 1bed2b5..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/SpecialEncoder.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.OutputStream;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.DoublePrecisionFloat;
-import co.nstant.in.cbor.model.HalfPrecisionFloat;
-import co.nstant.in.cbor.model.SimpleValue;
-import co.nstant.in.cbor.model.SimpleValueType;
-import co.nstant.in.cbor.model.SinglePrecisionFloat;
-import co.nstant.in.cbor.model.Special;
-
-public class SpecialEncoder extends AbstractEncoder<Special> {
-
- private final HalfPrecisionFloatEncoder halfPrecisionFloatEncoder;
- private final SinglePrecisionFloatEncoder singlePrecisionFloatEncoder;
- private final DoublePrecisionFloatEncoder doublePrecisionFloatEncoder;
-
- public SpecialEncoder(CborEncoder encoder, OutputStream outputStream) {
- super(encoder, outputStream);
- halfPrecisionFloatEncoder = new HalfPrecisionFloatEncoder(encoder, outputStream);
- singlePrecisionFloatEncoder = new SinglePrecisionFloatEncoder(encoder, outputStream);
- doublePrecisionFloatEncoder = new DoublePrecisionFloatEncoder(encoder, outputStream);
- }
-
- @Override
- public void encode(Special dataItem) throws CborException{
- switch (dataItem.getSpecialType()) {
- case BREAK:
- write((7 << 5) | 31);
- break;
- case SIMPLE_VALUE:
- SimpleValue simpleValue = (SimpleValue) dataItem;
- switch (simpleValue.getSimpleValueType()) {
- case FALSE:
- case NULL:
- case TRUE:
- case UNDEFINED:
- SimpleValueType type = simpleValue.getSimpleValueType();
- write((7 << 5) | type.getValue());
- break;
- case UNALLOCATED:
- write((7 << 5) | simpleValue.getValue());
- break;
- case RESERVED:
- break;
- }
- break;
- case IEEE_754_HALF_PRECISION_FLOAT:
- halfPrecisionFloatEncoder.encode((HalfPrecisionFloat) dataItem);
- break;
- case IEEE_754_SINGLE_PRECISION_FLOAT:
- singlePrecisionFloatEncoder.encode((SinglePrecisionFloat) dataItem);
- break;
- case IEEE_754_DOUBLE_PRECISION_FLOAT:
- doublePrecisionFloatEncoder.encode((DoublePrecisionFloat) dataItem);
- break;
- case SIMPLE_VALUE_NEXT_BYTE:
- SimpleValue simpleValueNextByte = (SimpleValue) dataItem;
- write((byte) ((7 << 5) | 24), (byte) simpleValueNextByte.getValue());
- break;
- default:
- throw new AssertionError("Unknown special value type");
- }
- }
-
-}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/TagEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/TagEncoder.java
deleted file mode 100644
index be9948e..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/TagEncoder.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.OutputStream;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.MajorType;
-import co.nstant.in.cbor.model.Tag;
-
-public class TagEncoder extends AbstractEncoder<Tag> {
-
- public TagEncoder(CborEncoder encoder, OutputStream outputStream) {
- super(encoder, outputStream);
- }
-
- @Override
- public void encode(Tag tag) throws CborException {
- encodeTypeAndLength(MajorType.TAG, tag.getValue());
- }
-
-}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/UnicodeStringEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/UnicodeStringEncoder.java
deleted file mode 100644
index ef769cb..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/UnicodeStringEncoder.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.OutputStream;
-import java.nio.charset.StandardCharsets;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.MajorType;
-import co.nstant.in.cbor.model.SimpleValue;
-import co.nstant.in.cbor.model.UnicodeString;
-
-public class UnicodeStringEncoder extends AbstractEncoder<UnicodeString> {
-
- public UnicodeStringEncoder(CborEncoder encoder, OutputStream outputStream) {
- super(encoder, outputStream);
- }
-
- @Override
- public void encode(UnicodeString dataItem) throws CborException {
- String string = dataItem.getString();
- if (dataItem.isChunked()) {
- encodeTypeChunked(MajorType.UNICODE_STRING);
- if (string != null) {
- encode(new UnicodeString(string));
- }
- } else if (string == null) {
- encoder.encode(SimpleValue.NULL);
- } else {
- byte[] bytes;
- bytes = string.getBytes(StandardCharsets.UTF_8);
- encodeTypeAndLength(MajorType.UNICODE_STRING, bytes.length);
- write(bytes);
- }
- }
-
-}
diff --git a/src/main/java/co/nstant/in/cbor/encoder/UnsignedIntegerEncoder.java b/src/main/java/co/nstant/in/cbor/encoder/UnsignedIntegerEncoder.java
deleted file mode 100644
index c7d08ef..0000000
--- a/src/main/java/co/nstant/in/cbor/encoder/UnsignedIntegerEncoder.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package co.nstant.in.cbor.encoder;
-
-import java.io.OutputStream;
-
-import co.nstant.in.cbor.CborEncoder;
-import co.nstant.in.cbor.CborException;
-import co.nstant.in.cbor.model.MajorType;
-import co.nstant.in.cbor.model.UnsignedInteger;
-
-public class UnsignedIntegerEncoder extends AbstractEncoder<UnsignedInteger> {
-
- public UnsignedIntegerEncoder(CborEncoder encoder, OutputStream outputStream) {
- super(encoder, outputStream);
- }
-
- @Override
- public void encode(UnsignedInteger dataItem) throws CborException {
- encodeTypeAndLength(MajorType.UNSIGNED_INTEGER, dataItem.getValue());
- }
-
-}