Skip to content

Commit 482281e

Browse files
committed
feat(json-pack): 🎸 implement command decoding
1 parent 948c6cf commit 482281e

File tree

3 files changed

+54
-1
lines changed

3 files changed

+54
-1
lines changed

src/json-pack/resp/RespDecoder.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,25 @@ export class RespDecoder<R extends IReader & IReaderResettable = IReader & IRead
8181
}
8282
}
8383

84+
public readCmd(): [cmd: string, ...args: Uint8Array[]] {
85+
const reader = this.reader;
86+
const type = reader.u8();
87+
if (type !== RESP.ARR) throw new Error('INVALID_COMMAND');
88+
const c = reader.peak();
89+
if (c === RESP.MINUS) throw new Error('INVALID_COMMAND');
90+
const length = this.readLength();
91+
if (length === 0) throw new Error('INVALID_COMMAND');
92+
const cmd = this.readAsciiAsStrBulk().toUpperCase();
93+
const args: [cmd: string, ...args: Uint8Array[]] = [cmd];
94+
this.tryUtf8 = false;
95+
for (let i = 1; i < length; i++) {
96+
const type = reader.u8();
97+
if (type !== RESP.STR_BULK) throw new Error('INVALID_COMMAND');
98+
args.push(this.readStrBulk() as Uint8Array);
99+
}
100+
return args;
101+
}
102+
84103
// ---------------------------------------------------------- Boolean reading
85104

86105
public readBool(): boolean {

src/json-pack/resp/__tests__/RespDecoder.spec.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {RespDecoder} from '../RespDecoder';
33
import {bufferToUint8Array} from '../../../util/buffers/bufferToUint8Array';
44
import {RespAttributes, RespPush} from '../extensions';
55
import {Writer} from '../../../util/buffers/Writer';
6-
import {Uint} from '@automerge/automerge';
6+
import {utf8} from '../../../util/buffers/strings';
77

88
const decode = (encoded: string | Uint8Array): unknown => {
99
const decoder = new RespDecoder();
@@ -215,3 +215,21 @@ describe('nulls', () => {
215215
expect(decoded).toBe(null);
216216
});
217217
});
218+
219+
describe('commands', () => {
220+
test('can decode a PING command', () => {
221+
const encoded = encoder.encodeCmd(['PING']);
222+
const decoder = new RespDecoder();
223+
decoder.reader.reset(encoded);
224+
const decoded = decoder.readCmd();
225+
expect(decoded).toEqual(['PING']);
226+
});
227+
228+
test('can decode a SET command', () => {
229+
const encoded = encoder.encodeCmd(['SET', 'foo', 'bar']);
230+
const decoder = new RespDecoder();
231+
decoder.reader.reset(encoded);
232+
const decoded = decoder.readCmd();
233+
expect(decoded).toEqual(['SET', utf8`foo`, utf8`bar`]);
234+
});
235+
});

src/util/buffers/strings.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {bufferToUint8Array} from "./bufferToUint8Array";
2+
3+
export const ascii = (txt: TemplateStringsArray | string | [string]): Uint8Array => {
4+
if (typeof txt === 'string') return ascii([txt]);
5+
[txt] = txt;
6+
const len = txt.length;
7+
const res = new Uint8Array(len);
8+
for (let i = 0; i < len; i++) res[i] = txt.charCodeAt(i);
9+
return res;
10+
};
11+
12+
export const utf8 = (txt: TemplateStringsArray | [string] | string): Uint8Array => {
13+
if (typeof txt === 'string') return utf8([txt]);
14+
[txt] = txt;
15+
return bufferToUint8Array(Buffer.from(txt, 'utf8'));
16+
};

0 commit comments

Comments
 (0)