Changeset

11465:19a88b61ab4e

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.
author Kim Alvefur <zash@zash.se>
date Sat, 20 Mar 2021 19:02:18 +0100
parents 11464:6e25409fecbd
children 11466:c098d07e6717
files teal-src/util/datamapper.tl util/datamapper.lua
diffstat 2 files changed, 84 insertions(+), 80 deletions(-) [+]
line wrap: on
line diff
--- 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