-
Notifications
You must be signed in to change notification settings - Fork 125
Adds support for writing Ion 1.1 null, bool, int, and float binary encoding #612
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,161 @@ | ||
| package com.amazon.ion.impl.bin; | ||
|
|
||
| import com.amazon.ion.Decimal; | ||
| import com.amazon.ion.IonType; | ||
| import com.amazon.ion.Timestamp; | ||
| import com.amazon.ion.impl.bin.utf8.Utf8StringEncoder; | ||
|
|
||
| import java.math.BigDecimal; | ||
| import java.math.BigInteger; | ||
|
|
||
| import static java.lang.Double.doubleToRawLongBits; | ||
| import static java.lang.Float.floatToIntBits; | ||
|
|
||
| /** | ||
| * Provides functions for writing various Ion values to a WriteBuffer. | ||
| * | ||
| * This class can be subsumed by IonRawBinaryWriter_1_1, when it is created. | ||
| */ | ||
| public class IonEncoder_1_1 { | ||
|
|
||
| /** | ||
| * Writes an Ion Null value to the given WriteBuffer. | ||
| * @return the number of bytes written | ||
| */ | ||
| public static int writeNullValue(WriteBuffer buffer, final IonType ionType) { | ||
| if (ionType == IonType.NULL) { | ||
| buffer.writeByte(OpCodes.NULL_UNTYPED); | ||
| return 1; | ||
| } | ||
|
|
||
| buffer.writeByte(OpCodes.NULL_TYPED); | ||
| switch (ionType) { | ||
| case BOOL: | ||
| buffer.writeByte((byte) 0x00); | ||
| break; | ||
| case INT: | ||
| buffer.writeByte((byte) 0x01); | ||
| break; | ||
| case FLOAT: | ||
| buffer.writeByte((byte) 0x02); | ||
| break; | ||
| case DECIMAL: | ||
| buffer.writeByte((byte) 0x03); | ||
| break; | ||
| case TIMESTAMP: | ||
| buffer.writeByte((byte) 0x04); | ||
| break; | ||
| case STRING: | ||
| buffer.writeByte((byte) 0x05); | ||
| break; | ||
| case SYMBOL: | ||
| buffer.writeByte((byte) 0x06); | ||
| break; | ||
| case BLOB: | ||
| buffer.writeByte((byte) 0x07); | ||
| break; | ||
| case CLOB: | ||
| buffer.writeByte((byte) 0x08); | ||
| break; | ||
| case LIST: | ||
| buffer.writeByte((byte) 0x09); | ||
| break; | ||
| case SEXP: | ||
| buffer.writeByte((byte) 0x0A); | ||
| break; | ||
| case STRUCT: | ||
| buffer.writeByte((byte) 0x0B); | ||
| break; | ||
| case DATAGRAM: | ||
| throw new IllegalArgumentException("Cannot write a null datagram"); | ||
| } | ||
| return 2; | ||
| } | ||
|
|
||
| /** | ||
| * Writes an Ion Bool value to the given WriteBuffer. | ||
| * @return the number of bytes written | ||
| */ | ||
| public static int writeBoolValue(WriteBuffer buffer, final boolean value) { | ||
| if (value) { | ||
| buffer.writeByte(OpCodes.BOOLEAN_TRUE); | ||
| } else { | ||
| buffer.writeByte(OpCodes.BOOLEAN_FALSE); | ||
| } | ||
| return 1; | ||
| } | ||
|
|
||
| /** | ||
| * Writes an Ion Integer value to the given WriteBuffer. | ||
| * @return the number of bytes written | ||
| */ | ||
| public static int writeIntValue(WriteBuffer buffer, final long value) { | ||
| if (value == 0) { | ||
| buffer.writeByte(OpCodes.INTEGER_ZERO_LENGTH); | ||
| return 1; | ||
| } | ||
| int length = WriteBuffer.fixedIntLength(value); | ||
| buffer.writeByte((byte) (OpCodes.INTEGER_ZERO_LENGTH + length)); | ||
| buffer.writeFixedInt(value); | ||
| return 1 + length; | ||
| } | ||
|
|
||
| private static final BigInteger BIG_INT_LONG_MAX_VALUE = BigInteger.valueOf(Long.MAX_VALUE); | ||
| private static final BigInteger BIG_INT_LONG_MIN_VALUE = BigInteger.valueOf(Long.MIN_VALUE); | ||
|
|
||
| /** | ||
| * Writes an Ion Integer value to the given WriteBuffer. | ||
| * @return the number of bytes written | ||
| */ | ||
| public static int writeIntValue(WriteBuffer buffer, final BigInteger value) { | ||
| if (value == null) { | ||
| return writeNullValue(buffer, IonType.INT); | ||
| } | ||
| if (value.compareTo(BIG_INT_LONG_MIN_VALUE) >= 0 && value.compareTo(BIG_INT_LONG_MAX_VALUE) <= 0) { | ||
| return writeIntValue(buffer, value.longValue()); | ||
| } | ||
| buffer.writeByte(OpCodes.VARIABLE_LENGTH_INTEGER); | ||
| byte[] intBytes = value.toByteArray(); | ||
| int totalBytes = 1 + intBytes.length + buffer.writeFlexUInt(intBytes.length); | ||
| for (int i = intBytes.length; i > 0; i--) { | ||
| buffer.writeByte(intBytes[i-1]); | ||
| } | ||
| return totalBytes; | ||
| } | ||
|
|
||
| /** | ||
| * Writes a float to the given WriteBuffer using the Ion 1.1 encoding for Ion Floats. | ||
| * @return the number of bytes written | ||
| */ | ||
| public static int writeFloat(WriteBuffer buffer, final float value) { | ||
| // TODO: Optimization to write a 16 bit float for non-finite and possibly other values | ||
| if (value == 0.0) { | ||
| buffer.writeByte(OpCodes.FLOAT_ZERO_LENGTH); | ||
| return 1; | ||
| } else { | ||
| buffer.writeByte(OpCodes.FLOAT_32); | ||
| buffer.writeUInt32(floatToIntBits(value)); | ||
| return 5; | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Writes a double to the given WriteBuffer using the Ion 1.1 encoding for Ion Floats. | ||
| * @return the number of bytes written | ||
| */ | ||
| public static int writeFloat(WriteBuffer buffer, final double value) { | ||
| // TODO: Optimization to write a 16 bit float for non-finite and possibly other values | ||
| if (value == 0.0) { | ||
| buffer.writeByte(OpCodes.FLOAT_ZERO_LENGTH); | ||
| return 1; | ||
| } else if (!Double.isFinite(value) || value == (float) value) { | ||
| buffer.writeByte(OpCodes.FLOAT_32); | ||
| buffer.writeUInt32(floatToIntBits((float) value)); | ||
| return 5; | ||
| } else { | ||
| buffer.writeByte(OpCodes.FLOAT_64); | ||
| buffer.writeUInt64(doubleToRawLongBits(value)); | ||
| return 9; | ||
| } | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| package com.amazon.ion.impl.bin; | ||
|
|
||
| /** | ||
| * Utility class holding Ion 1.1 Op Codes. | ||
| */ | ||
| public class OpCodes { | ||
| private OpCodes() {} | ||
|
|
||
| public static final byte INTEGER_ZERO_LENGTH = 0x50; | ||
| // 0x51-0x58 are additional lengths of integers. | ||
| // 0x59 Reserved | ||
| public static final byte FLOAT_ZERO_LENGTH = 0x5A; | ||
| public static final byte FLOAT_16 = 0x5B; | ||
| public static final byte FLOAT_32 = 0x5C; | ||
| public static final byte FLOAT_64 = 0x5D; | ||
| public static final byte BOOLEAN_TRUE = 0x5E; | ||
| public static final byte BOOLEAN_FALSE = 0x5F; | ||
|
|
||
| public static final byte DECIMAL_ZERO_LENGTH = 0x60; | ||
| // 0x61-0x6E are additional lengths of decimals. | ||
| public static final byte NEGATIVE_ZERO_DECIMAL = 0x6F; | ||
|
|
||
|
|
||
| public static final byte NULL_UNTYPED = (byte) 0xEA; | ||
| public static final byte NULL_TYPED = (byte) 0xEB; | ||
|
|
||
| public static final byte VARIABLE_LENGTH_INTEGER = (byte) 0xF5; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.