@@ -425,7 +425,9 @@ and internal = {
425425 mutable serializer ?: builder ,
426426 // Builder refine that the value matches the schema
427427 // Applies for both parsing and serializing
428- mutable refiner ?: builder ,
428+ mutable refiner ?: refinerBuilder ,
429+ // Compiler for custom schema logic
430+ mutable compiler ?: builder ,
429431 // A schema we transform to
430432 mutable to ?: internal ,
431433 mutable const ?: char , // use char to avoid Caml_option.some
@@ -507,6 +509,7 @@ and has = {
507509 object ?: bool ,
508510}
509511and builder = (b , ~input : val , ~selfSchema : internal , ~path : Path .t ) => val
512+ and refinerBuilder = (b , ~inputVar : string , ~selfSchema : internal , ~path : Path .t ) => string
510513and val = {
511514 @as ("b" )
512515 mutable b : b ,
@@ -1897,14 +1900,19 @@ let rec parse = (prevB: b, ~schema, ~input as inputArg: val, ~path) => {
18971900 b -> B .unsupportedTransform (~from = input .contents -> Obj .magic , ~target = schema , ~path )
18981901 }
18991902
1900- switch schema .refiner {
1901- | Some (refiner ) =>
1902- // Some refiners like union might return a new
1903- // instance of value. This is used for an assumption
1904- // that it's transformed.
1905- input := refiner (b , ~input = input .contents , ~selfSchema = schema , ~path )
1906- | _ => ()
1903+ switch schema .compiler {
1904+ | Some (compiler ) => input := compiler (b , ~input = input .contents , ~selfSchema = schema , ~path )
1905+ | None => ()
1906+ }
1907+
1908+ if input .contents .skipTo !== Some (true ) {
1909+ switch schema .refiner {
1910+ | Some (refiner ) =>
1911+ b .code = b .code ++ refiner (b , ~inputVar = input .contents .var (b ), ~selfSchema = schema , ~path )
1912+ | None => ()
1913+ }
19071914 }
1915+
19081916 switch schema .to {
19091917 | Some (to ) =>
19101918 switch schema .parser {
@@ -2504,26 +2512,20 @@ let noValidation = (schema, value) => {
25042512 mut -> castToPublic
25052513}
25062514
2515+ let appendRefiner = (maybeExistingRefiner , refiner ) => {
2516+ switch maybeExistingRefiner {
2517+ | Some (existingRefiner ) =>
2518+ (b , ~inputVar , ~selfSchema , ~path ) => {
2519+ existingRefiner (b , ~inputVar , ~selfSchema , ~path ) ++ refiner (b , ~inputVar , ~selfSchema , ~path )
2520+ }
2521+ | None => refiner
2522+ }
2523+ }
2524+
25072525let internalRefine = (schema , refiner ) => {
25082526 let schema = schema -> castToInternal
25092527 updateOutput (schema , mut => {
2510- let prevRefiner = mut .refiner
2511- mut .refiner = Some (
2512- Builder .make ((b , ~input , ~selfSchema , ~path ) => {
2513- // FIXME: Should it be applied in more places?
2514- b -> B .transform (
2515- ~input = switch prevRefiner {
2516- | Some (prevRefiner ) => prevRefiner (b , ~input , ~selfSchema , ~path )
2517- | None => input
2518- },
2519- (b , ~input ) => {
2520- let rCode = refiner (b , ~inputVar = b -> B .Val .var (input ), ~selfSchema , ~path )
2521- b .code = b .code ++ rCode
2522- input
2523- },
2524- )
2525- }),
2526- )
2528+ mut .refiner = Some (appendRefiner (mut .refiner , refiner ))
25272529 })
25282530}
25292531
@@ -2614,7 +2616,7 @@ let neverBuilder = Builder.make((b, ~input, ~selfSchema, ~path) => {
26142616})
26152617
26162618let never = base (Never )
2617- never .refiner = Some (neverBuilder )
2619+ never .compiler = Some (neverBuilder )
26182620let never : t <never > = never -> castToPublic
26192621
26202622let nestedLoc = "BS_PRIVATE_NESTED_SOME_NONE"
@@ -2685,7 +2687,7 @@ module Union = {
26852687 })
26862688 }
26872689
2688- let refiner = Builder .make ((b , ~input , ~selfSchema , ~path ) => {
2690+ let compiler = Builder .make ((b , ~input , ~selfSchema , ~path ) => {
26892691 let schemas = selfSchema .anyOf -> X .Option .getUnsafe
26902692
26912693 switch input .anyOf {
@@ -2731,6 +2733,10 @@ module Union = {
27312733 let schema = switch selfSchema .to {
27322734 | Some (target ) if ! (selfSchema .parser -> Obj .magic ) && target .tag !== Union =>
27332735 updateOutput (schemas -> Js .Array2 .unsafe_get (idx ), mut => {
2736+ switch selfSchema .refiner {
2737+ | Some (refiner ) => mut .refiner = Some (appendRefiner (mut .refiner , refiner ))
2738+ | None => ()
2739+ }
27342740 mut .to = Some (target )
27352741 })-> castToInternal
27362742 | _ => schemas -> Js .Array2 .unsafe_get (idx )
@@ -3098,7 +3104,7 @@ module Union = {
30983104 }
30993105 let mut = base (Union )
31003106 mut .anyOf = Some (anyOf -> X .Set .toArray )
3101- mut .refiner = Some (refiner )
3107+ mut .compiler = Some (compiler )
31023108 mut .has = Some (has )
31033109 mut -> castToPublic
31043110 }
@@ -3268,10 +3274,10 @@ module Option = {
32683274 }),
32693275 )
32703276 let to = itemOutputSchema .contents -> X .Option .getUnsafe -> copyWithoutCache
3271- switch to .refiner {
3272- | Some (refiner ) => {
3273- to .serializer = Some (refiner )
3274- %raw (` delete to .refiner ` )
3277+ switch to .compiler {
3278+ | Some (compiler ) => {
3279+ to .serializer = Some (compiler )
3280+ %raw (` delete to .compiler ` )
32753281 }
32763282 | None => to .serializer = Some ((_b , ~input , ~selfSchema as _ , ~path as _ ) => input )
32773283 }
@@ -3320,7 +3326,7 @@ module Array = {
33203326 }
33213327 }
33223328
3323- let arrayRefiner = Builder .make ((b , ~input , ~selfSchema , ~path ) => {
3329+ let arrayCompiler = Builder .make ((b , ~input , ~selfSchema , ~path ) => {
33243330 let item = selfSchema .additionalItems -> (Obj .magic : option <additionalItems > => internal )
33253331
33263332 let inputVar = b -> B .Val .var (input )
@@ -3361,7 +3367,7 @@ module Array = {
33613367 let mut = base (Array )
33623368 mut .additionalItems = Some (Schema (item -> castToInternal -> castToPublic ))
33633369 mut .items = Some (X .Array .immutableEmpty )
3364- mut .refiner = Some (arrayRefiner )
3370+ mut .compiler = Some (arrayCompiler )
33653371 mut -> castToPublic
33663372 }
33673373}
@@ -3426,7 +3432,7 @@ let deepStrict = schema => {
34263432}
34273433
34283434module Dict = {
3429- let dictRefiner = Builder .make ((b , ~input , ~selfSchema , ~path ) => {
3435+ let dictCompiler = Builder .make ((b , ~input , ~selfSchema , ~path ) => {
34303436 let item = selfSchema .additionalItems -> (Obj .magic : option <additionalItems > => internal )
34313437
34323438 let inputVar = b -> B .Val .var (input )
@@ -3476,7 +3482,7 @@ module Dict = {
34763482 mut .properties = Some (X .Object .immutableEmpty )
34773483 mut .items = Some (X .Array .immutableEmpty )
34783484 mut .additionalItems = Some (Schema (item -> castToPublic ))
3479- mut .refiner = Some (dictRefiner )
3485+ mut .compiler = Some (dictCompiler )
34803486 mut -> castToPublic
34813487 }
34823488}
@@ -3556,7 +3562,7 @@ let enableJson = () => {
35563562 "object" : true ,
35573563 "array" : true ,
35583564 },
3559- refiner : Union .refiner ,
3565+ compiler : Union .compiler ,
35603566 },
35613567 )
35623568 json .defs = Some (defs )
@@ -3586,7 +3592,7 @@ let enableJsonString = {
35863592 jsonString .tag = String
35873593 jsonString .format = Some (JSON )
35883594 jsonString .name = Some (` ${jsonName} string` )
3589- jsonString .refiner = Some (
3595+ jsonString .compiler = Some (
35903596 Builder .make ((b , ~input as inputArg , ~selfSchema , ~path ) => {
35913597 let inputTagFlag = inputArg .tag -> TagFlag .get
35923598 let input = ref (inputArg )
@@ -4003,7 +4009,7 @@ module Schema = {
40034009 },
40044010 })
40054011
4006- let rec schemaRefiner = (b , ~input : val , ~selfSchema , ~path ) => {
4012+ let rec schemaCompiler = (b , ~input : val , ~selfSchema , ~path ) => {
40074013 let additionalItems = selfSchema .additionalItems
40084014 let items = selfSchema .items -> X .Option .getUnsafe
40094015 let isArray = TagFlag .isArray (selfSchema .tag )
@@ -4118,6 +4124,7 @@ module Schema = {
41184124
41194125 // This should be done in the parser/serializer
41204126 let _ = %raw (` delete mut .refiner ` )
4127+ let _ = %raw (` delete mut .compiler ` )
41214128
41224129 mut .serializer = Some (
41234130 Builder .make ((b , ~input , ~selfSchema , ~path ) => {
@@ -4317,7 +4324,7 @@ module Schema = {
43174324 schema .items = Some (items )
43184325 schema .properties = Some (properties )
43194326 schema .additionalItems = Some (globalConfig .defaultAdditionalItems )
4320- schema .refiner = Some (schemaRefiner )
4327+ schema .compiler = Some (schemaCompiler )
43214328 schema -> castToPublic
43224329 }
43234330
@@ -4645,7 +4652,7 @@ module Schema = {
46454652 let mut = base (Array )
46464653 mut .items = Some (items )
46474654 mut .additionalItems = Some (Strict )
4648- mut .refiner = Some (schemaRefiner )
4655+ mut .compiler = Some (schemaCompiler )
46494656 mut
46504657 } else {
46514658 let cnstr = (definition -> Obj .magic )["constructor" ]
@@ -4674,7 +4681,7 @@ module Schema = {
46744681 mut .items = Some (items )
46754682 mut .properties = Some (node -> (Obj .magic : dict <unknown > => dict <internal >))
46764683 mut .additionalItems = Some (globalConfig .defaultAdditionalItems )
4677- mut .refiner = Some (schemaRefiner )
4684+ mut .compiler = Some (schemaCompiler )
46784685 mut
46794686 }
46804687 }
@@ -5497,7 +5504,7 @@ let js_merge = (s1, s2) => {
54975504 mut .items = Some (items )
54985505 mut .properties = Some (properties )
54995506 mut .additionalItems = Some (additionalItems1 )
5500- mut .refiner = Some (Schema .schemaRefiner )
5507+ mut .compiler = Some (Schema .schemaCompiler )
55015508 Some (mut -> castToPublic )
55025509 | _ => None
55035510 } {
0 commit comments