toml: add reflection method (#12664)
							parent
							
								
									0da7e2f8ab
								
							
						
					
					
						commit
						1d6cc57d9c
					
				| 
						 | 
					@ -226,3 +226,36 @@ fn (a Any) value_(value Any, key []string) Any {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (a Any) reflect<T>() T {
 | 
				
			||||||
 | 
						mut reflected := T{}
 | 
				
			||||||
 | 
						$for field in T.fields {
 | 
				
			||||||
 | 
							$if field.typ is string {
 | 
				
			||||||
 | 
								reflected.$(field.name) = a.value(field.name).default_to('').string()
 | 
				
			||||||
 | 
							} $else $if field.typ is bool {
 | 
				
			||||||
 | 
								reflected.$(field.name) = a.value(field.name).default_to(false).bool()
 | 
				
			||||||
 | 
							} $else $if field.typ is int {
 | 
				
			||||||
 | 
								reflected.$(field.name) = a.value(field.name).default_to(0).int()
 | 
				
			||||||
 | 
							} $else $if field.typ is f32 {
 | 
				
			||||||
 | 
								reflected.$(field.name) = a.value(field.name).default_to(0.0).f32()
 | 
				
			||||||
 | 
							} $else $if field.typ is f64 {
 | 
				
			||||||
 | 
								reflected.$(field.name) = a.value(field.name).default_to(0.0).f64()
 | 
				
			||||||
 | 
							} $else $if field.typ is i64 {
 | 
				
			||||||
 | 
								reflected.$(field.name) = a.value(field.name).default_to(0).i64()
 | 
				
			||||||
 | 
							} $else $if field.typ is u64 {
 | 
				
			||||||
 | 
								reflected.$(field.name) = a.value(field.name).default_to(0).u64()
 | 
				
			||||||
 | 
							} $else $if field.typ is Any {
 | 
				
			||||||
 | 
								reflected.$(field.name) = a.value(field.name)
 | 
				
			||||||
 | 
							} $else $if field.typ is DateTime {
 | 
				
			||||||
 | 
								dt := DateTime{'0000-00-00T00:00:00.000'}
 | 
				
			||||||
 | 
								reflected.$(field.name) = a.value(field.name).default_to(dt).datetime()
 | 
				
			||||||
 | 
							} $else $if field.typ is Date {
 | 
				
			||||||
 | 
								da := Date{'0000-00-00'}
 | 
				
			||||||
 | 
								reflected.$(field.name) = a.value(field.name).default_to(da).date()
 | 
				
			||||||
 | 
							} $else $if field.typ is Time {
 | 
				
			||||||
 | 
								t := Time{'00:00:00.000'}
 | 
				
			||||||
 | 
								reflected.$(field.name) = a.value(field.name).default_to(t).time()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return reflected
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,50 @@
 | 
				
			||||||
 | 
					import toml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const toml_text = '# This TOML can reflect to a struct
 | 
				
			||||||
 | 
					name = "Tom"
 | 
				
			||||||
 | 
					age = 45
 | 
				
			||||||
 | 
					height = 1.97
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					birthday = 1980-04-23
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[bio]
 | 
				
			||||||
 | 
					text = "Tom has done many great things"
 | 
				
			||||||
 | 
					years_of_service = 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[config]
 | 
				
			||||||
 | 
					data = [ 1, 2, 3 ]
 | 
				
			||||||
 | 
					levels = { "info" = 1, "warn" = 2, "critical" = 3 }
 | 
				
			||||||
 | 
					'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Bio {
 | 
				
			||||||
 | 
						text             string
 | 
				
			||||||
 | 
						years_of_service int
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct User {
 | 
				
			||||||
 | 
						name     string
 | 
				
			||||||
 | 
						age      int
 | 
				
			||||||
 | 
						height   f64
 | 
				
			||||||
 | 
						birthday toml.Date
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config toml.Any
 | 
				
			||||||
 | 
					mut:
 | 
				
			||||||
 | 
						bio Bio
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fn test_reflect() {
 | 
				
			||||||
 | 
						toml_doc := toml.parse(toml_text) or { panic(err) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mut user := toml_doc.reflect<User>()
 | 
				
			||||||
 | 
						user.bio = toml_doc.value('bio').reflect<Bio>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert user.name == 'Tom'
 | 
				
			||||||
 | 
						assert user.age == 45
 | 
				
			||||||
 | 
						assert user.height == 1.97
 | 
				
			||||||
 | 
						assert user.birthday.str() == '1980-04-23'
 | 
				
			||||||
 | 
						assert user.bio.text == 'Tom has done many great things'
 | 
				
			||||||
 | 
						assert user.bio.years_of_service == 5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						assert user.config.value('data[0]').int() == 1
 | 
				
			||||||
 | 
						assert user.config.value('levels.warn').int() == 2
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -173,6 +173,10 @@ pub fn (d Doc) to_any() Any {
 | 
				
			||||||
	return ast_to_any(d.ast.table)
 | 
						return ast_to_any(d.ast.table)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub fn (d Doc) reflect<T>() T {
 | 
				
			||||||
 | 
						return d.to_any().reflect<T>()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// value queries a value from the TOML document.
 | 
					// value queries a value from the TOML document.
 | 
				
			||||||
// `key` supports a small query syntax scheme:
 | 
					// `key` supports a small query syntax scheme:
 | 
				
			||||||
// Maps can be queried in "dotted" form e.g. `a.b.c`.
 | 
					// Maps can be queried in "dotted" form e.g. `a.b.c`.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue