diff --git a/src/IonBinaryReader.ts b/src/IonBinaryReader.ts index b162104c..0a215ffa 100644 --- a/src/IonBinaryReader.ts +++ b/src/IonBinaryReader.ts @@ -130,7 +130,7 @@ export class BinaryReader implements Reader { if (this._parser.getAnnotation(0) !== ion_symbol_table_sid) { break; } - this._symtab = makeSymbolTable(this._cat, this); + this._symtab = makeSymbolTable(this._cat, this, this._symtab); } else { break; } diff --git a/src/IonSymbols.ts b/src/IonSymbols.ts index 084e2c74..38718828 100644 --- a/src/IonSymbols.ts +++ b/src/IonSymbols.ts @@ -20,6 +20,7 @@ import { Reader } from "./IonReader"; import { SharedSymbolTable } from "./IonSharedSymbolTable"; import { SubstituteSymbolTable } from "./IonSubstituteSymbolTable"; import { getSystemSymbolTableImport } from "./IonSystemSymbolTable"; +import { IonTypes } from "./Ion"; export const ion_symbol_table = "$ion_symbol_table"; export const ion_symbol_table_sid = 3; @@ -100,15 +101,18 @@ function load_symbols(reader: Reader): (string | null)[] { * * @param catalog The catalog to resolve imported shared symbol tables from. * @param reader The Ion {Reader} over the local symbol table in its serialized form. + * @param currentSymbolTable Current local symbol table for the reader. */ export function makeSymbolTable( catalog: Catalog, - reader: Reader + reader: Reader, + currentSymbolTable: LocalSymbolTable ): LocalSymbolTable { let import_: Import | null = null; let symbols: (string | null)[] = []; let foundSymbols: boolean = false; let foundImports: boolean = false; + let foundLstAppend: boolean = false; reader.stepIn(); while (reader.next()) { @@ -117,14 +121,35 @@ export function makeSymbolTable( if (foundImports) { throw new Error("Multiple import fields found."); } - import_ = load_imports(reader, catalog); + let ion_type = reader.type(); + if ( + ion_type === IonTypes.SYMBOL && + reader.stringValue() === ion_symbol_table + ) { + // this is a local symbol table append + import_ = currentSymbolTable.import; + let symbols_ = symbols; + symbols = currentSymbolTable.symbols; + symbols.push(...symbols_); + foundLstAppend = true; + } else if (ion_type === IonTypes.LIST) { + import_ = load_imports(reader, catalog); + } else { + throw new Error( + `Expected import field name to be a list or symbol found ${ion_type}` + ); + } foundImports = true; break; case "symbols": if (foundSymbols) { throw new Error("Multiple symbol fields found."); } - symbols = load_symbols(reader); + if (foundLstAppend) { + symbols.push(...load_symbols(reader)); + } else { + symbols = load_symbols(reader); + } foundSymbols = true; break; } diff --git a/src/IonTextReader.ts b/src/IonTextReader.ts index 0966d193..820f1ccc 100644 --- a/src/IonTextReader.ts +++ b/src/IonTextReader.ts @@ -190,7 +190,7 @@ export class TextReader implements Reader { break; } this._type = get_ion_type(this._raw_type); - this._symtab = makeSymbolTable(this._cat, this); + this._symtab = makeSymbolTable(this._cat, this, this._symtab); this._raw = undefined; this._raw_type = undefined; } else { diff --git a/test/IonTextReader.ts b/test/IonTextReader.ts index 6de7f518..cca267fd 100644 --- a/test/IonTextReader.ts +++ b/test/IonTextReader.ts @@ -97,6 +97,19 @@ class IonTextReaderTests { assert.equal(ionReader.stringValue(), 'taco'); } + @test "resolves symbol IDs for symbol table append"() { + let ionToRead = `$ion_symbol_table::{ symbols:[ "foo", "bar" ]} $ion_symbol_table::{ imports: $ion_symbol_table, symbols:[ "baz" ]}[$10, $11, $12]`; + let ionReader = ion.makeReader(ionToRead); + ionReader.next(); + ionReader.stepIn(); + ionReader.next(); + assert.equal(ionReader.stringValue(), "foo"); + ionReader.next(); + assert.equal(ionReader.stringValue(), "bar"); + ionReader.next(); + assert.equal(ionReader.stringValue(), "baz"); + } + @test "Parse through struct"() { let ionToRead = "{ key : \"string\" }"; let ionReader = ion.makeReader(ionToRead); diff --git a/test/iontests.ts b/test/iontests.ts index 7197fcc4..43bee257 100644 --- a/test/iontests.ts +++ b/test/iontests.ts @@ -459,7 +459,6 @@ let equivsSkipList = toSkipList([ "ion-tests/iontestdata/good/equivs/decimalsWithUnderscores.ion", "ion-tests/iontestdata/good/equivs/floatsWithUnderscores.ion", "ion-tests/iontestdata/good/equivs/intsWithUnderscores.ion", - "ion-tests/iontestdata/good/equivs/localSymbolTableAppend.ion", "ion-tests/iontestdata/good/equivs/localSymbolTableNullSlots.ion", "ion-tests/iontestdata/good/equivs/localSymbolTables.ion", "ion-tests/iontestdata/good/equivs/nonIVMNoOps.ion",