(accessor: (expr: string) => string)
| 55 | } |
| 56 | |
| 57 | read(accessor: (expr: string) => string): string { |
| 58 | const codec = this.builder.getExternal(DecimalCodec.name); |
| 59 | const decimal = this.builder.getExternal(Decimal.name); |
| 60 | const scale = this.scope.uniqueName("decimal_scale"); |
| 61 | const header = this.scope.uniqueName("decimal_header"); |
| 62 | const meta = this.scope.uniqueName("decimal_meta"); |
| 63 | const length = this.scope.uniqueName("decimal_length"); |
| 64 | const magnitudeBytes = this.scope.uniqueName("decimal_magnitude_bytes"); |
| 65 | const magnitude = this.scope.uniqueName("decimal_magnitude"); |
| 66 | const unscaled = this.scope.uniqueName("decimal_unscaled"); |
| 67 | return ` |
| 68 | const ${scale} = ${this.builder.reader.readVarInt32()}; |
| 69 | const ${header} = ${this.builder.reader.readVarUInt64()}; |
| 70 | if ((${header} & 1n) === 0n) { |
| 71 | ${accessor(`new ${decimal}(${codec}.decodeZigZag64(${header} >> 1n), ${scale})`)} |
| 72 | } else { |
| 73 | const ${meta} = ${header} >> 1n; |
| 74 | const ${length} = Number(${meta} >> 1n); |
| 75 | if (${length} <= 0 || ${length} > 0x7fffffff) { |
| 76 | throw new Error(\`Invalid decimal magnitude length \${${length}}.\`); |
| 77 | } |
| 78 | const ${magnitudeBytes} = ${this.builder.reader.buffer(length)}; |
| 79 | if (${magnitudeBytes}[${length} - 1] === 0) { |
| 80 | throw new Error("Non-canonical decimal magnitude bytes: trailing zero byte."); |
| 81 | } |
| 82 | const ${magnitude} = ${codec}.fromCanonicalLittleEndianMagnitude(${magnitudeBytes}); |
| 83 | if (${magnitude} === 0n) { |
| 84 | throw new Error("Big decimal encoding must not represent zero."); |
| 85 | } |
| 86 | const ${unscaled} = ((${meta} & 1n) === 0n) ? ${magnitude} : -${magnitude}; |
| 87 | ${accessor(`new ${decimal}(${unscaled}, ${scale})`)} |
| 88 | } |
| 89 | `; |
| 90 | } |
| 91 | |
| 92 | getFixedSize(): number { |
| 93 | return 20; |
nothing calls this directly
no test coverage detected