Skip to content

Commit

Permalink
Adds support for writing macros in IonManagedWriter_1_1 (#934)
Browse files Browse the repository at this point in the history
  • Loading branch information
popematt authored and tgregg committed Sep 9, 2024
1 parent 13e8402 commit 49769f5
Show file tree
Hide file tree
Showing 24 changed files with 1,422 additions and 126 deletions.
21 changes: 6 additions & 15 deletions src/main/java/com/amazon/ion/IonWriter.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,5 @@
/*
* Copyright 2007-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package com.amazon.ion;

import com.amazon.ion.facet.Faceted;
Expand Down Expand Up @@ -518,4 +505,8 @@ public void writeClob(byte[] value, int start, int len)
*/
public void writeBlob(byte[] value, int start, int len)
throws IOException;

public default void writeObject(WriteAsIon obj) {
obj.writeTo(this);
}
}
48 changes: 48 additions & 0 deletions src/main/java/com/amazon/ion/MacroAwareIonWriter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package com.amazon.ion

import com.amazon.ion.impl.macro.*

/**
* Extension of the IonWriter interface that supports writing macros.
*
* TODO: Consider exposing this as a Facet.
*/
interface MacroAwareIonWriter : IonWriter {

/**
* Adds a macro to the macro table, returning a MacroRef that can be used to invoke the macro.
*/
fun addMacro(macro: Macro): MacroRef

/**
* Adds a macro to the macro table, returning a MacroRef that can be used to invoke the macro.
*/
fun addMacro(name: String, macro: Macro): MacroRef

/**
* Starts writing a macro invocation, adding it to the macro table, if needed.
*/
fun startMacro(macro: Macro)

/**
* Starts writing a macro using the given [MacroRef].
*/
fun startMacro(macro: MacroRef)

/**
* Ends and steps out of the current macro invocation.
*/
fun endMacro()

/**
* Starts writing an expression group. May only be called while the writer is in a macro invocation.
*/
fun startExpressionGroup()

/**
* Ends and steps out of the current expression group.
*/
fun endExpressionGroup()
}
52 changes: 42 additions & 10 deletions src/main/java/com/amazon/ion/SystemSymbols.java
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,31 @@ private SystemSymbols() { }
*/
public static final String MAX_ID = "max_id";

/**
* The ID of system symbol {@value #MAX_ID}, as defined by Ion 1.0.
*/
public static final int MAX_ID_SID = 8;


/**
* The text of system symbol {@value}, as defined by Ion 1.0.
*/
public static final String ION_SHARED_SYMBOL_TABLE =
"$ion_shared_symbol_table";

/**
* The ID of system symbol {@value #ION_SHARED_SYMBOL_TABLE},
* as defined by Ion 1.0.
*/
public static final int ION_SHARED_SYMBOL_TABLE_SID = 9;

/**
* The maximum ID of the IDs of system symbols defined by Ion 1.0.
*/
public static final int ION_1_0_MAX_ID = 9;

// Ion 1.1 Symbols

/**
* The annotation that denotes an Ion encoding directive in Ion 1.1+.
*/
Expand All @@ -111,25 +136,32 @@ private SystemSymbols() { }
public static final String MACRO_TABLE = "macro_table";

/**
* The ID of system symbol {@value #MAX_ID}, as defined by Ion 1.0.
* The name of the "annotate" system macro.
*/
public static final int MAX_ID_SID = 8;
public static final String ANNOTATE = "annotate";

/**
* The name of the "literal" special form.
*/
public static final String LITERAL = "literal";

/**
* The text of system symbol {@value}, as defined by Ion 1.0.
* The name of the "macro" s-expression in the macro table.
*/
public static final String ION_SHARED_SYMBOL_TABLE =
"$ion_shared_symbol_table";
public static final String MACRO = "macro";

/**
* The ID of system symbol {@value #ION_SHARED_SYMBOL_TABLE},
* as defined by Ion 1.0.
* The name of the "export" s-expression in the macro table.
*/
public static final int ION_SHARED_SYMBOL_TABLE_SID = 9;
public static final String EXPORT = "export";

/**
* The maximum ID of the IDs of system symbols defined by Ion 1.0.
* The name of the "make_sexp" system macro.
*/
public static final int ION_1_0_MAX_ID = 9;
public static final String MAKE_SEXP = "make_sexp";

