From 76bc93d73bf2503bd1ecc78f7bb9aa051bbfb9c8 Mon Sep 17 00:00:00 2001 From: kpcyrd Date: Fri, 24 May 2019 17:18:21 +0200 Subject: [PATCH] Add a function to get a named xml element --- README.md | 1 + docs/reference.rst | 16 +++++++++++ src/engine/ctx.rs | 1 + src/runtime/xml.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++- src/xml.rs | 34 +++--------------------- 5 files changed, 86 insertions(+), 32 deletions(-) diff --git a/README.md b/README.md index b9b1fb3..7238797 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,7 @@ For everything else please have a look at the [detailed list][1]. - [utf8_decode](https://sn0int.readthedocs.io/en/latest/reference.html#utf8-decode) - [x509_parse_pem](https://sn0int.readthedocs.io/en/latest/reference.html#x509-parse-pem) - [xml_decode](https://sn0int.readthedocs.io/en/latest/reference.html#xml-decode) + - [xml_named](https://sn0int.readthedocs.io/en/latest/reference.html#xml-named) ## Rationale diff --git a/docs/reference.rst b/docs/reference.rst index 4c8afbd..860956a 100644 --- a/docs/reference.rst +++ b/docs/reference.rst @@ -914,3 +914,19 @@ Decode a lua value from an xml document. print(foo['attrs']['fizz']) print(foo['text']) + +xml_named +--------- + +Get a named child element from a parent element. + +.. code-block:: lua + + x = xml_decode('bar') + if last_err() then return end + + body = x['children'][1] + foo = xml_named(body, 'foo') + if foo ~= nil then + print(foo) + end diff --git a/src/engine/ctx.rs b/src/engine/ctx.rs index 5703e7d..2166cd0 100644 --- a/src/engine/ctx.rs +++ b/src/engine/ctx.rs @@ -395,6 +395,7 @@ fn ctx<'a>(env: Environment, logger: Arc>>) -> (hlua::Lua<'a runtime::utf8_decode(&mut lua, state.clone()); runtime::x509_parse_pem(&mut lua, state.clone()); runtime::xml_decode(&mut lua, state.clone()); + runtime::xml_named(&mut lua, state.clone()); debug!("Created lua context"); diff --git a/src/runtime/xml.rs b/src/runtime/xml.rs index c8625b9..366eb76 100644 --- a/src/runtime/xml.rs +++ b/src/runtime/xml.rs @@ -12,6 +12,70 @@ pub fn xml_decode(lua: &mut hlua::Lua, state: Arc) { })) } +#[inline] +fn key_is(key: &AnyLuaValue, expected: &str) -> bool { + match key { + AnyLuaValue::LuaString(key) => key.as_str() == expected, + _ => false, + } +} + +#[inline] +fn get_children(xml: AnyLuaValue) -> Option { + match xml { + AnyLuaValue::LuaArray(arr) => { + for (key, value) in arr { + if key_is(&key, "children") { + return Some(value); + } + } + + None + } + _ => None, + } +} + +#[inline] +fn match_element_name(xml: &AnyLuaValue, name: &str) -> bool { + match xml { + AnyLuaValue::LuaArray(arr) => { + for (key, value) in arr { + if key_is(key, "name") { + match value { + AnyLuaValue::LuaString(key) => { + return key.as_str() == name + }, + _ => return false, + } + } + } + + false + }, + _ => false, + } +} + +pub fn xml_named(lua: &mut hlua::Lua, _state: Arc) { + lua.set("xml_named", hlua::function2(move |xml: AnyLuaValue, name: String| -> AnyLuaValue { + if let Some(value) = get_children(xml) { + match value { + AnyLuaValue::LuaArray(arr) => { + for (_, value) in arr { + if match_element_name(&value, &name) { + return value; + } + } + }, + _ => (), + } + } + + AnyLuaValue::LuaNil + })) +} + #[cfg(test)] mod tests { use crate::engine::ctx::Script; @@ -29,7 +93,7 @@ mod tests { return 'wrong body tag name' end - foo = body['named']['foo'] + foo = xml_named(body, 'foo') if foo['name'] ~= 'foo' then return 'foo has wrong tag name' end diff --git a/src/xml.rs b/src/xml.rs index 1c6c6de..779fed9 100644 --- a/src/xml.rs +++ b/src/xml.rs @@ -28,7 +28,6 @@ pub struct XmlElement { pub attrs: HashMap, pub text: Option, pub children: Vec, - pub named: HashMap, } impl XmlElement { @@ -43,7 +42,6 @@ impl XmlElement { attrs, text: None, children: Vec::new(), - named: HashMap::new(), } } } @@ -100,12 +98,11 @@ fn decode_raw(x: &str) -> Result { let name = name.local_name; if child.name != name { - bail!("todo") + bail!("end element name doesn't match start element name") } if let Some(tail) = stack.last_mut() { - tail.children.push(child.clone()); - tail.named.insert(name, child); + tail.children.push(child); } else { doc.children.push(child); } @@ -118,7 +115,7 @@ fn decode_raw(x: &str) -> Result { // TODO: consider ignoring this? if !stack.is_empty() { - bail!("todo") + bail!("end of document but still open elements remaining") } Ok(doc) @@ -144,7 +141,6 @@ mod tests { attrs: HashMap::new(), text: None, children: vec![], - named: hashmap!{}, } ] }); @@ -167,20 +163,8 @@ mod tests { }, text: None, children: vec![], - named: hashmap!{}, } ], - named: hashmap!{ - String::from("foo") => XmlElement { - name: String::from("foo"), - attrs: hashmap!{ - String::from("x") => String::from("1"), - }, - text: None, - children: vec![], - named: hashmap!{}, - } - }, } ] }); @@ -203,20 +187,8 @@ mod tests { }, text: Some(String::from("hello world")), children: vec![], - named: hashmap!{}, } ], - named: hashmap!{ - String::from("foo") => XmlElement { - name: String::from("foo"), - attrs: hashmap!{ - String::from("x") => String::from("1"), - }, - text: Some(String::from("hello world")), - children: vec![], - named: hashmap!{}, - } - }, } ] });