util.datamapper: Factor out extraction of the XML part to use
authorKim Alvefur <zash@zash.se>
Sat, 20 Mar 2021 19:02:18 +0100
changeset 11469 19a88b61ab4e
parent 11468 6e25409fecbd
child 11470 c098d07e6717
util.datamapper: Factor out extraction of the XML part to use So extract_value() takes an XML tag and details about which part we're interested in and returns that. Factoring this out will help with array implementation since this will be common behavior.
teal-src/util/datamapper.tl
util/datamapper.lua
--- a/teal-src/util/datamapper.tl	Fri Mar 19 19:07:25 2021 +0100
+++ b/teal-src/util/datamapper.tl	Sat Mar 20 19:02:18 2021 +0100
@@ -115,6 +115,45 @@
 local parse_object : function (schema : schema_t, s : st.stanza_t) : { string : any }
 local parse_array : function (schema : schema_t, s : st.stanza_t) : { any }
 
+local function extract_value (s : st.stanza_t, value_where : value_goes, proptype : json.json_type_name, name : string, namespace : string, prefix : string, single_attribute : string, enums : { any }) : string
+	if value_where == "in_tag_name" then
+		local c : st.stanza_t
+		if proptype == "boolean" then
+			c = s:get_child(name, namespace);
+		elseif enums and proptype == "string" then
+			-- XXX O(n²) ?
+			-- Probably better to flip the table and loop over :childtags(nil, ns), should be 2xO(n)
+			-- BUT works first, optimize later
+			for i = 1, #enums do
+				c = s:get_child(enums[i] as string, namespace);
+				if c then break end
+			end
+		else
+			c = s:get_child(nil, namespace);
+		end
+		if c then
+			return c.name;
+		end
+	elseif value_where == "in_attribute" then
+		local attr = name
+		if prefix then
+			attr = prefix .. ':' .. name
+		elseif namespace ~= s.attr.xmlns then
+			attr = namespace .. "\1" .. name
+		end
+		return s.attr[attr]
+
+	elseif value_where == "in_text" then
+		return s:get_text()
+
+	elseif value_where == "in_single_attribute" then
+		local c = s:get_child(name, namespace)
+		return c and c.attr[single_attribute]
+	elseif value_where == "in_text_tag" then
+		return s:get_child_text(name, namespace)
+	end
+end
+
 function parse_object (schema : schema_t, s : st.stanza_t) : { string : any }
 	local out : { string : any } = {}
 	if schema is json_schema_object and schema.properties then
@@ -122,43 +161,7 @@
 
 			local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns)
 
-			local value : string
-			if value_where == "in_tag_name" then
-				local c : st.stanza_t
-				if proptype == "boolean" then
-					c = s:get_child(name, namespace);
-				elseif enums and proptype == "string" then
-					-- XXX O(n²) ?
-					-- Probably better to flip the table and loop over :childtags(nil, ns), should be 2xO(n)
-					-- BUT works first, optimize later
-					for i = 1, #enums do
-						c = s:get_child(enums[i] as string, namespace);
-						if c then break end
-					end
-				else
-					c = s:get_child(nil, namespace);
-				end
-				if c is st.stanza_t then
-					value = c.name;
-				end
-			elseif value_where == "in_attribute" then
-				local attr = name
-				if prefix then
-					attr = prefix .. ':' .. name
-				elseif namespace ~= s.attr.xmlns then
-					attr = namespace .. "\1" .. name
-				end
-				value = s.attr[attr]
-
-			elseif value_where == "in_text" then
-				value = s:get_text()
-
-			elseif value_where == "in_single_attribute" then
-				local c = s:get_child(name, namespace)
-				value = c and c.attr[single_attribute]
-			elseif value_where == "in_text_tag" then
-				value = s:get_child_text(name, namespace)
-			elseif value_where == "in_children" and propschema is json_schema_object then
+			if value_where == "in_children" and propschema is json_schema_object then
 				if proptype == "object" then
 					local c = s:get_child(name, namespace)
 					if c then
@@ -177,9 +180,8 @@
 					error "unreachable"
 				end
 			else
-				error "unreachable"
-			end
-			if value_where ~= "in_children" and value_where ~= "in_wrapper" then
+				local value : string = extract_value (s, value_where, proptype, name, namespace, prefix, single_attribute, enums)
+
 				out[prop] = totype(proptype, value)
 			end
 		end
--- a/util/datamapper.lua	Fri Mar 19 19:07:25 2021 +0100
+++ b/util/datamapper.lua	Sat Mar 20 19:02:18 2021 +0100
@@ -82,6 +82,45 @@
 local parse_object
 local parse_array
 
+local function extract_value(s, value_where, proptype, name, namespace, prefix, single_attribute, enums)
+	if value_where == "in_tag_name" then
+		local c
+		if proptype == "boolean" then
+			c = s:get_child(name, namespace);
+		elseif enums and proptype == "string" then
+
+			for i = 1, #enums do
+				c = s:get_child(enums[i], namespace);
+				if c then
+					break
+				end
+			end
+		else
+			c = s:get_child(nil, namespace);
+		end
+		if c then
+			return c.name
+		end
+	elseif value_where == "in_attribute" then
+		local attr = name
+		if prefix then
+			attr = prefix .. ":" .. name
+		elseif namespace ~= s.attr.xmlns then
+			attr = namespace .. "\1" .. name
+		end
+		return s.attr[attr]
+
+	elseif value_where == "in_text" then
+		return s:get_text()
+
+	elseif value_where == "in_single_attribute" then
+		local c = s:get_child(name, namespace)
+		return c and c.attr[single_attribute]
+	elseif value_where == "in_text_tag" then
+		return s:get_child_text(name, namespace)
+	end
+end
+
 function parse_object(schema, s)
 	local out = {}
 	if type(schema) == "table" and schema.properties then
@@ -89,43 +128,7 @@
 
 			local proptype, value_where, name, namespace, prefix, single_attribute, enums = unpack_propschema(propschema, prop, s.attr.xmlns)
 
-			local value
-			if value_where == "in_tag_name" then
-				local c
-				if proptype == "boolean" then
-					c = s:get_child(name, namespace);
-				elseif enums and proptype == "string" then
-
-					for i = 1, #enums do
-						c = s:get_child(enums[i], namespace);
-						if c then
-							break
-						end
-					end
-				else
-					c = s:get_child(nil, namespace);
-				end
-				if type(c) == "table" then
-					value = c.name;
-				end
-			elseif value_where == "in_attribute" then
-				local attr = name
-				if prefix then
-					attr = prefix .. ":" .. name
-				elseif namespace ~= s.attr.xmlns then
-					attr = namespace .. "\1" .. name
-				end
-				value = s.attr[attr]
-
-			elseif value_where == "in_text" then
-				value = s:get_text()
-
-			elseif value_where == "in_single_attribute" then
-				local c = s:get_child(name, namespace)
-				value = c and c.attr[single_attribute]
-			elseif value_where == "in_text_tag" then
-				value = s:get_child_text(name, namespace)
-			elseif value_where == "in_children" and type(propschema) == "table" then
+			if value_where == "in_children" and type(propschema) == "table" then
 				if proptype == "object" then
 					local c = s:get_child(name, namespace)
 					if c then
@@ -144,9 +147,8 @@
 					error("unreachable")
 				end
 			else
-				error("unreachable")
-			end
-			if value_where ~= "in_children" and value_where ~= "in_wrapper" then
+				local value = extract_value(s, value_where, proptype, name, namespace, prefix, single_attribute, enums)
+
 				out[prop] = totype(proptype, value)
 			end
 		end