Skip to content

Commit 49769f5

Browse files
popematttgregg
authored andcommitted
Adds support for writing macros in IonManagedWriter_1_1 (#934)
1 parent 13e8402 commit 49769f5

24 files changed

+1422
-126
lines changed

src/main/java/com/amazon/ion/IonWriter.java

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,5 @@
1-
/*
2-
* Copyright 2007-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3-
*
4-
* Licensed under the Apache License, Version 2.0 (the "License").
5-
* You may not use this file except in compliance with the License.
6-
* A copy of the License is located at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* or in the "license" file accompanying this file. This file is distributed
11-
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12-
* express or implied. See the License for the specific language governing
13-
* permissions and limitations under the License.
14-
*/
15-
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
163
package com.amazon.ion;
174

185
import com.amazon.ion.facet.Faceted;
@@ -518,4 +505,8 @@ public void writeClob(byte[] value, int start, int len)
518505
*/
519506
public void writeBlob(byte[] value, int start, int len)
520507
throws IOException;
508+
509+
public default void writeObject(WriteAsIon obj) {
510+
obj.writeTo(this);
511+
}
521512
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package com.amazon.ion
4+
5+
import com.amazon.ion.impl.macro.*
6+
7+
/**
8+
* Extension of the IonWriter interface that supports writing macros.
9+
*
10+
* TODO: Consider exposing this as a Facet.
11+
*/
12+
interface MacroAwareIonWriter : IonWriter {
13+
14+
/**
15+
* Adds a macro to the macro table, returning a MacroRef that can be used to invoke the macro.
16+
*/
17+
fun addMacro(macro: Macro): MacroRef
18+
19+
/**
20+
* Adds a macro to the macro table, returning a MacroRef that can be used to invoke the macro.
21+
*/
22+
fun addMacro(name: String, macro: Macro): MacroRef
23+
24+
/**
25+
* Starts writing a macro invocation, adding it to the macro table, if needed.
26+
*/
27+
fun startMacro(macro: Macro)
28+
29+
/**
30+
* Starts writing a macro using the given [MacroRef].
31+
*/
32+
fun startMacro(macro: MacroRef)
33+
34+
/**
35+
* Ends and steps out of the current macro invocation.
36+
*/
37+
fun endMacro()
38+
39+
/**
40+
* Starts writing an expression group. May only be called while the writer is in a macro invocation.
41+
*/
42+
fun startExpressionGroup()
43+
44+
/**
45+
* Ends and steps out of the current expression group.
46+
*/
47+
fun endExpressionGroup()
48+
}

src/main/java/com/amazon/ion/SystemSymbols.java

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,31 @@ private SystemSymbols() { }
9595
*/
9696
public static final String MAX_ID = "max_id";
9797

98+
/**
99+
* The ID of system symbol {@value #MAX_ID}, as defined by Ion 1.0.
100+
*/
101+
public static final int MAX_ID_SID = 8;
102+
103+
104+
/**
105+
* The text of system symbol {@value}, as defined by Ion 1.0.
106+
*/
107+
public static final String ION_SHARED_SYMBOL_TABLE =
108+
"$ion_shared_symbol_table";
109+
110+
/**
111+
* The ID of system symbol {@value #ION_SHARED_SYMBOL_TABLE},
112+
* as defined by Ion 1.0.
113+
*/
114+
public static final int ION_SHARED_SYMBOL_TABLE_SID = 9;
115+
116+
/**
117+
* The maximum ID of the IDs of system symbols defined by Ion 1.0.
118+
*/
119+
public static final int ION_1_0_MAX_ID = 9;
120+
121+
// Ion 1.1 Symbols
122+
98123
/**
99124
* The annotation that denotes an Ion encoding directive in Ion 1.1+.
100125
*/
@@ -111,25 +136,32 @@ private SystemSymbols() { }
111136
public static final String MACRO_TABLE = "macro_table";
112137

113138
/**
114-
* The ID of system symbol {@value #MAX_ID}, as defined by Ion 1.0.
139+
* The name of the "annotate" system macro.
115140
*/
116-
public static final int MAX_ID_SID = 8;
141+
public static final String ANNOTATE = "annotate";
117142

143+
/**
144+
* The name of the "literal" special form.
145+
*/
146+
public static final String LITERAL = "literal";
118147

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

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

131158
/**
132-
* The maximum ID of the IDs of system symbols defined by Ion 1.0.
159+
* The name of the "make_sexp" system macro.
133160
*/
134-
public static final int ION_1_0_MAX_ID = 9;
161+
public static final String MAKE_SEXP = "make_sexp";
162+
163+
/**
164+
* The sigil used to denote an expression group in TDL.
165+
*/
166+
public static final String TDL_EXPRESSION_GROUP = ";";
135167
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package com.amazon.ion
4+
5+
/**
6+
* Indicates that the implementing class has a standardized/built-in way to serialize as Ion.
7+
*/
8+
interface WriteAsIon {
9+
10+
/**
11+
* Writes this object to an IonWriter capable of producing macro invocations.
12+
*/
13+
fun writeToMacroAware(writer: MacroAwareIonWriter) = writeTo(writer as IonWriter)
14+
15+
/**
16+
* Writes this object to a standard [IonWriter].
17+
*/
18+
fun writeTo(writer: IonWriter)
19+
}

src/main/java/com/amazon/ion/impl/IonRawTextWriter_1_1.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,15 +130,16 @@ class IonRawTextWriter_1_1 internal constructor(
130130

131131
override fun close() {
132132
if (closed) return
133-
finish()
133+
flush()
134134
output.close()
135135
closed = true
136136
}
137137

138-
override fun finish() {
138+
override fun flush() {
139139
if (closed) return
140140
confirm(depth() == 0) { "Cannot call finish() while in a container" }
141141
confirm(numAnnotations == 0) { "Cannot call finish with dangling annotations" }
142+
output.flush()
142143
}
143144

144145
override fun writeIVM() {

src/main/java/com/amazon/ion/impl/IonRawWriter_1_1.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,13 @@ interface IonRawWriter_1_1 {
2525
* Implementations should allow the application to continue writing further top-level values following the semantics
2626
* for concatenating Ion data streams.
2727
*/
28-
fun finish()
28+
fun flush()
2929

3030
/**
3131
* Closes this stream and releases any system resources associated with it.
3232
* If the stream is already closed then invoking this method has no effect.
3333
*
34-
* If the cursor is between top-level values, this method will [finish] before closing the underlying output stream.
34+
* If the cursor is between top-level values, this method will [flush] before closing the underlying output stream.
3535
* If not, the resulting data may be incomplete and invalid Ion.
3636
*/
3737
fun close()

src/main/java/com/amazon/ion/impl/IonReaderContinuableCoreBinary.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1646,7 +1646,10 @@ private void collectEExpressionArgs(List<Expression.EExpressionBodyExpression> e
16461646
throw new UnsupportedOperationException("System macro invocations not yet supported.");
16471647
}
16481648
long id = getMacroInvocationId();
1649-
MacroRef address = MacroRef.byId(id);
1649+
if (id > Integer.MAX_VALUE) {
1650+
throw new IonException("Macro addresses larger than 2147483647 are not supported by this implementation.");
1651+
}
1652+
MacroRef address = MacroRef.byId((int) id);
16501653
Macro macro = macroEvaluator.getEncodingContext().getMacroTable().get(address);
16511654
if (macro == null) {
16521655
throw new IonException(String.format("Encountered an unknown macro address: %d.", id));

src/main/java/com/amazon/ion/impl/_Private_IonTextWriterBuilder_1_1.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,13 @@ public IonWriter build(Appendable out) {
147147
throw new NullPointerException("Cannot construct a writer with a null Appendable.");
148148
}
149149
_Private_IonTextWriterBuilder_1_1 b = fillDefaults();
150-
ManagedWriterOptions_1_1 options = new ManagedWriterOptions_1_1(false, symbolInliningStrategy, LengthPrefixStrategy.NEVER_PREFIXED);
150+
ManagedWriterOptions_1_1 options = new ManagedWriterOptions_1_1(
151+
false,
152+
symbolInliningStrategy,
153+
LengthPrefixStrategy.NEVER_PREFIXED,
154+
// This could be made configurable.
155+
ManagedWriterOptions_1_1.EExpressionIdentifierStrategy.BY_NAME
156+
);
151157
return IonManagedWriter_1_1.textWriter(out, options, b);
152158
}
153159

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

160166
_Private_IonTextWriterBuilder_1_1 b = fillDefaults();
161-
ManagedWriterOptions_1_1 options = new ManagedWriterOptions_1_1(false, symbolInliningStrategy, LengthPrefixStrategy.NEVER_PREFIXED);
167+
ManagedWriterOptions_1_1 options = new ManagedWriterOptions_1_1(
168+
false,
169+
symbolInliningStrategy,
170+
LengthPrefixStrategy.NEVER_PREFIXED,
171+
// This could be made configurable.
172+
ManagedWriterOptions_1_1.EExpressionIdentifierStrategy.BY_NAME
173+
);
162174
return IonManagedWriter_1_1.textWriter(out, options, b);
163175
}
164176

0 commit comments

Comments
 (0)