Skip to content

Commit 23d97ef

Browse files
committed
feat(json-type): 🎸 implement "map" type capacity estimator codegen
1 parent ac9256d commit 23d97ef

File tree

2 files changed

+46
-30
lines changed

2 files changed

+46
-30
lines changed

src/json-type/codegen/capacity/__tests__/CapacityEstimatorCodegenContext.spec.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,38 @@ describe('object', () => {
155155
});
156156
});
157157

158+
describe('map', () => {
159+
test('empty', () => {
160+
const system = new TypeSystem();
161+
const type = system.t.map;
162+
const estimator = type.compileCapacityEstimator({});
163+
expect(estimator(123)).toBe(maxEncodingCapacity({}));
164+
});
165+
166+
test('with one field', () => {
167+
const system = new TypeSystem();
168+
const type = system.t.Map(system.t.bool);
169+
const estimator = type.compileCapacityEstimator({});
170+
expect(estimator({foo: true})).toBe(maxEncodingCapacity({foo: true}));
171+
});
172+
173+
test('three number fields', () => {
174+
const system = new TypeSystem();
175+
const type = system.t.Map(system.t.num);
176+
const estimator = type.compileCapacityEstimator({});
177+
const data = {foo: 1, bar: 2, baz: 3};
178+
expect(estimator(data)).toBe(maxEncodingCapacity(data));
179+
});
180+
181+
test('nested maps', () => {
182+
const system = new TypeSystem();
183+
const type = system.t.Map(system.t.Map(system.t.str));
184+
const estimator = type.compileCapacityEstimator({});
185+
const data = {foo: {bar: 'baz'}, baz: {bar: 'foo'}};
186+
expect(estimator(data)).toBe(maxEncodingCapacity(data));
187+
});
188+
});
189+
158190
describe('ref', () => {
159191
test('two hops', () => {
160192
const system = new TypeSystem();

src/json-type/type/classes.ts

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,11 +1142,7 @@ export class ArrayType<T extends Type> extends AbstractType<schema.ArraySchema<S
11421142
ctx.inc(MaxEncodingOverhead.Array);
11431143
const rLen = codegen.var(`${value.use()}.length`);
11441144
const type = this.type;
1145-
codegen.js(
1146-
`size += ${
1147-
MaxEncodingOverhead.ArrayElement === 1 ? `${rLen}` : `${MaxEncodingOverhead.ArrayElement} * ${rLen}`
1148-
};`,
1149-
);
1145+
codegen.js(`size += ${MaxEncodingOverhead.ArrayElement} * ${rLen}`);
11501146
// TODO: Use ".capacityEstimator()" here.
11511147
const fn = type.compileCapacityEstimator({
11521148
system: ctx.options.system,
@@ -2005,31 +2001,19 @@ export class MapType<T extends Type> extends AbstractType<schema.MapSchema<Schem
20052001
}
20062002

20072003
public codegenCapacityEstimator(ctx: CapacityEstimatorCodegenContext, value: JsExpression): void {
2008-
ctx.codegen.js(`size += maxEncodingCapacity(${value.use()});`);
2009-
// throw new Error('TODO CAP');
2010-
// const codegen = ctx.codegen;
2011-
// ctx.inc(MaxEncodingOverhead.Array);
2012-
// const rLen = codegen.var(`${value.use()}.length`);
2013-
// const type = this.type;
2014-
// codegen.js(
2015-
// `size += ${
2016-
// MaxEncodingOverhead.ArrayElement === 1 ? `${rLen}` : `${MaxEncodingOverhead.ArrayElement} * ${rLen}`
2017-
// };`,
2018-
// );
2019-
// // TODO: Use ".capacityEstimator()" here.
2020-
// const fn = type.compileCapacityEstimator({
2021-
// system: ctx.options.system,
2022-
// name: ctx.options.name,
2023-
// });
2024-
// const isConstantSizeType = type instanceof ConstType || type instanceof BooleanType || type instanceof NumberType;
2025-
// if (isConstantSizeType) {
2026-
// codegen.js(`size += ${rLen} * ${fn(null)};`);
2027-
// } else {
2028-
// const r = codegen.var(value.use());
2029-
// const rFn = codegen.linkDependency(fn);
2030-
// const ri = codegen.getRegister();
2031-
// codegen.js(`for(var ${ri} = ${rLen}; ${ri}-- !== 0;) size += ${rFn}(${r}[${ri}]);`);
2032-
// }
2004+
const codegen = ctx.codegen;
2005+
ctx.inc(MaxEncodingOverhead.Object);
2006+
const r = codegen.var(value.use());
2007+
const rKeys = codegen.var(`Object.keys(${r})`);
2008+
const rKey = codegen.var();
2009+
const rLen = codegen.var(`${rKeys}.length`);
2010+
codegen.js(`size += ${MaxEncodingOverhead.ObjectElement} * ${rLen}`);
2011+
const ri = codegen.var('0');
2012+
codegen.js(`for (; ${ri} < ${rLen}; ${ri}++) {`);
2013+
codegen.js(`${rKey} = ${rKeys}[${ri}];`);
2014+
codegen.js(`size += ${MaxEncodingOverhead.String} + ${MaxEncodingOverhead.StringLengthMultiplier} * ${rKey}.length;`);
2015+
this.type.codegenCapacityEstimator(ctx, new JsExpression(() => `${r}[${rKey}]`));
2016+
codegen.js(`}`);
20332017
}
20342018

20352019
public random(): Record<string, unknown> {

0 commit comments

Comments
 (0)