Skip to content

Commit

Permalink
Adding postion() API to Reader (#657)
Browse files Browse the repository at this point in the history
  • Loading branch information
bingkh authored Dec 21, 2020
1 parent 3c7a67c commit 7d4bbc6
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 0 deletions.
4 changes: 4 additions & 0 deletions src/IonBinaryReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ export class BinaryReader implements Reader {
this._raw_type = BOC;
}

position(): number {
return this._parser.source().position();
}

next(): IonType | null {
this._annotations = null;

Expand Down
4 changes: 4 additions & 0 deletions src/IonParserBinaryRaw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,10 @@ export class ParserBinaryRaw {
return Decimal._fromBigIntCoefficient(isNegative, coefficient, exponent);
}

source(): BinarySpan {
return this._in;
}

next(): any {
if (this._curr === undefined && this._len > 0) {
this._in.skip(this._len);
Expand Down
4 changes: 4 additions & 0 deletions src/IonParserTextRaw.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,10 @@ export class ParserTextRaw {
return this._fieldnameType;
}

source(): StringSpan {
return this._in;
}

annotations(): SymbolToken[] {
return this._ann;
}
Expand Down
22 changes: 22 additions & 0 deletions src/IonReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,28 @@ export type ReaderScalarValue =
* invoke [[next]] to position a newly created reader on the first value.
*/
export interface Reader {
/**
* Returns the Reader's offset from the beginning of its input.
*
* For binary Readers, the return value is the number of bytes that have
* been processed.
*
* For text Readers, the return value is the number of UTF-16 code units
* that have been processed, regardless of the input's original encoding.
* For more on JavaScript's in-memory representation of text, see:
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length#Description
*
* Note that a Reader cannot safely skip to a given position in input without
* processing the stream leading up to that position. This is because there are
* mid-stream system level values that must be processed to guarantee that the
* Reader is in a valid state. It is safe, however, to start at the beginning of a data
* source and call next() until you reach the desired position, as the reader
* will still have the opportunity to process system-level values along the way.)
*
* @returns the [[number]] of bytes or UTF-16 code units that the reader has processed.
*/
position(): number;

/**
* Advances the reader to the next value in the stream at the current depth.
*
Expand Down
4 changes: 4 additions & 0 deletions src/IonTextReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,10 @@ export class TextReader implements Reader {
return false;
}

position() {
return this._parser.source().position();
}

next() {
this._raw = undefined;
if (this._raw_type === EOF) {
Expand Down
47 changes: 47 additions & 0 deletions test/IonBinaryReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,51 @@ describe('Binary Reader', () => {
reader.next();
assert.deepEqual(reader.timestampValue(), timestamp);
});
it('test position', () => {
// In the comments below, the vertical bar '|' indicates the current position of the cursor at each step.
const ionBinary: Uint8Array = ion.dumpBinary(null, 7, -17, "Hello", [1, 2, 3]);
// [|0xE0, 0x1, 0x0, 0xEA, |0xF, |0x21, 0x7, |0x31, 0x11, |0x85, 0x48, 0x65, 0x6C, 0x6C, 0x6F, |0xB6, 0x21, 0x1, 0x21, 0x2, 0x21, 0x3 |]
// Version null 7 -17 "hello" [1,2,3]
const binaryReader = ion.makeReader(ionBinary);
// init pos 0
// [|0xE0, 0x1, 0x0, 0xEA, 0xF, 0x21, 0x7, 0x31, 0x11, 0x85, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0xB6, 0x21, 0x1, 0x21, 0x2, 0x21, 0x3]
assert.equal(binaryReader.position(), 0);
binaryReader.next();
// at null
// [0xE0, 0x1, 0x0, 0xEA, 0xF,| 0x21, 0x7, 0x31, 0x11, 0x85, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0xB6, 0x21, 0x1, 0x21, 0x2, 0x21, 0x3]
assert.equal(binaryReader.position(), 5);
binaryReader.next();
// at 7
// [0xE0, 0x1, 0x0, 0xEA, 0xF, 0x21, 0x7,| 0x31, 0x11, 0x85, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0xB6, 0x21, 0x1, 0x21, 0x2, 0x21, 0x3]
assert.equal(binaryReader.position(), 6);
binaryReader.next();
// at 17
// [0xE0, 0x1, 0x0, 0xEA, 0xF, 0x21, 0x7, 0x31, 0x11,| 0x85, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0xB6, 0x21, 0x1, 0x21, 0x2, 0x21, 0x3]
assert.equal(binaryReader.position(), 8);
binaryReader.next();
// at hello
// [0xE0, 0x1, 0x0, 0xEA, 0xF, 0x21, 0x7, 0x31, 0x11, 0x85, 0x48,| 0x65, 0x6C, 0x6C, 0x6F, 0xB6, 0x21, 0x1, 0x21, 0x2, 0x21, 0x3]
assert.equal(binaryReader.position(), 10);
binaryReader.next();
// at [1,2,3]
// [0xE0, 0x1, 0x0, 0xEA, 0xF, 0x21, 0x7, 0x31, 0x11, 0x85, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0xB6, 0x21,| 0x1, 0x21, 0x2, 0x21, 0x3]
assert.equal(binaryReader.position(), 16);
binaryReader.stepIn();
binaryReader.next();
// at 1
// [0xE0, 0x1, 0x0, 0xEA, 0xF, 0x21, 0x7, 0x31, 0x11, 0x85, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0xB6, 0x21, 0x1,| 0x21, 0x2, 0x21, 0x3]
assert.equal(binaryReader.position(), 17);
binaryReader.next();
// at 2
// [0xE0, 0x1, 0x0, 0xEA, 0xF, 0x21, 0x7, 0x31, 0x11, 0x85, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0xB6, 0x21, 0x1, 0x21, 0x2,| 0x21, 0x3]
assert.equal(binaryReader.position(), 19);
binaryReader.next();
// at 3
// [0xE0, 0x1, 0x0, 0xEA, 0xF, 0x21, 0x7, 0x31, 0x11, 0x85, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0xB6, 0x21, 0x1, 0x21, 0x2, 0x21, 0x3|]
assert.equal(binaryReader.position(), 21);
binaryReader.stepOut();
// out of stream
// [0xE0, 0x1, 0x0, 0xEA, 0xF, 0x21, 0x7, 0x31, 0x11, 0x85, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0xB6, 0x21, 0x1, 0x21, 0x2, 0x21, 0x3]|
assert.equal(binaryReader.position(), 22);
});
});
66 changes: 66 additions & 0 deletions test/IonTextReader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,4 +249,70 @@ class IonTextReaderTests {
IonTextReaderTests.ivmTest(textReader, unsupportedIVM[i], false, 0, ["taco"]);
}
}

@test "get position from reader" () {
const ionToRead = "ann1::{ key: valX } ann2::{ keyX: ['v1', 'v2'], keyY: ['v3', 'v4'] }";
const ionTextReader = ion.makeReader(ionToRead);

// In the comments below, the vertical bar '|' indicates the current position of the cursor at each step.
const pos1 = ionTextReader.position();
// |ann1::{ key: valX } ann2::{ keyX: ['v1', 'v2'], keyY: ['v3', 'v4'] }
assert.equal(pos1, 0);

ionTextReader.next();
// ann1::{| key: valX } ann2::{ keyX: ['v1', 'v2'], keyY: ['v3', 'v4'] }
const pos2 = ionTextReader.position();
assert.equal(pos2, 7);

ionTextReader.stepIn();
ionTextReader.next();
// ann1::{ key: valX |} ann2::{ keyX: ['v1', 'v2'], keyY: ['v3', 'v4'] }
const pos7 = ionTextReader.position();
assert.equal(pos7, 18);

ionTextReader.stepOut();
ionTextReader.next();
// ann1::{ key: valX } ann2::{| keyX: ['v1', 'v2'], keyY: ['v3', 'v4'] }
const pos3 = ionTextReader.position();
assert.equal(pos3, 27);

ionTextReader.stepIn();
ionTextReader.next();
// ann1::{ key: valX } ann2::{ keyX: [|'v1', 'v2'], keyY: ['v3', 'v4'] }
const pos4 = ionTextReader.position();
assert.equal(pos4, 35);

ionTextReader.stepIn();
ionTextReader.next();
// ann1::{ key: valX } ann2::{ keyX: ['v1'|, 'v2'], keyY: ['v3', 'v4'] }
const pos5 = ionTextReader.position();
assert.equal(pos5, 39);

ionTextReader.stepOut();
// ann1::{ key: valX } ann2::{ keyX: ['v1', 'v2']|, keyY: ['v3', 'v4'] }
const pos6 = ionTextReader.position();
assert.equal(pos6, 46);

ionTextReader.stepOut();
// ann1::{ key: valX } ann2::{ keyX: ['v1', 'v2'], keyY: ['v3', 'v4'] }|
const pos8 = ionTextReader.position();
assert.equal(pos8, 68);
}

@test "get position from multi-byte" () {

// 's': \u0073
// '好': \u597d
// 'の': \u306e
// 'ç': \u00e7
// '👩': \ud83d \udc69
// '👩🏽': \ud83d \udc69 \ud83c \udffd
const reader: ion.Reader = ion.makeReader("\"s\" \"好\" \"の\" \"ç\" \"👩\" \"👩🏽\"");

const pos = [3, 7, 11, 15, 20, 27];
let i = 0;
while (reader.next()) {
assert.equal(reader.position(), pos[i++]);
}
}
}

0 comments on commit 7d4bbc6

Please sign in to comment.