@@ -2,14 +2,14 @@ import ConverterStream from './ConverterStream' | |||||
import { ReadStreamOptions, ConvertOptions, NumberSystem, Digit } from './common' | import { ReadStreamOptions, ConvertOptions, NumberSystem, Digit } from './common' | ||||
export default class Converter { | export default class Converter { | ||||
constructor(private readonly system: NumberSystem) {} | |||||
constructor(private readonly system: NumberSystem, private options: ConvertOptions) {} | |||||
public convert = (value: string | number | bigint, options: ConvertOptions): string => { | |||||
public convert = (value: string | number | bigint): string => { | |||||
let converted: string[] = [] | let converted: string[] = [] | ||||
switch (typeof value!) { | switch (typeof value!) { | ||||
case 'string': | case 'string': | ||||
case 'number': | case 'number': | ||||
return this.convert(BigInt(value), options) | |||||
return this.convert(BigInt(value)) | |||||
case 'bigint': | case 'bigint': | ||||
let current = value as bigint | let current = value as bigint | ||||
let thousandPower = 0n | let thousandPower = 0n | ||||
@@ -22,7 +22,7 @@ export default class Converter { | |||||
let kiloCount: string | let kiloCount: string | ||||
if (!(ones === 0 && tens === 0 && hundreds === 0)) { | if (!(ones === 0 && tens === 0 && hundreds === 0)) { | ||||
if (thousandPower > 0n) { | if (thousandPower > 0n) { | ||||
const { scale = 'short' } = options | |||||
const { scale = 'short' } = this.options | |||||
kiloName = this.system.getKiloName[scale!]!(thousandPower) | kiloName = this.system.getKiloName[scale!]!(thousandPower) | ||||
} | } | ||||
kiloCount = this.system.getKiloCount(hundreds, tens, ones) | kiloCount = this.system.getKiloCount(hundreds, tens, ones) | ||||
@@ -39,8 +39,7 @@ export default class Converter { | |||||
throw TypeError('Invalid argument passed to value.') | throw TypeError('Invalid argument passed to value.') | ||||
} | } | ||||
readStream(options: ReadStreamOptions): ConverterStream { | |||||
const { scale = 'short', encoding = 'utf-8' } = options | |||||
return new ConverterStream(this.system, { scale, encoding }) | |||||
public readStream = (streamOptions: ReadStreamOptions): ConverterStream => { | |||||
return new ConverterStream(this.convert, streamOptions) | |||||
} | } | ||||
} | } |
@@ -1,47 +1,26 @@ | |||||
import { Transform } from 'stream' | import { Transform } from 'stream' | ||||
import { Digit, NumberSystem, ReadStreamOptions } from './common' | |||||
import { StreamOptions } from './common' | |||||
export default class ConverterStream extends Transform { | export default class ConverterStream extends Transform { | ||||
private thousandPower: bigint = 0n | |||||
private bigintBuffer: bigint = 0n | |||||
private buffer = Buffer.from([]) | |||||
constructor(private readonly system: NumberSystem, private readonly options: ReadStreamOptions) { | |||||
constructor( | |||||
private readonly converter: (value: string | number | bigint) => string, | |||||
readonly options: StreamOptions, | |||||
) { | |||||
super() | super() | ||||
this.thousandPower = 0n | |||||
} | } | ||||
_transform(chunk: Buffer, _encoding: BufferEncoding, callback: Function) { | _transform(chunk: Buffer, _encoding: BufferEncoding, callback: Function) { | ||||
const { scale, encoding } = this.options | |||||
const [ones = 0, tens = 0, hundreds = 0] = chunk | |||||
.toString(encoding!) | |||||
.split('') | |||||
.filter((s: string) => /[0-9]/.test(s)) | |||||
.map((d: string) => Number(d) as Digit) // todo use encoding | |||||
let kiloName: string | undefined | |||||
let kiloCount: string | |||||
if (!(ones === 0 && tens === 0 && hundreds === 0)) { | |||||
if (this.thousandPower > 0n) { | |||||
kiloName = this.system.getKiloName[scale!]!(this.thousandPower) | |||||
} | |||||
kiloCount = this.system.getKiloCount(hundreds, tens, ones) | |||||
this.buffer = Buffer.concat([ | |||||
Buffer.from(this.system.joinKilo(kiloCount, kiloName), encoding), | |||||
Buffer.from(' ', encoding), | |||||
this.buffer, | |||||
]) | |||||
} | |||||
this.thousandPower = this.thousandPower + 1n | |||||
let chunkStr = chunk.toString(this.options.encoding) | |||||
// we might run out of allocation for bigints? | |||||
this.bigintBuffer *= 10n ** BigInt(chunkStr.length) | |||||
this.bigintBuffer += BigInt(chunkStr) | |||||
callback() | callback() | ||||
} | } | ||||
_flush(callback: Function) { | _flush(callback: Function) { | ||||
const { encoding } = this.options | |||||
this.push(this.buffer, encoding) | |||||
this.push(this.converter(this.bigintBuffer), this.options.encoding) | |||||
callback() | callback() | ||||
} | } | ||||
} | } |
@@ -10,7 +10,7 @@ describe.each` | |||||
let converter: Converter | let converter: Converter | ||||
beforeAll(() => { | beforeAll(() => { | ||||
converter = new Converter(system) | |||||
converter = new Converter(system, { scale, }) | |||||
}) | }) | ||||
describe('on values', () => { | describe('on values', () => { | ||||
@@ -19,7 +19,7 @@ describe.each` | |||||
${1000000} | ${'one million'} | ${1000000} | ${'one million'} | ||||
${123456789} | ${'one hundred twenty three million four hundred fifty six thousand seven hundred eighty nine'} | ${123456789} | ${'one hundred twenty three million four hundred fifty six thousand seven hundred eighty nine'} | ||||
`('should parse $value as $name', ({ value, name, }) => { | `('should parse $value as $name', ({ value, name, }) => { | ||||
expect(converter.convert(value, { scale })).toBe(name) | |||||
expect(converter.convert(value)).toBe(name) | |||||
}) | }) | ||||
}) | }) | ||||
@@ -27,22 +27,26 @@ describe.each` | |||||
const ENCODING = 'utf-8' | const ENCODING = 'utf-8' | ||||
test.each([ | test.each([ | ||||
'million.txt' | |||||
'million', | |||||
'example1', | |||||
'example2', | |||||
'example3', | |||||
'example4', | |||||
'example5', | |||||
'example6', | |||||
])('should correctly parse a stream', async (filename) => { | ])('should correctly parse a stream', async (filename) => { | ||||
const inputStream = fs.createReadStream( | const inputStream = fs.createReadStream( | ||||
`./tests/input/${filename}`, | |||||
`./tests/input/${filename}.txt`, | |||||
{ | { | ||||
encoding: ENCODING, | encoding: ENCODING, | ||||
highWaterMark: 3, // this is required to parse kilos correctly | |||||
} | } | ||||
) | ) | ||||
const readStream = converter.readStream({ | const readStream = converter.readStream({ | ||||
scale, | |||||
encoding: ENCODING | encoding: ENCODING | ||||
}) | }) | ||||
inputStream | inputStream | ||||
.pipe(readStream) | .pipe(readStream) | ||||
.pipe(fs.createWriteStream(`./tests/output/${filename}`)) | |||||
.pipe(fs.createWriteStream(`./tests/output/${filename}.${scale}.txt`)) | |||||
return new Promise((resolve) => { | return new Promise((resolve) => { | ||||
readStream.on('end', () => { | readStream.on('end', () => { | ||||
@@ -0,0 +1 @@ | |||||
987654321 |
@@ -0,0 +1 @@ | |||||
123456789246801357 |
@@ -0,0 +1 @@ | |||||
123456789246801357000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
@@ -0,0 +1 @@ | |||||
123456789246801357000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
@@ -0,0 +1 @@ | |||||
123456789246801357000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
@@ -0,0 +1 @@ | |||||
123456789246801357000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
@@ -1 +1 @@ | |||||
987000321 | |||||
1000000 |