Skip to content

Commit

Permalink
feat(json-pack): 🎸 add ability to encode binary types
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Dec 10, 2023
1 parent 773a217 commit 687bb76
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 8 deletions.
40 changes: 32 additions & 8 deletions src/json-pack/resp/RespEncoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ export class RespEncoder<W extends IWriter & IWriterGrowable = IWriter & IWriter
return this.writeBoolean(value);
case 'object': {
if (!value) return this.writeNull();
if (value instanceof Array) return this.writeArr(value as unknown[]);
if (value instanceof Array) return this.writeArr(value);
if (value instanceof Uint8Array) return this.writeBin(value);
if (value instanceof Error) return this.writeErr(value.message);
if (value instanceof Set) return this.writeSet(value);
return this.writeObj(value as Record<string, unknown>);
Expand Down Expand Up @@ -115,11 +116,18 @@ export class RespEncoder<W extends IWriter & IWriterGrowable = IWriter & IWriter
}

public writeBin(buf: Uint8Array): void {
throw new Error('Not implemented');
const writer = this.writer;
const length = buf.length;
writer.u8(36); // $
writer.ascii(length + '');
writer.u16(RESP.RN); // \r\n
writer.buf(buf, length);
writer.u16(RESP.RN); // \r\n
}

public writeBinHdr(length: number): void {
throw new Error('Not implemented');
// Because then we also need `.writeBinBody()` which would emit trailing `\r\n`.
}

public writeStr(str: string): void {
Expand All @@ -128,6 +136,7 @@ export class RespEncoder<W extends IWriter & IWriterGrowable = IWriter & IWriter

public writeStrHdr(length: number): void {
throw new Error('Not implemented');
// Because then we also need `.writeBinBody()` which would emit trailing `\r\n`.
}

public writeSimpleStr(str: string): void {
Expand Down Expand Up @@ -326,26 +335,41 @@ export class RespEncoder<W extends IWriter & IWriterGrowable = IWriter & IWriter
}

public writeStartArr(): void {
throw new Error('Not implemented');
this.writer.u32(
42 * 0x1000000 + // *
(63 << 16) + // ?
RESP.RN, // \r\n
);
}

public writeArrChunk(item: unknown): void {
throw new Error('Not implemented');
this.writeAny(item);
}

public writeEndArr(): void {
throw new Error('Not implemented');
this.writer.u8u16(
46, // .
RESP.RN, // \r\n
);
}

public writeStartObj(): void {
throw new Error('Not implemented');
this.writer.u32(
37 * 0x1000000 + // %
(63 << 16) + // ?
RESP.RN, // \r\n
);
}

public writeObjChunk(key: string, value: unknown): void {
throw new Error('Not implemented');
this.writeStr(key);
this.writeAny(value);
}

public writeEndObj(): void {
throw new Error('Not implemented');
this.writer.u8u16(
46, // .
RESP.RN, // \r\n
);
}
}
16 changes: 16 additions & 0 deletions src/json-pack/resp/__tests__/RespEncoder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,22 @@ describe('strings', () => {
});
});

describe('binary', () => {
test('empty blob', () => {
const encoder = new RespEncoder();
const encoded = encoder.encode(new Uint8Array(0));
expect(toStr(encoded)).toBe('$0\r\n\r\n');
expect(parse(encoded)).toBe('');
});

test('small blob', () => {
const encoder = new RespEncoder();
const encoded = encoder.encode(new Uint8Array([65, 66]));
expect(toStr(encoded)).toBe('$2\r\nAB\r\n');
expect(parse(encoded)).toBe('AB');
});
});

describe('.writeAsciiString()', () => {
test('can write "OK"', () => {
const encoder = new RespEncoder();
Expand Down

0 comments on commit 687bb76

Please sign in to comment.