Skip to content

Commit

Permalink
Merge pull request #69 from UCNot/json-deserializer
Browse files Browse the repository at this point in the history
JSON deserializer
  • Loading branch information
surol authored Aug 15, 2023
2 parents 18afa4c + df37162 commit af2ff44
Show file tree
Hide file tree
Showing 13 changed files with 1,118 additions and 309 deletions.
73 changes: 73 additions & 0 deletions src/syntax/formats/charge/charge.deserializer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { beforeAll, describe, expect, it } from '@jest/globals';
import { esline } from 'esgen';
import { UcdCompiler } from '../../../compiler/deserialization/ucd-compiler.js';
import { UC_MODULE_CHURI } from '../../../compiler/impl/uc-modules.js';
import { ucMap } from '../../../schema/map/uc-map.js';
import { UcDeserializer } from '../../../schema/uc-deserializer.js';
import { ucUnknown } from '../../../schema/unknown/uc-unknown.js';
import { UcURIParamsLexer } from '../uri-params/uc-uri-params.lexer.js';
import { ucFormatCharge } from './uc-inset-charge.js';

describe('URI charge deserializer', () => {
describe('in default mode', () => {
let readValue: UcDeserializer<unknown>;

beforeAll(async () => {
const compiler = new UcdCompiler({
models: {
readValue: {
model: ucMap({
a: ucUnknown({ within: { uriParam: ucFormatCharge() } }),
}),
lexer: ({ emit }) => {
const Lexer = UC_MODULE_CHURI.import(UcURIParamsLexer.name);

return esline`return new ${Lexer}(${emit})`;
},
},
},
});

({ readValue } = await compiler.evaluate());
});

it('URI-decodes values', () => {
expect(readValue(`a='te%20st'`)).toEqual({ a: `te st'` });
expect(readValue(`a=te+st`)).toEqual({ a: 'te+st' });
expect(readValue(`a=%33`)).toEqual({ a: 3 });
});
});

describe('in plus-as-space mode', () => {
let readValue: UcDeserializer<unknown>;

beforeAll(async () => {
const compiler = new UcdCompiler({
models: {
readValue: {
model: ucMap({
a: ucUnknown({
within: {
uriParam: ucFormatCharge({ plusAsSpace: true }),
},
}),
}),
lexer: ({ emit }) => {
const Lexer = UC_MODULE_CHURI.import(UcURIParamsLexer.name);

return esline`return new ${Lexer}(${emit})`;
},
},
},
});

({ readValue } = await compiler.evaluate());
});

it('decodes URI charge values', () => {
expect(readValue(`a='te%20st'`)).toEqual({ a: `te st'` });
expect(readValue(`a='te+st'`)).toEqual({ a: `te st'` });
expect(readValue(`a=%33`)).toEqual({ a: 3 });
});
});
});
74 changes: 1 addition & 73 deletions src/syntax/formats/charge/uc-charge.lexer.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import { beforeAll, beforeEach, describe, expect, it } from '@jest/globals';
import { esline } from 'esgen';
import { UcdCompiler } from '../../../compiler/deserialization/ucd-compiler.js';
import { UC_MODULE_CHURI } from '../../../compiler/impl/uc-modules.js';
import { ucMap } from '../../../schema/map/uc-map.js';
import { UcDeserializer } from '../../../schema/uc-deserializer.js';
import { ucUnknown } from '../../../schema/unknown/uc-unknown.js';
import { beforeEach, describe, expect, it } from '@jest/globals';
import {
UC_TOKEN_AMPERSAND,
UC_TOKEN_APOSTROPHE,
Expand All @@ -31,9 +25,7 @@ import {
UC_TOKEN_SLASH,
UcToken,
} from '../../uc-token.js';
import { UcURIParamsLexer } from '../uri-params/uc-uri-params.lexer.js';
import { UcChargeLexer } from './uc-charge.lexer.js';
import { ucFormatCharge } from './uc-inset-charge.js';

describe('UcChargeLexer', () => {
let lexer: UcChargeLexer;
Expand Down Expand Up @@ -231,67 +223,3 @@ describe('UcChargeLexer', () => {
});
});
});

