Skip to content

Commit

Permalink
Adds suggested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
popematt committed Jan 2, 2024
1 parent 286ad00 commit 340a4e5
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 78 deletions.
32 changes: 21 additions & 11 deletions src/main/java/com/amazon/ion/impl/IonRawTextWriter_1_1.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ class IonRawTextWriter_1_1 internal constructor(
private val output: _Private_IonTextAppender,
) : IonRawWriter_1_1 {

companion object {
const val IVM = "\$ion_1_1"
}

enum class ContainerType {
List,
SExp,
Expand All @@ -39,8 +43,8 @@ class IonRawTextWriter_1_1 internal constructor(
private var isPendingSeparator = false
private var isPendingLeadingWhitespace = false

private var fieldNameTextBuffer: CharSequence? = null
private var fieldNameIdBuffer: Int = -1
private var fieldNameText: CharSequence? = null
private var fieldNameId: Int = -1
private var hasFieldName = false

private var annotationsTextBuffer = arrayOfNulls<CharSequence>(8)
Expand Down Expand Up @@ -74,17 +78,17 @@ class IonRawTextWriter_1_1 internal constructor(
isPendingSeparator = false

if (hasFieldName) {
if (fieldNameTextBuffer != null) {
output.printSymbol(fieldNameTextBuffer)
if (fieldNameText != null) {
output.printSymbol(fieldNameText)
output.appendAscii(':')
if (options.isPrettyPrintOn) output.appendAscii(" ")
fieldNameTextBuffer = null
fieldNameText = null
} else {
output.appendAscii("$")
output.printInt(fieldNameIdBuffer.toLong())
output.printInt(fieldNameId.toLong())
output.appendAscii(":")
if (options.isPrettyPrintOn) output.appendAscii(" ")
fieldNameIdBuffer = -1
fieldNameId = -1
}
}

Expand Down Expand Up @@ -134,7 +138,7 @@ class IonRawTextWriter_1_1 internal constructor(
override fun writeIVM() {
confirm(currentContainer == Top) { "IVM can only be written at the top level of an Ion stream." }
confirm(numAnnotations == 0) { "Cannot write an IVM with annotations" }
output.appendAscii("\$ion_1_1")
output.appendAscii(IVM)
isPendingSeparator = true
}

Expand Down Expand Up @@ -197,14 +201,14 @@ class IonRawTextWriter_1_1 internal constructor(
override fun writeFieldName(sid: Int) {
confirm(currentContainer == Struct) { "Cannot write field name outside of a struct." }
confirm(!hasFieldName) { "Field name already set." }
fieldNameIdBuffer = sid
fieldNameId = sid
hasFieldName = true
}

override fun writeFieldName(text: CharSequence) {
confirm(currentContainer == Struct) { "Cannot write field name outside of a struct." }
confirm(!hasFieldName) { "Field name already set." }
fieldNameTextBuffer = text
fieldNameText = text
hasFieldName = true
}

Expand Down Expand Up @@ -276,7 +280,13 @@ class IonRawTextWriter_1_1 internal constructor(
output.printInt(id.toLong())
}

override fun writeSymbol(text: CharSequence) = writeScalar { output.printSymbol(text) }
override fun writeSymbol(text: CharSequence) = writeScalar {
when (IonTextUtils.symbolVariant(text)) {
IonTextUtils.SymbolVariant.IDENTIFIER -> output.appendAscii(text)
IonTextUtils.SymbolVariant.OPERATOR -> if (currentContainer == SExp) output.appendAscii(text) else output.printQuotedSymbol(text)
IonTextUtils.SymbolVariant.QUOTED -> output.printQuotedSymbol(text)
}
}

override fun writeString(value: CharSequence) = writeScalar { output.printString(value) }

Expand Down
170 changes: 103 additions & 67 deletions src/test/java/com/amazon/ion/impl/IonRawTextWriterTest_1_1.kt
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,11 @@ import org.junit.jupiter.params.provider.CsvSource

class IonRawTextWriterTest_1_1 {

private inline fun writeAsString(
private inline fun ionWriter(
out: StringBuilder = StringBuilder(),
builderConfigurator: IonTextWriterBuilder.() -> Unit = { /* noop */ },
autoClose: Boolean = true,
block: IonRawTextWriter_1_1.() -> Unit,
): String {
val out = StringBuilder()
): IonRawTextWriter_1_1 {
val b = IonTextWriterBuilder.standard()
.apply(builderConfigurator)
// Always use LF because the tests' expected data uses LF.
Expand All @@ -31,6 +30,16 @@ class IonRawTextWriterTest_1_1 {
output = _Private_IonTextAppender.forAppendable(out)
)
block.invoke(rawWriter)
return rawWriter
}

private inline fun writeAsString(
builderConfigurator: IonTextWriterBuilder.() -> Unit = { /* noop */ },
autoClose: Boolean = true,
block: IonRawTextWriter_1_1.() -> Unit,
): String {
val out = StringBuilder()
val rawWriter = ionWriter(out, builderConfigurator, block)
if (autoClose) rawWriter.close()
return out.toString()
}
Expand All @@ -44,70 +53,59 @@ class IonRawTextWriterTest_1_1 {
assertEquals(text, writeAsString(builderConfigurator, autoClose, block))
}

private inline fun assertWriterThrows(block: IonRawTextWriter_1_1.() -> Unit) {
val out = StringBuilder()
val rawWriter = IonRawTextWriter_1_1(
options = _Private_IonTextWriterBuilder.STANDARD,
output = _Private_IonTextAppender.forAppendable(out)
)
assertThrows<IonException> {
block.invoke(rawWriter)
}
}

@Test
fun `calling close while in a container should throw IonException`() {
assertWriterThrows {
ionWriter {
stepInList(false)
close()
assertThrows<IonException> { close() }
}
}

@Test
fun `calling finish while in a container should throw IonException`() {
assertWriterThrows {
ionWriter {
stepInList(true)
finish()
assertThrows<IonException> { finish() }
}
}

@Test
fun `calling finish with a dangling annotation should throw IonException`() {
assertWriterThrows {
ionWriter {
writeAnnotations(10)
finish()
assertThrows<IonException> { finish() }
}
}

@Test
fun `calling stepOut while not in a container should throw IonException`() {
assertWriterThrows {
stepOut()
ionWriter {
assertThrows<IonException> { stepOut() }
}
}

@Test
fun `calling stepOut with a dangling annotation should throw IonException`() {
assertWriterThrows {
ionWriter {
stepInList(true)
writeAnnotations(10)
stepOut()
assertThrows<IonException> { stepOut() }
}
}

@Test
fun `calling writeIVM when in a container should throw IonException`() {
assertWriterThrows {
ionWriter {
stepInList(false)
writeIVM()
assertThrows<IonException> { writeIVM() }
}
}

@Test
fun `calling writeIVM with a dangling annotation should throw IonException`() {
assertWriterThrows {
ionWriter {
writeAnnotations(10)
writeIVM()
assertThrows<IonException> { writeIVM() }
}
}

Expand Down Expand Up @@ -320,7 +318,7 @@ class IonRawTextWriterTest_1_1 {
}

@Test
fun `write prefixed struct with a single flex sym field`() {
fun `write prefixed struct with a single text field name`() {
assertWriterOutputEquals(
"""{foo:true}"""
) {
Expand All @@ -331,22 +329,6 @@ class IonRawTextWriterTest_1_1 {
}
}

@Test
fun `write prefixed struct with multiple fields and flex syms`() {
assertWriterOutputEquals(
"""{foo:true,bar:true,baz:true}"""
) {
stepInStruct(false)
writeFieldName("foo")
writeBool(true)
writeFieldName("bar")
writeBool(true)
writeFieldName("baz")
writeBool(true)
stepOut()
}
}

@Test
fun `write a struct with sid 0`() {
assertWriterOutputEquals(
Expand All @@ -369,37 +351,37 @@ class IonRawTextWriterTest_1_1 {

@Test
fun `writing a value in a struct with no field name should throw an exception`() {
assertWriterThrows {
ionWriter {
stepInStruct(true)
writeBool(true)
assertThrows<IonException> { writeBool(true) }
}
assertWriterThrows {
ionWriter {
stepInStruct(false)
writeBool(true)
assertThrows<IonException> { writeBool(true) }
}
}

@Test
fun `calling writeFieldName outside of a struct should throw an exception`() {
assertWriterThrows {
writeFieldName(12)
ionWriter {
assertThrows<IonException> { writeFieldName(12) }
}
assertWriterThrows {
writeFieldName("foo")
ionWriter {
assertThrows<IonException> { writeFieldName("foo") }
}
}

@Test
fun `calling stepOut with a dangling field name should throw an exception`() {
assertWriterThrows {
ionWriter {
stepInStruct(false)
writeFieldName(12)
stepOut()
assertThrows<IonException> { stepOut() }
}
assertWriterThrows {
ionWriter {
stepInStruct(true)
writeFieldName("foo")
stepOut()
assertThrows<IonException> { stepOut() }
}
}

Expand Down Expand Up @@ -478,7 +460,7 @@ class IonRawTextWriterTest_1_1 {
}

@Test
fun `write one inline annotation`() {
fun `write one text annotation`() {
val expectedBytes = "foo::false"
assertWriterOutputEquals(expectedBytes) {
writeAnnotations("foo")
Expand Down Expand Up @@ -609,14 +591,48 @@ class IonRawTextWriterTest_1_1 {
@Test
fun `write symbol`() {
assertWriterOutputEquals(
"\$0 \$1 \$12345 foo 'null' 'bat\\'leth'"
"\$0 \$1 \$12345 foo 'null' 'null.int' 'bat\\'leth' '$99' 'true' 'false' 'nan' \$ion_1_1 '+' '==' '.'"
) {
writeSymbol(0)
writeSymbol(1)
writeSymbol(12345)
writeSymbol("foo")
writeSymbol("null")
writeSymbol("null.int")
writeSymbol("bat'leth")
writeSymbol("$99")
writeSymbol("true")
writeSymbol("false")
writeSymbol("nan")
writeSymbol("\$ion_1_1")
writeSymbol("+")
writeSymbol("==")
writeSymbol(".")
}
}

@Test
fun `write symbols in a sexp`() {
assertWriterOutputEquals(
"(\$0 \$1 \$12345 foo 'null' 'null.int' 'bat\\'leth' '$99' 'true' 'false' 'nan' \$ion_1_1 + == .)"
) {
writeSexp {
writeSymbol(0)
writeSymbol(1)
writeSymbol(12345)
writeSymbol("foo")
writeSymbol("null")
writeSymbol("null.int")
writeSymbol("bat'leth")
writeSymbol("$99")
writeSymbol("true")
writeSymbol("false")
writeSymbol("nan")
writeSymbol("\$ion_1_1")
writeSymbol("+")
writeSymbol("==")
writeSymbol(".")
}
}
}

Expand Down Expand Up @@ -699,20 +715,40 @@ class IonRawTextWriterTest_1_1 {

@Test
fun `calling stepInExpressionGroup with an annotation should throw IonException`() {
assertWriterThrows {
ionWriter {
stepInEExp(1)
writeAnnotations("foo")
stepInExpressionGroup(false)
assertThrows<IonException> { stepInExpressionGroup(false) }
}
}

@Test
fun `calling stepInExpressionGroup while not directly in a Macro container should throw IonException`() {
assertWriterThrows { stepInExpressionGroup(true) }
assertWriterThrows { writeList { stepInExpressionGroup(true) } }
assertWriterThrows { writeSexp { stepInExpressionGroup(true) } }
assertWriterThrows { writeStruct { stepInExpressionGroup(true) } }
assertWriterThrows { writeEExp(123) { writeExpressionGroup { stepInExpressionGroup(true) } } }
ionWriter {
assertThrows<IonException> { stepInExpressionGroup(true) }
}
ionWriter {
writeList {
assertThrows<IonException> { stepInExpressionGroup(true) }
}
}
ionWriter {
writeSexp {
assertThrows<IonException> { stepInExpressionGroup(true) }
}
}
ionWriter {
writeStruct {
assertThrows<IonException> { stepInExpressionGroup(true) }
}
}
ionWriter {
writeEExp(123) {
writeExpressionGroup {
assertThrows<IonException> { stepInExpressionGroup(true) }
}
}
}
}

/**
Expand Down

0 comments on commit 340a4e5

Please sign in to comment.