11import { JsExpression } from '@jsonjoy.com/util/lib/codegen/util/JsExpression' ;
22import { MaxEncodingOverhead , maxEncodingCapacity } from '@jsonjoy.com/util/lib/json-size' ;
3- import type { CapacityEstimatorCodegenContext } from './CapacityEstimatorCodegenContext' ;
3+ import { CapacityEstimatorCodegenContext } from './CapacityEstimatorCodegenContext' ;
4+ import type { CapacityEstimatorCodegenContextOptions , CompiledCapacityEstimator } from './CapacityEstimatorCodegenContext' ;
45import type { Type } from '../../type' ;
56
67type EstimatorFunction = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) => void ;
78
8- function normalizeAccessor ( key : string ) : string {
9+ const normalizeAccessor = ( key : string ) : string => {
910 // Simple property access for valid identifiers, bracket notation otherwise
1011 if ( / ^ [ a - z A - Z _ $ ] [ a - z A - Z 0 - 9 _ $ ] * $ / . test ( key ) ) {
1112 return `.${ key } ` ;
1213 }
1314 return `[${ JSON . stringify ( key ) } ]` ;
14- }
15+ } ;
1516
16- export function estimateAnyCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void {
17+ export const any = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void => {
1718 const codegen = ctx . codegen ;
1819 codegen . link ( 'Value' ) ;
1920 const r = codegen . var ( value . use ( ) ) ;
@@ -34,32 +35,32 @@ export function estimateAnyCapacity(ctx: CapacityEstimatorCodegenContext, value:
3435 ctx . codegen . js ( `size += maxEncodingCapacity(${ r } );` ) ;
3536 } ,
3637 ) ;
37- }
38+ } ;
3839
39- export function estimateBooleanCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression ) : void {
40+ export const bool = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression ) : void => {
4041 ctx . inc ( MaxEncodingOverhead . Boolean ) ;
41- }
42+ } ;
4243
43- export function estimateNumberCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression ) : void {
44+ export const num = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression ) : void => {
4445 ctx . inc ( MaxEncodingOverhead . Number ) ;
45- }
46+ } ;
4647
47- export function estimateStringCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression ) : void {
48+ export const str = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression ) : void => {
4849 ctx . inc ( MaxEncodingOverhead . String ) ;
4950 ctx . codegen . js ( `size += ${ MaxEncodingOverhead . StringLengthMultiplier } * ${ value . use ( ) } .length;` ) ;
50- }
51+ } ;
5152
52- export function estimateBinaryCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression ) : void {
53+ export const bin = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression ) : void => {
5354 ctx . inc ( MaxEncodingOverhead . Binary ) ;
5455 ctx . codegen . js ( `size += ${ MaxEncodingOverhead . BinaryLengthMultiplier } * ${ value . use ( ) } .length;` ) ;
55- }
56+ } ;
5657
57- export function estimateConstCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void {
58+ export const const_ = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void => {
5859 const constType = type as any ; // ConstType
5960 ctx . inc ( maxEncodingCapacity ( constType . value ( ) ) ) ;
60- }
61+ } ;
6162
62- export function estimateArrayCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void {
63+ export const arr = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void => {
6364 const codegen = ctx . codegen ;
6465 ctx . inc ( MaxEncodingOverhead . Array ) ;
6566 const rLen = codegen . var ( `${ value . use ( ) } .length` ) ;
@@ -81,9 +82,9 @@ export function estimateArrayCapacity(ctx: CapacityEstimatorCodegenContext, valu
8182 codegen . js ( `size += ${ rFn } (${ value . use ( ) } [${ ri } ]);` ) ;
8283 codegen . js ( `}` ) ;
8384 }
84- }
85+ } ;
8586
86- export function estimateTupleCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void {
87+ export const tup = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void => {
8788 const codegen = ctx . codegen ;
8889 const r = codegen . var ( value . use ( ) ) ;
8990 const tupleType = type as any ; // TupleType
@@ -99,9 +100,9 @@ export function estimateTupleCapacity(ctx: CapacityEstimatorCodegenContext, valu
99100 const rFn = codegen . linkDependency ( fn ) ;
100101 codegen . js ( `size += ${ rFn } (${ r } [${ i } ]);` ) ;
101102 }
102- }
103+ } ;
103104
104- export function estimateObjectCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type , estimateCapacityFn : EstimatorFunction ) : void {
105+ export const obj = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type , estimateCapacityFn : EstimatorFunction ) : void => {
105106 const codegen = ctx . codegen ;
106107 const r = codegen . var ( value . use ( ) ) ;
107108 const objectType = type as any ; // ObjectType
@@ -122,9 +123,9 @@ export function estimateObjectCapacity(ctx: CapacityEstimatorCodegenContext, val
122123 codegen . if ( `${ r } ${ accessor } !== undefined` , block ) ;
123124 } else block ( ) ;
124125 }
125- }
126+ } ;
126127
127- export function estimateMapCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void {
128+ export const map = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void => {
128129 const codegen = ctx . codegen ;
129130 ctx . inc ( MaxEncodingOverhead . Object ) ;
130131 const r = codegen . var ( value . use ( ) ) ;
@@ -144,18 +145,18 @@ export function estimateMapCapacity(ctx: CapacityEstimatorCodegenContext, value:
144145 codegen . js ( `${ rKey } = ${ rKeys } [${ ri } ];` ) ;
145146 codegen . js ( `size += maxEncodingCapacity(${ rKey } ) + ${ rFn } (${ r } [${ rKey } ]);` ) ;
146147 codegen . js ( `}` ) ;
147- }
148+ } ;
148149
149- export function estimateRefCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void {
150+ export const ref = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void => {
150151 const refType = type as any ; // RefType
151152 const system = ctx . options . system || refType . system ;
152153 if ( ! system ) throw new Error ( 'NO_SYSTEM' ) ;
153154 const estimator = system . resolve ( refType . schema . ref ) . type . capacityEstimator ( ) ;
154155 const d = ctx . codegen . linkDependency ( estimator ) ;
155156 ctx . codegen . js ( `size += ${ d } (${ value . use ( ) } );` ) ;
156- }
157+ } ;
157158
158- export function estimateOrCapacity ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type , estimateCapacityFn : EstimatorFunction ) : void {
159+ export const or = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type , estimateCapacityFn : EstimatorFunction ) : void => {
159160 const codegen = ctx . codegen ;
160161 const orType = type as any ; // OrType
161162 const discriminator = orType . discriminator ( ) ;
@@ -170,4 +171,72 @@ export function estimateOrCapacity(ctx: CapacityEstimatorCodegenContext, value:
170171 } ,
171172 ] ) ,
172173 ) ;
173- }
174+ } ;
175+
176+ /**
177+ * Main router function that dispatches capacity estimation to the appropriate
178+ * estimator function based on the type's kind.
179+ */
180+ export const generate = ( ctx : CapacityEstimatorCodegenContext , value : JsExpression , type : Type ) : void => {
181+ const kind = type . getTypeName ( ) ;
182+
183+ switch ( kind ) {
184+ case 'any' :
185+ any ( ctx , value , type ) ;
186+ break ;
187+ case 'bool' :
188+ bool ( ctx , value ) ;
189+ break ;
190+ case 'num' :
191+ num ( ctx , value ) ;
192+ break ;
193+ case 'str' :
194+ str ( ctx , value ) ;
195+ break ;
196+ case 'bin' :
197+ bin ( ctx , value ) ;
198+ break ;
199+ case 'const' :
200+ const_ ( ctx , value , type ) ;
201+ break ;
202+ case 'arr' :
203+ arr ( ctx , value , type ) ;
204+ break ;
205+ case 'tup' :
206+ tup ( ctx , value , type ) ;
207+ break ;
208+ case 'obj' :
209+ obj ( ctx , value , type , generate ) ;
210+ break ;
211+ case 'map' :
212+ map ( ctx , value , type ) ;
213+ break ;
214+ case 'ref' :
215+ ref ( ctx , value , type ) ;
216+ break ;
217+ case 'or' :
218+ or ( ctx , value , type , generate ) ;
219+ break ;
220+ default :
221+ throw new Error ( `${ kind } type capacity estimation not implemented` ) ;
222+ }
223+ } ;
224+
225+ /**
226+ * Standalone function to generate a capacity estimator for a given type.
227+ */
228+ export const codegen = (
229+ type : Type ,
230+ options : Omit < CapacityEstimatorCodegenContextOptions , 'type' > ,
231+ ) : CompiledCapacityEstimator => {
232+ const ctx = new CapacityEstimatorCodegenContext ( {
233+ system : type . system ,
234+ ...options ,
235+ type : type as any ,
236+ } ) ;
237+ const r = ctx . codegen . options . args [ 0 ] ;
238+ const value = new JsExpression ( ( ) => r ) ;
239+ // Use the centralized router instead of the abstract method
240+ generate ( ctx , value , type ) ;
241+ return ctx . compile ( ) ;
242+ } ;
0 commit comments