diff --git a/integration/hurl/tests_error_parser/xml.err b/integration/hurl/tests_error_parser/xml.err index 0813188f6..b4a8d0bc5 100644 --- a/integration/hurl/tests_error_parser/xml.err +++ b/integration/hurl/tests_error_parser/xml.err @@ -1,7 +1,7 @@ -error: Error { pos: Pos { line: 2, column: 1 }, recoverable: false, inner: Xml } - --> tests_error_parser/xml.hurl:2:1 +error: Parsing XML + --> tests_error_parser/xml.hurl:2:14 | 2 | - | ^ Error { pos: Pos { line: 2, column: 1 }, recoverable: false, inner: Xml } + | ^ invalid XML | diff --git a/packages/hurl_core/src/error/mod.rs b/packages/hurl_core/src/error/mod.rs index b959e3309..5d9d08372 100644 --- a/packages/hurl_core/src/error/mod.rs +++ b/packages/hurl_core/src/error/mod.rs @@ -61,6 +61,7 @@ impl Error for parser::Error { ParseError::UrlInvalidStart => "Parsing URL".to_string(), ParseError::Version => "Parsing version".to_string(), ParseError::XPathExpr => "Parsing XPath expression".to_string(), + ParseError::Xml => "Parsing XML".to_string(), // TODO: implement all variants // _ => , ParseError::Eof => format!("{self:?}"), @@ -69,7 +70,6 @@ impl Error for parser::Error { ParseError::InvalidOption => format!("{self:?}"), ParseError::Unicode => format!("{self:?}"), ParseError::Url => format!("{self:?}"), - ParseError::Xml => format!("{self:?}"), } } @@ -138,7 +138,7 @@ impl Error for parser::Error { "HTTP version must be HTTP, HTTP/1.0, HTTP/1.1 or HTTP/2".to_string() } ParseError::XPathExpr => "expecting a XPath expression".to_string(), - + ParseError::Xml => "invalid XML".to_string(), // TODO: implement all variants // _ => format!("{self:?}"), ParseError::Eof => format!("{self:?}"), @@ -147,7 +147,6 @@ impl Error for parser::Error { ParseError::InvalidOption => format!("{self:?}"), ParseError::Unicode => format!("{self:?}"), ParseError::Url => format!("{self:?}"), - ParseError::Xml => format!("{self:?}"), } } } diff --git a/packages/hurl_core/src/parser/xml.rs b/packages/hurl_core/src/parser/xml.rs index 64ad42179..72e42ab2a 100644 --- a/packages/hurl_core/src/parser/xml.rs +++ b/packages/hurl_core/src/parser/xml.rs @@ -47,8 +47,6 @@ use crate::parser::ParseResult; /// byte a possible valid XML body. /// pub fn parse(reader: &mut Reader) -> ParseResult { - let start = reader.state; - // We test if our first character is a start of an XML text. // If not, we return immediately a recoverable error. // Otherwise, we start parsing the supposedly XML buffer. Any @@ -56,13 +54,7 @@ pub fn parse(reader: &mut Reader) -> ParseResult { let c = reader.peek(); match c { Some('<') => {} - _ => { - return Err(Error { - pos: start.pos, - recoverable: true, - inner: ParseError::Xml, - }) - } + _ => return Err(Error::new(reader.state.pos, true, ParseError::Xml)), } let mut buf = String::new(); @@ -82,6 +74,9 @@ pub fn parse(reader: &mut Reader) -> ParseResult { ptr::null(), ); + // We keep track of the previous char reader position, to accurately raise eventual error. + let mut prev_pos = reader.state.pos; + while let Some(c) = reader.read() { buf.push(c); @@ -95,11 +90,7 @@ pub fn parse(reader: &mut Reader) -> ParseResult { let ret = xmlParseChunk(context, bytes, count, end); if ret != 0 { xmlFreeParserCtxt(context); - return Err(Error { - pos: start.pos, - recoverable: false, - inner: ParseError::Xml, - }); + return Err(Error::new(prev_pos, false, ParseError::Xml)); } // End of the XML body is detected with a closing element event and depth of the tree. @@ -110,6 +101,7 @@ pub fn parse(reader: &mut Reader) -> ParseResult { { break; } + prev_pos = reader.state.pos; } xmlFreeParserCtxt(context); @@ -240,18 +232,30 @@ mod tests { let mut reader = Reader::new("<<"); let error = parse(&mut reader).err().unwrap(); - assert_eq!(error.pos, Pos { line: 1, column: 1 }); + assert_eq!(error.pos, Pos { line: 1, column: 2 }); assert_eq!(error.inner, ParseError::Xml); assert!(!error.recoverable); let mut reader = Reader::new("