Skip to content

Commit 1b3fb7d

Browse files
committed
Fixed #63
1 parent e9a275d commit 1b3fb7d

File tree

4 files changed

+35
-33
lines changed

4 files changed

+35
-33
lines changed

dist/types/enum.d.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,15 @@ export default class EnumType<E> extends AbstractType<E> {
3333
*/
3434
readonly values: E[];
3535
private readonly type;
36-
private readonly valueIndices;
36+
private cachedValueIndices;
3737
/**
3838
* @param type The type of each element in the tuple
3939
* @param values The possible distinct values.
4040
* Cannot contain more than 255 values.
4141
* @throws If any value cannot be serialized by `type`
4242
*/
4343
constructor({ type, values }: EnumParams<E>);
44+
private readonly valueIndices;
4445
addToBuffer(buffer: AppendableBuffer): boolean;
4546
/**
4647
* Appends value bytes to an [[AppendableBuffer]] according to the type

dist/types/enum.js

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,16 @@ class EnumType extends abstract_1.default {
4444
catch (e) {
4545
assert_1.default.fail(String(values.length) + ' values is too many');
4646
}
47+
this.type = type;
48+
this.values = values; //used when reading to get constant-time lookup of value index into value
49+
}
50+
static get _value() {
51+
return 0x55;
52+
}
53+
get valueIndices() {
54+
const { type, values, cachedValueIndices } = this;
55+
if (cachedValueIndices)
56+
return cachedValueIndices;
4757
const valueIndices = new Map();
4858
for (let i = 0; i < values.length; i++) {
4959
const value = values[i];
@@ -52,18 +62,13 @@ class EnumType extends abstract_1.default {
5262
assert_1.default.fail('Value is repeated: ' + util_inspect_1.inspect(value));
5363
valueIndices.set(valueString, i); //so writing a value has constant-time lookup into the values array
5464
}
55-
this.type = type;
56-
this.values = values; //used when reading to get constant-time lookup of value index into value
57-
this.valueIndices = valueIndices;
58-
}
59-
static get _value() {
60-
return 0x55;
65+
return this.cachedValueIndices = valueIndices;
6166
}
6267
addToBuffer(buffer) {
6368
/*istanbul ignore else*/
6469
if (super.addToBuffer(buffer)) {
6570
this.type.addToBuffer(buffer);
66-
buffer.add(this.valueIndices.size);
71+
buffer.add(this.values.length);
6772
for (const valueBuffer of this.valueIndices.keys()) {
6873
buffer.addAll(bufferString.fromBinaryString(valueBuffer));
6974
}
@@ -94,13 +99,10 @@ class EnumType extends abstract_1.default {
9499
consumeValue(buffer, offset) {
95100
assert_1.default(buffer.byteLength > offset, read_util_1.NOT_LONG_ENOUGH);
96101
const valueIndex = new Uint8Array(buffer)[offset];
97-
//Can't check for value === undefined since value could be undefined with OptionalType
98-
const { values } = this;
99-
assert_1.default(valueIndex in values, 'Index ' + String(valueIndex) + ' is invalid');
100-
return {
101-
value: values[valueIndex],
102-
length: 1
103-
};
102+
const value = this.values[valueIndex];
103+
if (value === undefined)
104+
throw new Error('Index ' + String(valueIndex) + ' is invalid');
105+
return { value, length: 1 };
104106
}
105107
equals(otherType) {
106108
if (!super.equals(otherType))

test/type-bytes/enum.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,10 @@ export = () => {
1616
[tooManyValues, '256 values is too many']
1717
]) {
1818
assert.throws(
19-
() => {
20-
new t.EnumType({
21-
type: new t.StringType,
22-
values: invalidValues as any
23-
})
24-
},
19+
() => new t.EnumType({
20+
type: new t.StringType,
21+
values: invalidValues as any
22+
}).toBuffer(),
2523
message as string
2624
)
2725
}

types/enum.ts

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export default class EnumType<E> extends AbstractType<E> {
4040
*/
4141
readonly values: E[]
4242
private readonly type: Type<E>
43-
private readonly valueIndices: Map<string, number>
43+
private cachedValueIndices: Map<string, number> | undefined
4444
/**
4545
* @param type The type of each element in the tuple
4646
* @param values The possible distinct values.
@@ -55,22 +55,27 @@ export default class EnumType<E> extends AbstractType<E> {
5555
try { assert.byteUnsignedInteger(values.length) }
5656
catch (e) { assert.fail(String(values.length) + ' values is too many') }
5757

58+
this.type = type
59+
this.values = values //used when reading to get constant-time lookup of value index into value
60+
}
61+
private get valueIndices() {
62+
const {type, values, cachedValueIndices} = this
63+
if (cachedValueIndices) return cachedValueIndices
64+
5865
const valueIndices = new Map<string, number>()
5966
for (let i = 0; i < values.length; i++) {
6067
const value = values[i]
6168
const valueString = bufferString.toBinaryString(type.valueBuffer(value)) //convert value to bytes and then string for use as a map key
6269
if (valueIndices.has(valueString)) assert.fail('Value is repeated: ' + inspect(value))
6370
valueIndices.set(valueString, i) //so writing a value has constant-time lookup into the values array
6471
}
65-
this.type = type
66-
this.values = values //used when reading to get constant-time lookup of value index into value
67-
this.valueIndices = valueIndices
72+
return this.cachedValueIndices = valueIndices
6873
}
6974
addToBuffer(buffer: AppendableBuffer) {
7075
/*istanbul ignore else*/
7176
if (super.addToBuffer(buffer)) {
7277
this.type.addToBuffer(buffer)
73-
buffer.add(this.valueIndices.size)
78+
buffer.add(this.values.length)
7479
for (const valueBuffer of this.valueIndices.keys()) {
7580
buffer.addAll(bufferString.fromBinaryString(valueBuffer))
7681
}
@@ -100,13 +105,9 @@ export default class EnumType<E> extends AbstractType<E> {
100105
consumeValue(buffer: ArrayBuffer, offset: number): ReadResult<E> {
101106
assert(buffer.byteLength > offset, NOT_LONG_ENOUGH)
102107
const valueIndex = new Uint8Array(buffer)[offset]
103-
//Can't check for value === undefined since value could be undefined with OptionalType
104-
const {values} = this
105-
assert(valueIndex in values, 'Index ' + String(valueIndex) + ' is invalid')
106-
return {
107-
value: values[valueIndex],
108-
length: 1
109-
}
108+
const value = this.values[valueIndex] as E | undefined
109+
if (value === undefined) throw new Error('Index ' + String(valueIndex) + ' is invalid')
110+
return {value, length: 1}
110111
}
111112
equals(otherType: any) {
112113
if (!super.equals(otherType)) return false

0 commit comments

Comments
 (0)