22// Use of this source code is governed by the Apache License 2.0
33// that can be found in the LICENSE file.
44
5- use avdschema:: { any:: AnySchema , boolean:: Bool , dict:: Dict , int:: Int , list:: List , str:: Str } ;
5+ use avdschema:: delegate_anyschema_method;
6+ use avdschema:: {
7+ any:: AnySchema , boolean:: Bool , dict:: Dict , int:: Int , list:: List , resolve_ref, str:: Str ,
8+ } ;
69use serde_json:: Value ;
710
811use crate :: { context:: Context , feedback:: CoercionNote } ;
1922 ///
2023 /// TODO: Decide whether we should limit this to only coerce according to `convert_types`.
2124 fn coerce ( & self , input : & mut Value , ctx : & mut Context ) ;
25+ fn coerce_ref ( & self , input : & mut Value , ctx : & mut Context ) ;
2226}
2327impl Coercion for Bool {
2428 fn coerce ( & self , _input : & mut Value , _ctx : & mut Context ) { }
29+ fn coerce_ref ( & self , _input : & mut Value , _ctx : & mut Context ) { }
2530}
2631impl Coercion for Dict {
2732 fn coerce ( & self , input : & mut Value , ctx : & mut Context ) {
@@ -49,6 +54,18 @@ impl Coercion for Dict {
4954 }
5055 }
5156 }
57+ self . coerce_ref ( input, ctx) ;
58+ }
59+
60+ fn coerce_ref ( & self , input : & mut Value , ctx : & mut Context ) {
61+ if let Some ( ref_) = self . base . schema_ref . as_ref ( ) {
62+ // Ignoring not being able to resolve the schema.
63+ // Ignoring a wrong schema type at the ref. Since coercion is infallible.
64+ // TODO: What to do?
65+ if let Ok ( AnySchema :: Dict ( ref_schema) ) = resolve_ref ( ref_, ctx. store ) {
66+ ref_schema. coerce ( input, ctx) ;
67+ }
68+ }
5269 }
5370}
5471
@@ -97,6 +114,18 @@ impl Coercion for Int {
97114 if let Some ( value) = value {
98115 _ = core:: mem:: replace ( input, value. into ( ) ) ;
99116 }
117+ self . coerce_ref ( input, ctx) ;
118+ }
119+
120+ fn coerce_ref ( & self , input : & mut Value , ctx : & mut Context ) {
121+ if let Some ( ref_) = self . base . schema_ref . as_ref ( ) {
122+ // Ignoring not being able to resolve the schema.
123+ // Ignoring a wrong schema type at the ref. Since coercion is infallible.
124+ // TODO: What to do?
125+ if let Ok ( AnySchema :: Int ( ref_schema) ) = resolve_ref ( ref_, ctx. store ) {
126+ ref_schema. coerce ( input, ctx) ;
127+ }
128+ }
100129 }
101130}
102131impl Coercion for List {
@@ -110,6 +139,18 @@ impl Coercion for List {
110139 ctx. state . path . pop ( ) ;
111140 }
112141 }
142+ self . coerce_ref ( input, ctx) ;
143+ }
144+
145+ fn coerce_ref ( & self , input : & mut Value , ctx : & mut Context ) {
146+ if let Some ( ref_) = self . base . schema_ref . as_ref ( ) {
147+ // Ignoring not being able to resolve the schema.
148+ // Ignoring a wrong schema type at the ref. Since coercion is infallible.
149+ // TODO: What to do?
150+ if let Ok ( AnySchema :: List ( ref_schema) ) = resolve_ref ( ref_, ctx. store ) {
151+ ref_schema. coerce ( input, ctx) ;
152+ }
153+ }
113154 }
114155}
115156impl Coercion for Str {
@@ -163,16 +204,78 @@ impl Coercion for Str {
163204 if let Some ( value) = value. as_deref ( ) {
164205 _ = core:: mem:: replace ( input, value. into ( ) ) ;
165206 }
207+ self . coerce_ref ( input, ctx) ;
208+ }
209+
210+ fn coerce_ref ( & self , input : & mut Value , ctx : & mut Context ) {
211+ if let Some ( ref_) = self . base . schema_ref . as_ref ( ) {
212+ // Ignoring not being able to resolve the schema.
213+ // Ignoring a wrong schema type at the ref. Since coercion is infallible.
214+ // TODO: What to do?
215+ if let Ok ( AnySchema :: Str ( ref_schema) ) = resolve_ref ( ref_, ctx. store ) {
216+ ref_schema. coerce ( input, ctx) ;
217+ }
218+ }
166219 }
167220}
168221impl Coercion for AnySchema {
169222 fn coerce ( & self , input : & mut Value , ctx : & mut Context ) {
170- match self {
171- Self :: Bool ( schema) => schema. coerce ( input, ctx) ,
172- Self :: Int ( schema) => schema. coerce ( input, ctx) ,
173- Self :: Str ( schema) => schema. coerce ( input, ctx) ,
174- Self :: List ( schema) => schema. coerce ( input, ctx) ,
175- Self :: Dict ( schema) => schema. coerce ( input, ctx) ,
176- }
223+ delegate_anyschema_method ! ( self , coerce, input, ctx)
224+ }
225+
226+ fn coerce_ref ( & self , input : & mut Value , ctx : & mut Context ) {
227+ delegate_anyschema_method ! ( self , coerce_ref, input, ctx)
228+ }
229+ }
230+
231+ #[ cfg( test) ]
232+ mod tests {
233+ use avdschema:: base:: Base ;
234+ use ordermap:: OrderMap ;
235+
236+ use super :: * ;
237+ use crate :: Validation as _;
238+ use crate :: context:: { Configuration , Context } ;
239+ use crate :: feedback:: { CoercionNote , Feedback } ;
240+ use crate :: validation:: test_utils:: get_test_store;
241+
242+ #[ test]
243+ fn validate_coecion_with_ref_ok ( ) {
244+ let schema = Dict {
245+ keys : Some ( OrderMap :: from_iter ( [ (
246+ "foo" . into ( ) ,
247+ Dict {
248+ base : Base {
249+ // Using ref to the root of the schema since such refs will not get resolved.
250+ schema_ref : Some ( "eos_cli_config_gen#" . into ( ) ) ,
251+ ..Default :: default ( )
252+ } ,
253+ ..Default :: default ( )
254+ }
255+ . into ( ) ,
256+ ) ] ) ) ,
257+ ..Default :: default ( )
258+ } ;
259+ let mut input = serde_json:: json!( { "foo" : { "key1" : 123 } } ) ;
260+ let store = get_test_store ( ) ;
261+ let configuration = Configuration {
262+ return_coercion_infos : true ,
263+ ..Default :: default ( )
264+ } ;
265+ let mut ctx = Context :: new ( & store, Some ( & configuration) ) ;
266+ schema. coerce ( & mut input, & mut ctx) ;
267+ schema. validate_value ( & input, & mut ctx) ;
268+ assert ! ( ctx. result. errors. is_empty( ) ) ;
269+ assert_eq ! (
270+ ctx. result. infos,
271+ vec![ Feedback {
272+ path: vec![ "foo" . into( ) , "key1" . into( ) ] . into( ) ,
273+ issue: CoercionNote {
274+ found: 123 . into( ) ,
275+ made: "123" . into( )
276+ }
277+ . into( )
278+ } , ]
279+ )
177280 }
178281}
0 commit comments