describe('ucInsetCharge', () => {
describe('in default mode', () => {
let readValue: UcDeserializer<unknown>;

beforeAll(async () => {
const compiler = new UcdCompiler({
models: {
readValue: {
model: ucMap({
a: ucUnknown({ within: { uriParam: ucFormatCharge() } }),
}),
lexer: ({ emit }) => {
const Lexer = UC_MODULE_CHURI.import(UcURIParamsLexer.name);

return esline`return new ${Lexer}(${emit})`;
},
},
},
});

({ readValue } = await compiler.evaluate());
});

it('URI-decodes values', () => {
expect(readValue(`a='te%20st'`)).toEqual({ a: `te st'` });
expect(readValue(`a=te+st`)).toEqual({ a: 'te+st' });
expect(readValue(`a=%33`)).toEqual({ a: 3 });
});
});

describe('in plus-as-space mode', () => {
let readValue: UcDeserializer<unknown>;

beforeAll(async () => {
const compiler = new UcdCompiler({
models: {
readValue: {
model: ucMap({
a: ucUnknown({
within: {
uriParam: ucFormatCharge({ plusAsSpace: true }),
},
}),
}),
lexer: ({ emit }) => {
const Lexer = UC_MODULE_CHURI.import(UcURIParamsLexer.name);

return esline`return new ${Lexer}(${emit})`;
},
},
},
});

({ readValue } = await compiler.evaluate());
});

it('decodes URI charge values', () => {
expect(readValue(`a='te%20st'`)).toEqual({ a: `te st'` });
expect(readValue(`a='te+st'`)).toEqual({ a: `te st'` });
expect(readValue(`a=%33`)).toEqual({ a: 3 });
});
});
});
88 changes: 88 additions & 0 deletions src/syntax/formats/json/json.deserializer.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { beforeAll, describe, expect, it } from '@jest/globals';
import { esline } from 'esgen';
import { UcdCompiler } from '../../../compiler/deserialization/ucd-compiler.js';
import { UC_MODULE_CHURI } from '../../../compiler/impl/uc-modules.js';
import { ucMap } from '../../../schema/map/uc-map.js';
import { UcDeserializer } from '../../../schema/uc-deserializer.js';
import { ucUnknown } from '../../../schema/unknown/uc-unknown.js';
import { UcURIParamsLexer } from '../uri-params/uc-uri-params.lexer.js';
import { ucFormatJSON } from './uc-format-json.js';
import { UcJSONLexer } from './uc-json.lexer.js';

describe('JSON deserializer', () => {
describe('at top level', () => {
let readValue: UcDeserializer<unknown>;

beforeAll(async () => {
const compiler = new UcdCompiler({
models: {
readValue: {
model: ucUnknown(),
lexer({ emit }) {
const Lexer = UC_MODULE_CHURI.import(UcJSONLexer.name);

return esline`return new ${Lexer}(${emit});`;
},
},
},
});

({ readValue } = await compiler.evaluate());
});

it('recognizes primitive values', () => {
expect(readValue(`"test"`)).toBe(`test`);
expect(readValue(`13`)).toBe(13);
expect(readValue(`null`)).toBeNull();
expect(readValue(`true`)).toBe(true);
expect(readValue(`false`)).toBe(false);
});

it('recognizes object', () => {
const object = { foo: [1, 2, 3] };

expect(readValue(JSON.stringify(object))).toEqual(object);
});
});

describe('as inset', () => {
let readValue: UcDeserializer<unknown>;

beforeAll(async () => {
const compiler = new UcdCompiler({
models: {
readValue: {
model: ucMap({
test: ucUnknown({
within: {
uriParam: ucFormatJSON(),
},
}),
}),
lexer({ emit }) {
const Lexer = UC_MODULE_CHURI.import(UcURIParamsLexer.name);

return esline`return new ${Lexer}(${emit});`;
},
},
},
});

({ readValue } = await compiler.evaluate());
});

it('recognizes primitive values', () => {
expect(readValue(`test="test"`)).toEqual({ test: `test` });
expect(readValue(`test=13`)).toEqual({ test: 13 });
expect(readValue(`test=null`)).toEqual({ test: null });
expect(readValue(`test=true`)).toEqual({ test: true });
expect(readValue(`test=false`)).toEqual({ test: false });
});

it('recognizes object', () => {
const object = { foo: [1, 2, 3] };

expect(readValue(`test=${JSON.stringify(object)}`)).toEqual({ test: object });
});
});
});
2 changes: 2 additions & 0 deletions src/syntax/formats/json/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './uc-format-json.js';
export * from './uc-json.lexer.js';
21 changes: 21 additions & 0 deletions src/syntax/formats/json/uc-format-json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { UcdInsetOptions } from '../../../compiler/deserialization/ucd-process-inset.js';
import { CHURI_MODULE, COMPILER_MODULE } from '../../../impl/module-names.js';
import { UcOmniConstraints } from '../../../schema/uc-constraints.js';

/**
* Enables {@link UcJsonLexer JSON} format for schema or inset.
*
* @returns Schema constraints.
*/
export function ucFormatJSON(): UcOmniConstraints {
return {
deserializer: {
use: 'ucdProcessInset',
from: COMPILER_MODULE,
with: {
lexer: 'UcJSONLexer',
from: CHURI_MODULE,
} satisfies UcdInsetOptions,
},
};
}
Loading

0 comments on commit af2ff44

Please sign in to comment.