@@ -3,6 +3,7 @@ use indexmap::IndexMap;
33use miette:: miette;
44use schematic_types:: * ;
55use std:: collections:: { HashMap , VecDeque } ;
6+ use std:: mem;
67
78/// Options to control the rendered template.
89pub struct TemplateOptions {
@@ -15,8 +16,8 @@ pub struct TemplateOptions {
1516 /// Characters to prefix a comment line.
1617 pub comment_prefix : String ,
1718
18- /// Default values for each field within the root struct .
19- pub default_values : HashMap < String , SchemaType > ,
19+ /// Custom values for each field. Supports dot notation .
20+ pub custom_values : HashMap < String , Schema > ,
2021
2122 /// List of array and object field names to expand and render a fake item.
2223 pub expand_fields : Vec < String > ,
@@ -35,6 +36,9 @@ pub struct TemplateOptions {
3536
3637 /// Insert an extra newline between fields.
3738 pub newline_between_fields : bool ,
39+
40+ /// List of field names to only render.
41+ pub only_fields : Vec < String > ,
3842}
3943
4044impl Default for TemplateOptions {
@@ -43,13 +47,14 @@ impl Default for TemplateOptions {
4347 comments : true ,
4448 comment_fields : vec ! [ ] ,
4549 comment_prefix : "# " . into ( ) ,
46- default_values : HashMap :: new ( ) ,
50+ custom_values : HashMap :: new ( ) ,
4751 expand_fields : vec ! [ ] ,
4852 footer : String :: new ( ) ,
4953 header : String :: new ( ) ,
5054 hide_fields : vec ! [ ] ,
5155 indent_char : " " . into ( ) ,
5256 newline_between_fields : true ,
57+ only_fields : vec ! [ ] ,
5358 }
5459 }
5560}
@@ -142,8 +147,17 @@ impl TemplateContext {
142147 } ) ;
143148 }
144149
145- if let Some ( env_var) = & field. env_var {
146- push ( format ! ( "@envvar {env_var}" ) ) ;
150+ if let Some ( env_var) = & field. env_var
151+ && !env_var. is_empty ( )
152+ {
153+ push ( format ! ( "@env {env_var}" ) ) ;
154+ }
155+
156+ if let SchemaType :: Enum ( enu) = & field. schema . ty
157+ && let Ok ( enum_values) = render_enum_values ( enu)
158+ && !enum_values. is_empty ( )
159+ {
160+ push ( format ! ( "@values {enum_values}" ) ) ;
147161 }
148162
149163 if lines. is_empty ( ) {
@@ -189,14 +203,22 @@ impl TemplateContext {
189203 key
190204 }
191205
206+ pub fn get_stack_value ( & self ) -> Option < Schema > {
207+ let key = self . get_stack_key ( ) ;
208+
209+ self . options . custom_values . get ( & key) . cloned ( )
210+ }
211+
192212 pub fn is_expanded ( & self , key : & String ) -> bool {
193213 self . options . expand_fields . contains ( key)
194214 }
195215
196216 pub fn is_hidden ( & self , field : & SchemaField ) -> bool {
197217 let key = self . get_stack_key ( ) ;
198218
199- field. hidden || self . options . hide_fields . contains ( & key)
219+ field. hidden
220+ || self . options . hide_fields . contains ( & key)
221+ || !self . options . only_fields . is_empty ( ) && !self . options . only_fields . contains ( & key)
200222 }
201223
202224 pub fn push_stack ( & mut self , name : & str ) {
@@ -216,6 +238,27 @@ impl TemplateContext {
216238
217239 initial. to_owned ( )
218240 }
241+
242+ pub fn validate_schema_variant < ' a > (
243+ & self ,
244+ custom : Option < & ' a Schema > ,
245+ fallback : & ' a Schema ,
246+ ) -> & ' a Schema {
247+ if let Some ( custom) = custom {
248+ if mem:: discriminant ( & custom. ty ) == mem:: discriminant ( & fallback. ty ) {
249+ return custom;
250+ } else {
251+ panic ! (
252+ "Received an invalid custom value for `{}`, mismatched schema types.\n \n Expected: {:#?}\n \n Received: {:#?}" ,
253+ self . get_stack_key( ) ,
254+ fallback,
255+ custom
256+ ) ;
257+ }
258+ }
259+
260+ fallback
261+ }
219262}
220263
221264pub fn render_array ( _array : & ArrayType ) -> RenderResult {
@@ -240,6 +283,26 @@ pub fn render_enum(enu: &EnumType) -> RenderResult {
240283 render_null ( )
241284}
242285
286+ pub fn render_enum_values ( enu : & EnumType ) -> RenderResult {
287+ let values: Vec < String > = match & enu. variants {
288+ Some ( variants) => variants
289+ . iter ( )
290+ . filter_map ( |( _, variant) | {
291+ if variant. hidden {
292+ None
293+ } else if let SchemaType :: Literal ( lit) = & variant. schema . ty {
294+ Some ( lit_to_string ( & lit. value ) )
295+ } else {
296+ None
297+ }
298+ } )
299+ . collect ( ) ,
300+ None => enu. values . iter ( ) . map ( lit_to_string) . collect ( ) ,
301+ } ;
302+
303+ Ok ( values. join ( " | " ) )
304+ }
305+
243306pub fn render_float ( float : & FloatType ) -> RenderResult {
244307 if let Some ( default) = & float. default {
245308 return Ok ( lit_to_string ( default) ) ;
0 commit comments