2
2
use crate :: { OutputMember , OutputStruct } ;
3
3
use anyhow:: { bail, Result } ;
4
4
use k8s_openapi:: apiextensions_apiserver:: pkg:: apis:: apiextensions:: v1:: {
5
- JSONSchemaProps , JSONSchemaPropsOrArray , JSONSchemaPropsOrBool ,
5
+ JSONSchemaProps , JSONSchemaPropsOrArray , JSONSchemaPropsOrBool , JSON ,
6
6
} ;
7
7
use std:: collections:: { BTreeMap , HashMap } ;
8
8
@@ -118,12 +118,58 @@ pub fn analyze(
118
118
debug ! ( "not recursing into unknown empty type {}" , key)
119
119
}
120
120
}
121
- x => debug ! ( "not recursing into {} (not a container - {})" , key, x) ,
121
+ x => {
122
+ if let Some ( en) = value. enum_ {
123
+ let new_result = analyze_enum_properties ( & en, & next_stack, level, & schema) ?;
124
+ results. extend ( new_result) ;
125
+ // TODO: this should probably be done outside of the property recursion loop
126
+ } else {
127
+ debug ! ( "not recursing into {} (not a container - {})" , key, x)
128
+ }
129
+ }
122
130
}
123
131
}
124
132
Ok ( ( ) )
125
133
}
126
134
135
+ // helper to figure out what output enums and embedded members are contained in the current object schema
136
+ fn analyze_enum_properties (
137
+ items : & Vec < JSON > ,
138
+ stack : & str ,
139
+ level : u8 ,
140
+ schema : & JSONSchemaProps ,
141
+ ) -> Result < Vec < OutputStruct > , anyhow:: Error > {
142
+ let mut results = vec ! [ ] ;
143
+ let mut members = vec ! [ ] ;
144
+ debug ! ( "analyzing enum {}" , serde_json:: to_string( & schema) . unwrap( ) ) ;
145
+ for en in items {
146
+ //debug!("got enum {:?}", en);
147
+ // TODO: do we need to verify enum elements? only in oneOf only right?
148
+ let ( name, rust_type) = match & en. 0 {
149
+ serde_json:: Value :: String ( name) => ( name, "" . to_string ( ) ) ,
150
+ _ => bail ! ( "not handling non-string enum" ) ,
151
+ } ;
152
+ // Create member and wrap types correctly
153
+ let member_doc = None ;
154
+ debug ! ( "with enum member {} of type {}" , name, rust_type) ;
155
+ members. push ( OutputMember {
156
+ type_ : rust_type,
157
+ name : name. to_string ( ) ,
158
+ field_annot : None ,
159
+ docs : member_doc,
160
+ } )
161
+ }
162
+ results. push ( OutputStruct {
163
+ name : stack. to_string ( ) ,
164
+ members,
165
+ level,
166
+ docs : schema. description . clone ( ) ,
167
+ is_enum : true ,
168
+ } ) ;
169
+ Ok ( results)
170
+ }
171
+
172
+
127
173
// helper to figure out what output structs (returned) and embedded members are contained in the current object schema
128
174
fn analyze_object_properties (
129
175
props : & BTreeMap < String , JSONSchemaProps > ,
@@ -134,6 +180,8 @@ fn analyze_object_properties(
134
180
) -> Result < Vec < OutputStruct > , anyhow:: Error > {
135
181
let mut results = vec ! [ ] ;
136
182
let mut members = vec ! [ ] ;
183
+ let mut is_enum = false ;
184
+ //debug!("analyzing object {}", serde_json::to_string(&schema).unwrap());
137
185
let reqs = schema. required . clone ( ) . unwrap_or_default ( ) ;
138
186
for ( key, value) in props {
139
187
let value_type = value. type_ . clone ( ) . unwrap_or_default ( ) ;
@@ -211,7 +259,15 @@ fn analyze_object_properties(
211
259
format ! ( "{}{}" , stack, uppercase_first_letter( key) )
212
260
}
213
261
}
214
- "string" => "String" . to_string ( ) ,
262
+ "string" => {
263
+ debug ! ( "got string schema: {}" , serde_json:: to_string( & schema) . unwrap( ) ) ;
264
+ if let Some ( _en) = & value. enum_ {
265
+ is_enum = true ;
266
+ format ! ( "{}{}" , stack, uppercase_first_letter( key) )
267
+ } else {
268
+ "String" . to_string ( )
269
+ }
270
+ }
215
271
"boolean" => "bool" . to_string ( ) ,
216
272
"date" => extract_date_type ( value) ?,
217
273
"number" => extract_number_type ( value) ?,
@@ -239,7 +295,7 @@ fn analyze_object_properties(
239
295
// Create member and wrap types correctly
240
296
let member_doc = value. description . clone ( ) ;
241
297
if reqs. contains ( key) {
242
- debug ! ( "with required member {} of type {}" , key, rust_type) ;
298
+ debug ! ( "with required member {} of type {}" , key, & rust_type) ;
243
299
members. push ( OutputMember {
244
300
type_ : rust_type,
245
301
name : key. to_string ( ) ,
@@ -262,6 +318,7 @@ fn analyze_object_properties(
262
318
members,
263
319
level,
264
320
docs : schema. description . clone ( ) ,
321
+ is_enum,
265
322
} ) ;
266
323
Ok ( results)
267
324
}
@@ -496,34 +553,46 @@ type: object
496
553
}
497
554
498
555
#[ test]
499
- fn enum_one_of ( ) {
556
+ fn enum_string ( ) {
500
557
let schema_str = r#"
501
- operator:
502
- enum:
503
- - In
504
- - NotIn
505
- - Exists
506
- - DoesNotExist
507
- type: string"# ;
558
+ properties:
559
+ operator:
560
+ enum:
561
+ - In
562
+ - NotIn
563
+ - Exists
564
+ - DoesNotExist
565
+ type: string
566
+ required:
567
+ - operator
568
+ type: object
569
+ "# ;
508
570
509
571
let schema: JSONSchemaProps = serde_yaml:: from_str ( schema_str) . unwrap ( ) ;
510
572
env_logger:: init ( ) ;
511
573
let mut structs = vec ! [ ] ;
512
- analyze ( schema, "" , "Operator " , 0 , & mut structs) . unwrap ( ) ;
574
+ analyze ( schema, "" , "MatchExpressions " , 0 , & mut structs) . unwrap ( ) ;
513
575
println ! ( "got {:?}" , structs) ;
514
576
let root = & structs[ 0 ] ;
515
- assert_eq ! ( root. name, "Operator " ) ;
577
+ assert_eq ! ( root. name, "MatchExpressions " ) ;
516
578
assert_eq ! ( root. level, 0 ) ;
579
+ assert_eq ! ( & root. members[ 0 ] . name, "operator" ) ;
580
+ assert_eq ! ( & root. members[ 0 ] . type_, "MatchExpressionsOperator" ) ;
581
+
582
+ // operator member
583
+ let op = & structs[ 1 ] ;
584
+ assert ! ( op. is_enum) ;
585
+ assert_eq ! ( op. name, "MatchExpressionsOperator" ) ;
517
586
518
587
// should have enum members:
519
- assert_eq ! ( & root . members[ 0 ] . name, "In" ) ;
520
- assert_eq ! ( & root . members[ 0 ] . type_, "" ) ;
521
- assert_eq ! ( & root . members[ 1 ] . name, "NotIn" ) ;
522
- assert_eq ! ( & root . members[ 1 ] . type_, "" ) ;
523
- assert_eq ! ( & root . members[ 2 ] . name, "Exists" ) ;
524
- assert_eq ! ( & root . members[ 2 ] . type_, "" ) ;
525
- assert_eq ! ( & root . members[ 3 ] . name, "DoesNotExist" ) ;
526
- assert_eq ! ( & root . members[ 3 ] . type_, "" ) ;
588
+ assert_eq ! ( & op . members[ 0 ] . name, "In" ) ;
589
+ assert_eq ! ( & op . members[ 0 ] . type_, "" ) ;
590
+ assert_eq ! ( & op . members[ 1 ] . name, "NotIn" ) ;
591
+ assert_eq ! ( & op . members[ 1 ] . type_, "" ) ;
592
+ assert_eq ! ( & op . members[ 2 ] . name, "Exists" ) ;
593
+ assert_eq ! ( & op . members[ 2 ] . type_, "" ) ;
594
+ assert_eq ! ( & op . members[ 3 ] . name, "DoesNotExist" ) ;
595
+ assert_eq ! ( & op . members[ 3 ] . type_, "" ) ;
527
596
}
528
597
529
598
#[ test]
0 commit comments