diff --git a/src/displaystring.ts b/src/displaystring.ts new file mode 100644 index 0000000..fac2c58 --- /dev/null +++ b/src/displaystring.ts @@ -0,0 +1,16 @@ +export class DisplayString { + + private value: string; + constructor(value: string) { + + this.value = value; + + } + + toString(): string { + + return this.value; + + } + +} diff --git a/src/index.ts b/src/index.ts index 1bed8df..fa4a463 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,3 +3,4 @@ export * from './parser'; export * from './types'; export * from './util'; export { Token } from './token'; +export { DisplayString } from './displaystring'; diff --git a/src/parser.ts b/src/parser.ts index 9e454f5..d34e99c 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -11,6 +11,7 @@ import { import { Token } from './token'; import { isAscii } from './util'; +import { DisplayString } from './displaystring'; export function parseDictionary(input: string): Dictionary { @@ -185,6 +186,9 @@ export default class Parser { if (char === '@') { return this.parseDate(); } + if (char === '%') { + return this.parseDisplayString(); + } throw new ParseError(this.pos, 'Unexpected input'); } @@ -299,6 +303,32 @@ export default class Parser { } + private parseDisplayString(): DisplayString { + + this.expectChar('%'); + this.pos++; + this.expectChar('"'); + this.pos++; + + let result = new Uint8Array(); + + while (!this.eof()) { + + const char = this.getChar(); + if (char.charCodeAt(0) <= 0x1F || (char.charCodeAt(0) >= 0x7F && char.charCodeAt(0) <= 0xFF)) { + throw new ParseError('Invalid byte found at offset: ' + this.pos); + } + + if (char==='%') { + const hexChars = this.input.substr(this.pos,2); + if (/^[0-9a-f]{2}$/.test(hexChars)) { + + } + + return new DisplayString(result); + + } + private parseToken(): Token { // The specification wants this check, but it's an unreachable code block. diff --git a/src/serializer.ts b/src/serializer.ts index 4c6ac77..da31764 100644 --- a/src/serializer.ts +++ b/src/serializer.ts @@ -11,6 +11,7 @@ import { import { Token } from './token'; import { isAscii, isInnerList, isValidKeyStr } from './util'; +import { DisplayString } from './displaystring'; export class SerializeError extends Error {} @@ -80,6 +81,9 @@ export function serializeBareItem(input: BareItem): string { if (input instanceof ByteSequence) { return serializeByteSequence(input); } + if (input instanceof DisplayString) { + return serializeDisplayString(input); + } if (input instanceof Date) { return serializeDate(input); } @@ -114,6 +118,10 @@ export function serializeString(input: string): string { return `"${input.replace(/("|\\)/g, (v) => '\\' + v)}"`; } +export function serializeDisplayString(input: DisplayString): string { + return '%' + serializeString(input.toString()); +} + export function serializeBoolean(input: boolean): string { return input ? '?1' : '?0'; } diff --git a/src/types.ts b/src/types.ts index 7f293a5..cba19a9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,4 +1,5 @@ import { Token } from './token'; +import { DisplayString } from './displaystring'; /** * Lists are arrays of zero or more members, each of which can be an Item @@ -47,6 +48,6 @@ export class ByteSequence { } -export type BareItem = number | string | Token | ByteSequence | Date | boolean; +export type BareItem = number | string | Token | ByteSequence | Date | boolean | DisplayString; export type Item = [BareItem, Parameters]; diff --git a/test/httpwg-tests.js b/test/httpwg-tests.js index b925a23..dbaea4c 100644 --- a/test/httpwg-tests.js +++ b/test/httpwg-tests.js @@ -10,7 +10,7 @@ const { ParseError, } = require('../dist'); -const { Token, ByteSequence } = require('../dist'); +const { Token, ByteSequence, DisplayString } = require('../dist'); const base32Encode = require('base32-encode'); const base32Decode = require('base32-decode'); const fs = require('fs'); @@ -24,6 +24,7 @@ describe('HTTP-WG tests', () => { 'string', 'token', 'date', + 'display-string', 'item', @@ -284,6 +285,12 @@ function packTestValue(input) { value: input.toString() } } + if(input instanceof DisplayString) { + return { + __type: 'displaystring', + value: input.toString() + } + } if (input instanceof ByteSequence) { return { __type: 'binary', @@ -340,6 +347,8 @@ function unpackTestValue(input) { return new ByteSequence(Buffer.from(base32Decode(input.value, 'RFC4648')).toString('base64')); case 'date' : return new Date(input.value * 1000); + case 'displaystring' : + return new DisplayString(input.value); default: throw new Error('Unknown input __type: ' + input.__type); }