diff --git a/src/disco.rs b/src/disco.rs index 3e9d8ce..2c3189f 100644 --- a/src/disco.rs +++ b/src/disco.rs @@ -164,15 +164,26 @@ impl TryFrom for DiscoInfoResult { features: vec!(), extensions: vec!(), }; + let mut parsing_identities_done = false; + let mut parsing_features_done = false; for child in elem.children() { - if child.is("feature", ns::DISCO_INFO) { - let feature = Feature::try_from(child.clone())?; - result.features.push(feature); - } else if child.is("identity", ns::DISCO_INFO) { + if child.is("identity", ns::DISCO_INFO) { + if parsing_identities_done { + return Err(Error::ParseError("Identity found after features or data forms in disco#info.")); + } let identity = Identity::try_from(child.clone())?; result.identities.push(identity); + } else if child.is("feature", ns::DISCO_INFO) { + parsing_identities_done = true; + if parsing_features_done { + return Err(Error::ParseError("Feature found after data forms in disco#info.")); + } + let feature = Feature::try_from(child.clone())?; + result.features.push(feature); } else if child.is("x", ns::DATA_FORMS) { + parsing_identities_done = true; + parsing_features_done = true; let data_form = DataForm::try_from(child.clone())?; if data_form.type_ != DataFormType::Result_ { return Err(Error::ParseError("Data form must have a 'result' type in disco#info.")); @@ -441,6 +452,22 @@ mod tests { _ => panic!(), }; assert_eq!(message, "disco#info feature not present in disco#info."); + + let elem: Element = "".parse().unwrap(); + let error = DiscoInfoResult::try_from(elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Identity found after features or data forms in disco#info."); + + let elem: Element = "coucou".parse().unwrap(); + let error = DiscoInfoResult::try_from(elem).unwrap_err(); + let message = match error { + Error::ParseError(string) => string, + _ => panic!(), + }; + assert_eq!(message, "Feature found after data forms in disco#info."); } #[test]