/**
* The sigil used to denote an expression group in TDL.
*/
public static final String TDL_EXPRESSION_GROUP = ";";
}
19 changes: 19 additions & 0 deletions src/main/java/com/amazon/ion/WriteAsIon.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
package com.amazon.ion

/**
* Indicates that the implementing class has a standardized/built-in way to serialize as Ion.
*/
interface WriteAsIon {

/**
* Writes this object to an IonWriter capable of producing macro invocations.
*/
fun writeToMacroAware(writer: MacroAwareIonWriter) = writeTo(writer as IonWriter)

/**
* Writes this object to a standard [IonWriter].
*/
fun writeTo(writer: IonWriter)
}
5 changes: 3 additions & 2 deletions src/main/java/com/amazon/ion/impl/IonRawTextWriter_1_1.kt
Original file line number Diff line number Diff line change
Expand Up @@ -130,15 +130,16 @@ class IonRawTextWriter_1_1 internal constructor(

override fun close() {
if (closed) return
finish()
flush()
output.close()
closed = true
}

override fun finish() {
override fun flush() {
if (closed) return
confirm(depth() == 0) { "Cannot call finish() while in a container" }
confirm(numAnnotations == 0) { "Cannot call finish with dangling annotations" }
output.flush()
}

override fun writeIVM() {
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/com/amazon/ion/impl/IonRawWriter_1_1.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ interface IonRawWriter_1_1 {
* Implementations should allow the application to continue writing further top-level values following the semantics
* for concatenating Ion data streams.
*/
fun finish()
fun flush()

/**
* Closes this stream and releases any system resources associated with it.
* If the stream is already closed then invoking this method has no effect.
*
* If the cursor is between top-level values, this method will [finish] before closing the underlying output stream.
* If the cursor is between top-level values, this method will [flush] before closing the underlying output stream.
* If not, the resulting data may be incomplete and invalid Ion.
*/
fun close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1646,7 +1646,10 @@ private void collectEExpressionArgs(List<Expression.EExpressionBodyExpression> e
throw new UnsupportedOperationException("System macro invocations not yet supported.");
}
long id = getMacroInvocationId();
MacroRef address = MacroRef.byId(id);
if (id > Integer.MAX_VALUE) {
throw new IonException("Macro addresses larger than 2147483647 are not supported by this implementation.");
}
MacroRef address = MacroRef.byId((int) id);
Macro macro = macroEvaluator.getEncodingContext().getMacroTable().get(address);
if (macro == null) {
throw new IonException(String.format("Encountered an unknown macro address: %d.", id));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,13 @@ public IonWriter build(Appendable out) {
throw new NullPointerException("Cannot construct a writer with a null Appendable.");
}
_Private_IonTextWriterBuilder_1_1 b = fillDefaults();
ManagedWriterOptions_1_1 options = new ManagedWriterOptions_1_1(false, symbolInliningStrategy, LengthPrefixStrategy.NEVER_PREFIXED);
ManagedWriterOptions_1_1 options = new ManagedWriterOptions_1_1(
false,
symbolInliningStrategy,
LengthPrefixStrategy.NEVER_PREFIXED,
// This could be made configurable.
ManagedWriterOptions_1_1.EExpressionIdentifierStrategy.BY_NAME
);
return IonManagedWriter_1_1.textWriter(out, options, b);
}

Expand All @@ -158,7 +164,13 @@ public IonWriter build(OutputStream out) {
}

_Private_IonTextWriterBuilder_1_1 b = fillDefaults();
ManagedWriterOptions_1_1 options = new ManagedWriterOptions_1_1(false, symbolInliningStrategy, LengthPrefixStrategy.NEVER_PREFIXED);
ManagedWriterOptions_1_1 options = new ManagedWriterOptions_1_1(
false,
symbolInliningStrategy,
LengthPrefixStrategy.NEVER_PREFIXED,
// This could be made configurable.
ManagedWriterOptions_1_1.EExpressionIdentifierStrategy.BY_NAME
);
return IonManagedWriter_1_1.textWriter(out, options, b);
}

Expand Down
Loading

0 comments on commit 49769f5

Please sign in to comment.