| 1 | module yaml |
| 2 | |
| 3 | import time |
| 4 | import x.json2 |
| 5 | |
| 6 | fn (a Any) value_(current Any, key []string) ?Any { |
| 7 | if key.len == 0 { |
| 8 | return none |
| 9 | } |
| 10 | k, index := parse_array_key(key[0]) |
| 11 | value := match current { |
| 12 | []Any { |
| 13 | if k != '' { |
| 14 | return none |
| 15 | } |
| 16 | current[index] or { return none } |
| 17 | } |
| 18 | map[string]Any { |
| 19 | v := current[k] or { return none } |
| 20 | if index > -1 { |
| 21 | if v is []Any { |
| 22 | v[index] or { return none } |
| 23 | } else { |
| 24 | return none |
| 25 | } |
| 26 | } else { |
| 27 | v |
| 28 | } |
| 29 | } |
| 30 | else { |
| 31 | return none |
| 32 | } |
| 33 | } |
| 34 | |
| 35 | if key.len <= 1 { |
| 36 | return value |
| 37 | } |
| 38 | return match value { |
| 39 | []Any, map[string]Any { a.value_(value, key[1..]) } |
| 40 | else { none } |
| 41 | } |
| 42 | } |
| 43 | |
| 44 | fn parse_dotted_key(key string) ![]string { |
| 45 | mut out := []string{} |
| 46 | mut buf := '' |
| 47 | mut in_string := false |
| 48 | mut delimiter := u8(` `) |
| 49 | for ch in key { |
| 50 | if ch in [`"`, `'`] { |
| 51 | if !in_string { |
| 52 | delimiter = ch |
| 53 | in_string = true |
| 54 | continue |
| 55 | } |
| 56 | if ch == delimiter { |
| 57 | in_string = false |
| 58 | if buf != '' { |
| 59 | out << buf |
| 60 | } |
| 61 | buf = '' |
| 62 | delimiter = ` ` |
| 63 | continue |
| 64 | } |
| 65 | } |
| 66 | buf += ch.ascii_str() |
| 67 | if !in_string && ch == `.` { |
| 68 | buf = buf[..buf.len - 1] |
| 69 | if buf != '' { |
| 70 | out << buf |
| 71 | } |
| 72 | buf = '' |
| 73 | } |
| 74 | } |
| 75 | if buf != '' { |
| 76 | out << buf |
| 77 | } |
| 78 | if in_string { |
| 79 | return error('yaml: missing closing string delimiter `${delimiter.ascii_str()}`') |
| 80 | } |
| 81 | return out |
| 82 | } |
| 83 | |
| 84 | fn parse_array_key(key string) (string, int) { |
| 85 | mut index := -1 |
| 86 | mut k := key |
| 87 | if k.contains('[') { |
| 88 | index = k.all_after('[').all_before(']').int() |
| 89 | if k.starts_with('[') { |
| 90 | k = '' |
| 91 | } else { |
| 92 | k = k.all_before('[') |
| 93 | } |
| 94 | } |
| 95 | return k, index |
| 96 | } |
| 97 | |
| 98 | fn from_json2(value json2.Any) Any { |
| 99 | return match value { |
| 100 | []json2.Any { |
| 101 | mut arr := []Any{cap: value.len} |
| 102 | for item in value { |
| 103 | arr << from_json2(item) |
| 104 | } |
| 105 | Any(arr) |
| 106 | } |
| 107 | map[string]json2.Any { |
| 108 | mut out := map[string]Any{} |
| 109 | for key, item in value { |
| 110 | out[key] = from_json2(item) |
| 111 | } |
| 112 | Any(out) |
| 113 | } |
| 114 | bool { |
| 115 | Any(value) |
| 116 | } |
| 117 | f32, f64 { |
| 118 | Any(f64(value)) |
| 119 | } |
| 120 | i8, i16, i32, int { |
| 121 | Any(int(value)) |
| 122 | } |
| 123 | i64 { |
| 124 | Any(value) |
| 125 | } |
| 126 | u8, u16, u32, u64 { |
| 127 | Any(u64(value)) |
| 128 | } |
| 129 | string { |
| 130 | Any(value) |
| 131 | } |
| 132 | time.Time { |
| 133 | Any(value.str()) |
| 134 | } |
| 135 | json2.Null { |
| 136 | null |
| 137 | } |
| 138 | } |
| 139 | } |
| 140 | |