Comparison

teal-src/util/datamapper.tl @ 11454:1d9c1893cc5e

util.datamapper: Use enum instead of mutually exclusive booleans Cleaner and rules out invalid combinations.
author Kim Alvefur <zash@zash.se>
date Sun, 14 Mar 2021 01:57:00 +0100
parent 11453:f0037234b2e9
child 11455:a5050e21ab08
comparison
equal deleted inserted replaced
11453:f0037234b2e9 11454:1d9c1893cc5e
26 if s == "true" or s == "1" then 26 if s == "true" or s == "1" then
27 return true 27 return true
28 elseif s == "false" or s == "0" then 28 elseif s == "false" or s == "0" then
29 return false 29 return false
30 end 30 end
31 end
32
33 local enum value_goes
34 "in_tag_name"
35 "in_text"
36 "in_text_tag"
37 "in_attribute"
38 "in_single_attribute"
39 "in_children"
31 end 40 end
32 41
33 local function parse_object (schema : js.schema_t, s : st.stanza_t) : table 42 local function parse_object (schema : js.schema_t, s : st.stanza_t) : table
34 local out : { string : any } = {} 43 local out : { string : any } = {}
35 if schema.properties then 44 if schema.properties then
36 for prop, propschema in pairs(schema.properties) do 45 for prop, propschema in pairs(schema.properties) do
37 -- TODO factor out, if it's generic enough 46 -- TODO factor out, if it's generic enough
38 local name = prop 47 local name = prop
39 local namespace = s.attr.xmlns; 48 local namespace = s.attr.xmlns;
40 local prefix : string = nil 49 local prefix : string = nil
41 local is_attribute = false 50 local value_where : value_goes = "in_text_tag"
42 local is_text = false
43 local name_is_value = false;
44 local single_attribute : string 51 local single_attribute : string
45 local enums : { any } 52 local enums : { any }
46 53
47 local proptype : js.schema_t.type_e 54 local proptype : js.schema_t.type_e
48 if propschema is js.schema_t then 55 if propschema is js.schema_t then
60 end 67 end
61 if propschema.xml.prefix then 68 if propschema.xml.prefix then
62 prefix = propschema.xml.prefix 69 prefix = propschema.xml.prefix
63 end 70 end
64 if propschema.xml.attribute then 71 if propschema.xml.attribute then
65 is_attribute = true 72 value_where = "in_attribute"
66 elseif propschema.xml.text then 73 elseif propschema.xml.text then
67 -- XXX Not yet in OpenAPI 74 -- XXX Not yet in OpenAPI
68 is_text = true 75 value_where = "in_text"
69 elseif propschema.xml.x_name_is_value then 76 elseif propschema.xml.x_name_is_value then
70 -- XXX Custom extension 77 -- XXX Custom extension
71 name_is_value = true 78 value_where = "in_tag_name"
72 elseif propschema.xml.x_single_attribute then 79 elseif propschema.xml.x_single_attribute then
73 -- XXX Custom extension 80 -- XXX Custom extension
74 single_attribute = propschema.xml.x_single_attribute 81 single_attribute = propschema.xml.x_single_attribute
82 value_where = "in_single_attribute"
75 end 83 end
76 if propschema["const"] then 84 if propschema["const"] then
77 enums = { propschema["const"] } 85 enums = { propschema["const"] }
78 elseif propschema["enum"] then 86 elseif propschema["enum"] then
79 enums = propschema["enum"] 87 enums = propschema["enum"]
80 end 88 end
81 end 89 end
82 90
83 if name_is_value then 91 if value_where == "in_tag_name" then
84 local c : st.stanza_t 92 local c : st.stanza_t
85 if proptype == "boolean" then 93 if proptype == "boolean" then
86 c = s:get_child(name, namespace); 94 c = s:get_child(name, namespace);
87 elseif enums and proptype == "string" then 95 elseif enums and proptype == "string" then
88 -- XXX O(n²) ? 96 -- XXX O(n²) ?
98 if c and proptype == "string" then 106 if c and proptype == "string" then
99 out[prop] = c.name; 107 out[prop] = c.name;
100 elseif proptype == "boolean" and c then 108 elseif proptype == "boolean" and c then
101 out[prop] = true; 109 out[prop] = true;
102 end 110 end
103 elseif is_attribute then 111 elseif value_where == "in_attribute" then
104 local attr = name 112 local attr = name
105 if prefix then 113 if prefix then
106 attr = prefix .. ':' .. name 114 attr = prefix .. ':' .. name
107 elseif namespace ~= s.attr.xmlns then 115 elseif namespace ~= s.attr.xmlns then
108 attr = namespace .. "\1" .. name 116 attr = namespace .. "\1" .. name
115 elseif proptype == "boolean" then 123 elseif proptype == "boolean" then
116 out[prop] = toboolean(s.attr[attr]) 124 out[prop] = toboolean(s.attr[attr])
117 -- else TODO 125 -- else TODO
118 end 126 end
119 127
120 elseif is_text then 128 elseif value_where == "in_text" then
121 if proptype == "string" then 129 if proptype == "string" then
122 out[prop] = s:get_text() 130 out[prop] = s:get_text()
123 elseif proptype == "integer" or proptype == "number" then 131 elseif proptype == "integer" or proptype == "number" then
124 out[prop] = tonumber(s:get_text()) 132 out[prop] = tonumber(s:get_text())
125 end 133 end
126 134
127 elseif single_attribute then 135 elseif value_where == "in_single_attribute" then
128 local c = s:get_child(name, namespace) 136 local c = s:get_child(name, namespace)
129 local a = c and c.attr[single_attribute] 137 local a = c and c.attr[single_attribute]
130 if proptype == "string" then 138 if proptype == "string" then
131 out[prop] = a 139 out[prop] = a
132 elseif proptype == "integer" or proptype == "number" then 140 elseif proptype == "integer" or proptype == "number" then
187 end 195 end
188 196
189 local name = prop 197 local name = prop
190 local namespace = current_ns 198 local namespace = current_ns
191 local prefix : string = nil 199 local prefix : string = nil
192 local is_attribute = false 200 local value_where : value_goes = "in_text_tag"
193 local is_text = false
194 local name_is_value = false;
195 local single_attribute : string 201 local single_attribute : string
196 202
197 if propschema is js.schema_t and propschema.xml then 203 if propschema is js.schema_t and propschema.xml then
198 204
199 if propschema.xml.name then 205 if propschema.xml.name then
206 if propschema.xml.prefix then 212 if propschema.xml.prefix then
207 prefix = propschema.xml.prefix 213 prefix = propschema.xml.prefix
208 end 214 end
209 215
210 if propschema.xml.attribute then 216 if propschema.xml.attribute then
211 is_attribute = true 217 value_where = "in_attribute"
212 elseif propschema.xml.text then 218 elseif propschema.xml.text then
213 is_text = true 219 value_where = "in_text"
214 elseif propschema.xml.x_name_is_value then 220 elseif propschema.xml.x_name_is_value then
215 name_is_value = true 221 value_where = "in_tag_name"
216 elseif propschema.xml.x_single_attribute then 222 elseif propschema.xml.x_single_attribute then
217 single_attribute = propschema.xml.x_single_attribute 223 single_attribute = propschema.xml.x_single_attribute
218 end 224 value_where = "in_single_attribute"
219 end 225 end
220 226 end
221 if is_attribute then 227
228 if value_where == "in_attribute" then
222 local attr = name 229 local attr = name
223 if prefix then 230 if prefix then
224 attr = prefix .. ':' .. name 231 attr = prefix .. ':' .. name
225 elseif namespace ~= current_ns then 232 elseif namespace ~= current_ns then
226 attr = namespace .. "\1" .. name 233 attr = namespace .. "\1" .. name
233 elseif proptype == "integer" and v is number then 240 elseif proptype == "integer" and v is number then
234 out.attr[attr] = string.format("%d", v) 241 out.attr[attr] = string.format("%d", v)
235 elseif proptype == "boolean" then 242 elseif proptype == "boolean" then
236 out.attr[attr] = v and "1" or "0" 243 out.attr[attr] = v and "1" or "0"
237 end 244 end
238 elseif is_text then 245 elseif value_where == "in_text" then
239 if v is string then 246 if v is string then
240 out:text(v) 247 out:text(v)
241 end 248 end
242 elseif single_attribute then 249 elseif value_where == "in_single_attribute" then
243 local propattr : { string : string } = {} 250 local propattr : { string : string } = {}
244 251
245 if namespace ~= current_ns then 252 if namespace ~= current_ns then
246 propattr.xmlns = namespace 253 propattr.xmlns = namespace
247 end 254 end
260 else 267 else
261 local propattr : { string : string } 268 local propattr : { string : string }
262 if namespace ~= current_ns then 269 if namespace ~= current_ns then
263 propattr = { xmlns = namespace } 270 propattr = { xmlns = namespace }
264 end 271 end
265 if name_is_value then 272 if value_where == "in_tag_name" then
266 if proptype == "string" and v is string then 273 if proptype == "string" and v is string then
267 out:tag(v, propattr):up(); 274 out:tag(v, propattr):up();
268 elseif proptype == "boolean" and v == true then 275 elseif proptype == "boolean" and v == true then
269 out:tag(name, propattr):up(); 276 out:tag(name, propattr):up();
270 end 277 end