tamer: Integrate xir::reader as a parser in the lowering pipeline

This allows `XmlXirReader` to be used in a `Lower` operation, just as
everything else, bringing me one step closer to a pipeline that can be
concisely represented; this is finally beginning to unify in a clear way,
though it is still a bit of a mess.

This causes `XmlXirReader` to _act_ like a `parse::Parser` in that it yields
a `ParsedResult`, but it does not use `parse::Parser` itself; that was the
_original_ plan: convert it into a `ParseState` where `XmlXirReader` became
a context, and force `Parser` to yield by feeding it a stream of tokens with
`repeat`, but that ended up performing poorly relative to this change.  I
did some investigation, which I might write about in the future, but for
now, this solution works just fine.

DEV-7145
main
Mike Gerwitz 2022-06-02 10:30:44 -04:00
parent f8c28655dc
commit 8d92667388
7 changed files with 259 additions and 160 deletions

View File

@ -37,6 +37,7 @@ use tamer::{
diagnose::{
AnnotatedSpan, Diagnostic, FsSpanResolver, Reporter, VisualReporter,
},
parse::{ParseError, Parsed, UnknownToken},
xir,
};
@ -86,7 +87,12 @@ pub fn main() -> Result<(), TamecError> {
into_iter_while_ok(
XmlXirReader::new(file, &escaper, ctx),
|toks| {
toks.write(&mut fout, Default::default(), &escaper)
toks.filter_map(|parsed| match parsed {
Parsed::Object(tok) => Some(tok),
_ => None,
})
.write(&mut fout, Default::default(), &escaper)
.map_err(TamecError::from)
},
)?;
@ -183,7 +189,7 @@ fn parse_options(opts: Options, args: Vec<String>) -> Result<Command, Fail> {
#[derive(Debug)]
pub enum TamecError {
Io(io::Error),
XirError(xir::Error),
XirParseError(ParseError<UnknownToken, xir::Error>),
XirWriterError(xir::writer::Error),
Fmt(fmt::Error),
}
@ -194,9 +200,9 @@ impl From<io::Error> for TamecError {
}
}
impl From<xir::Error> for TamecError {
fn from(e: xir::Error) -> Self {
Self::XirError(e)
impl From<ParseError<UnknownToken, xir::Error>> for TamecError {
fn from(e: ParseError<UnknownToken, xir::Error>) -> Self {
Self::XirParseError(e)
}
}
@ -216,7 +222,7 @@ impl Display for TamecError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Io(e) => Display::fmt(e, f),
Self::XirError(e) => Display::fmt(e, f),
Self::XirParseError(e) => Display::fmt(e, f),
Self::XirWriterError(e) => Display::fmt(e, f),
Self::Fmt(e) => Display::fmt(e, f),
}
@ -227,7 +233,7 @@ impl Error for TamecError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
Self::Io(e) => Some(e),
Self::XirError(e) => Some(e),
Self::XirParseError(e) => Some(e),
Self::XirWriterError(e) => Some(e),
Self::Fmt(e) => Some(e),
}
@ -237,7 +243,7 @@ impl Error for TamecError {
impl Diagnostic for TamecError {
fn describe(&self) -> Vec<AnnotatedSpan> {
match self {
Self::XirError(e) => e.describe(),
Self::XirParseError(e) => e.describe(),
// TODO (will fall back to rendering just the error `Display`)
_ => vec![],

View File

@ -35,10 +35,9 @@ use crate::{
Filesystem, FsCanonicalizer, PathFile, VisitOnceFile,
VisitOnceFilesystem,
},
iter::into_iter_while_ok,
ld::xmle::Sections,
obj::xmlo::{self, XmloError, XmloLowerError, XmloReader, XmloToken},
parse::{Lower, ParseError, ParseState, Parsed},
parse::{Lower, ParseError, Parsed, ParsedObject, UnknownToken},
sym::{GlobalSymbolResolve, SymbolId},
xir::reader::XmlXirReader,
xir::{
@ -188,28 +187,29 @@ fn load_xmlo<'a, P: AsRef<Path>, S: Escaper>(
// TODO: This entire block is a WIP and will be incrementally
// abstracted away.
let (mut asg, mut state) = into_iter_while_ok::<_, _, _, TameldError, _>(
XmlXirReader::new(file, escaper, ctx),
let (mut asg, mut state) = Lower::<
ParsedObject<XirToken, XirError>,
flat::State<64>,
>::lower::<_, TameldError>(
&mut XmlXirReader::new(file, escaper, ctx),
|toks| {
Lower::<flat::State<64>, XmloReader>::lower(
&mut flat::State::<64>::parse(toks),
|xmlo| {
let mut iter = xmlo.scan(false, |st, rtok| match st {
true => None,
false => {
*st = matches!(
rtok,
Ok(Parsed::Object(XmloToken::Eoh(..)))
);
Some(rtok)
}
});
Lower::<flat::State<64>, XmloReader>::lower(toks, |xmlo| {
let mut iter = xmlo.scan(false, |st, rtok| match st {
true => None,
false => {
*st = matches!(
rtok,
Ok(Parsed::Object(XmloToken::Eoh(..)))
);
Some(rtok)
}
});
Lower::<XmloReader, xmlo::LowerState>::lower_with_context(
&mut iter,
state,
|air| {
let (_, asg) = Lower::<xmlo::LowerState, AirState>::lower_with_context(
Lower::<XmloReader, xmlo::LowerState>::lower_with_context(
&mut iter,
state,
|air| {
let (_, asg) = Lower::<xmlo::LowerState, AirState>::lower_with_context(
air,
asg,
|end| {
@ -220,11 +220,10 @@ fn load_xmlo<'a, P: AsRef<Path>, S: Escaper>(
},
)?;
Ok(asg)
},
)
},
)
Ok(asg)
},
)
})
},
)?;
@ -278,7 +277,7 @@ fn output_xmle<'a, X: XmleSections<'a>, S: Escaper>(
pub enum TameldError {
Io(io::Error),
SortError(SortError),
XirError(XirError),
XirParseError(ParseError<UnknownToken, XirError>),
XirfParseError(ParseError<XirToken, XirfError>),
XmloParseError(ParseError<XirfToken, XmloError>),
XmloLowerError(ParseError<XmloToken, XmloLowerError>),
@ -300,9 +299,9 @@ impl From<SortError> for TameldError {
}
}
impl From<XirError> for TameldError {
fn from(e: XirError) -> Self {
Self::XirError(e)
impl From<ParseError<UnknownToken, XirError>> for TameldError {
fn from(e: ParseError<UnknownToken, XirError>) -> Self {
Self::XirParseError(e)
}
}
@ -347,7 +346,7 @@ impl Display for TameldError {
match self {
Self::Io(e) => Display::fmt(e, f),
Self::SortError(e) => Display::fmt(e, f),
Self::XirError(e) => Display::fmt(e, f),
Self::XirParseError(e) => Display::fmt(e, f),
Self::XirfParseError(e) => Display::fmt(e, f),
Self::XmloParseError(e) => Display::fmt(e, f),
Self::XmloLowerError(e) => Display::fmt(e, f),
@ -378,7 +377,7 @@ impl Error for TameldError {
match self {
Self::Io(e) => Some(e),
Self::SortError(e) => Some(e),
Self::XirError(e) => Some(e),
Self::XirParseError(e) => Some(e),
Self::XirfParseError(e) => Some(e),
Self::XmloParseError(e) => Some(e),
Self::XmloLowerError(e) => Some(e),
@ -393,7 +392,7 @@ impl Error for TameldError {
impl Diagnostic for TameldError {
fn describe(&self) -> Vec<AnnotatedSpan> {
match self {
Self::XirError(e) => e.describe(),
Self::XirParseError(e) => e.describe(),
Self::XirfParseError(e) => e.describe(),
Self::XmloParseError(e) => e.describe(),
Self::XmloLowerError(e) => e.describe(),

View File

@ -27,7 +27,7 @@ mod parser;
mod state;
pub use error::ParseError;
pub use lower::{Lower, LowerIter};
pub use lower::{Lower, LowerIter, ParsedObject};
pub use parser::{Parsed, ParsedResult, Parser};
pub use state::{
context::{Context, Empty as EmptyContext, NoContext},
@ -35,9 +35,11 @@ pub use state::{
Transitionable,
};
use crate::span::Span;
use std::fmt::Debug;
use std::{error::Error, fmt::Display};
use crate::span::{Span, DUMMY_SPAN};
use std::{
error::Error,
fmt::{Debug, Display},
};
/// A single datum from a streaming IR with an associated [`Span`].
///
@ -54,6 +56,26 @@ impl<T: Token> From<T> for Span {
}
}
/// A type of [`Token`] that is not relevant.
///
/// This may be used when a [`Token`] type is required but only incidental,
/// such as for use with a [`ParseState`] in the context of a source of a
/// lowering operation.
#[derive(Debug, PartialEq)]
pub struct UnknownToken;
impl Token for UnknownToken {
fn span(&self) -> Span {
DUMMY_SPAN
}
}
impl Display for UnknownToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "<unknown token>")
}
}
/// An IR object produced by a lowering operation on one or more [`Token`]s.
///
/// Note that an [`Object`] may also be a [`Token`] if it will be in turn

View File

@ -19,9 +19,15 @@
//! IR lowering operation between [`Parser`]s.
use super::{ParseError, ParseState, Parsed, ParsedResult, Parser, Token};
use crate::iter::{TripIter, TrippableIterator};
use std::iter;
use super::{
NoContext, Object, ParseError, ParseState, Parsed, ParsedResult, Parser,
Token, TransitionResult, UnknownToken,
};
use crate::{
diagnose::Diagnostic,
iter::{TripIter, TrippableIterator},
};
use std::{fmt::Display, iter, marker::PhantomData};
#[cfg(doc)]
use super::TokenStream;
@ -181,3 +187,56 @@ where
}
}
}
/// Representation of a [`ParseState`] producing some type of [`Object`].
///
/// This is intended to be used not as a value,
/// but as a type for lowering operations.
/// This is useful when a parser does not make use of [`ParseState`] but
/// still wishes to participate in a lowering pipeline.
/// The type of [`Token`] will always be [`UnknownToken`],
/// so this is only useful at the head of such a pipeline.
#[derive(Debug)]
pub struct ParsedObject<O: Object, E: Diagnostic + PartialEq> {
_phantom: PhantomData<(O, E)>,
}
impl<O: Object, E: Diagnostic + PartialEq> PartialEq for ParsedObject<O, E> {
fn eq(&self, _other: &Self) -> bool {
true
}
}
impl<O: Object, E: Diagnostic + PartialEq> Eq for ParsedObject<O, E> {}
impl<O: Object, E: Diagnostic + PartialEq> Default for ParsedObject<O, E> {
fn default() -> Self {
Self {
_phantom: Default::default(),
}
}
}
impl<O: Object, E: Diagnostic + PartialEq> Display for ParsedObject<O, E> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "<generic data>")
}
}
impl<O: Object, E: Diagnostic + PartialEq> ParseState for ParsedObject<O, E> {
type Token = UnknownToken;
type Object = O;
type Error = E;
fn parse_token(
self,
_tok: Self::Token,
_: NoContext,
) -> TransitionResult<Self> {
unreachable!("ParsedObject must be used for type information only")
}
fn is_accepting(&self) -> bool {
unreachable!("ParsedObject must be used for type information only")
}
}

View File

@ -565,6 +565,8 @@ impl parse::Token for Token {
}
}
impl parse::Object for Token {}
#[cfg(test)]
mod test {
use super::*;

View File

@ -23,6 +23,7 @@
use super::{error::SpanlessError, DefaultEscaper, Error, Escaper, Token};
use crate::{
parse::{ParseError, Parsed, ParsedObject, ParsedResult},
span::Context,
sym::{st::raw::WS_EMPTY, GlobalSymbolInternBytes},
};
@ -510,7 +511,7 @@ where
B: BufRead,
S: Escaper,
{
type Item = Result<Token>;
type Item = ParsedResult<ParsedObject<Token, Error>>;
/// Produce the next XIR [`Token`] from the input.
///
@ -519,8 +520,12 @@ where
fn next(&mut self) -> Option<Self::Item> {
self.tokbuf
.pop_back()
.map(Result::Ok)
.or_else(|| self.refill_buf())
.map(|tok| Ok(Parsed::Object(tok)))
.or_else(|| {
self.refill_buf().map(|result| {
result.map(Parsed::Object).map_err(ParseError::StateError)
})
})
}
}

View File

@ -17,15 +17,19 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
use std::borrow::Cow;
use super::*;
use crate::parse::UnknownToken;
use crate::sym::GlobalSymbolIntern;
use crate::{
convert::ExpectInto,
parse::{
ParseError::StateError as PE,
Parsed::{self, Object as O},
},
span::DUMMY_CONTEXT as DC,
xir::{Error, Token},
};
use std::borrow::Cow;
/// These tests use [`quick_xml`] directly,
/// rather than mocking it,
@ -44,6 +48,8 @@ use crate::{
/// redundant checks.
type Sut<'a, B, S> = XmlXirReader<'a, B, S>;
type SutResultCollect =
result::Result<Vec<Parsed<Token>>, ParseError<UnknownToken, Error>>;
#[derive(Debug, Default)]
struct MockEscaper {}
@ -99,8 +105,8 @@ fn empty_node_without_prefix_or_attributes() {
assert_eq!(
Ok(vec![
Token::Open("empty-node".unwrap_into(), a),
Token::Close(None, b),
O(Token::Open("empty-node".unwrap_into(), a)),
O(Token::Close(None, b)),
]),
sut.collect(),
);
@ -121,11 +127,11 @@ fn does_not_resolve_xmlns() {
assert_eq!(
Ok(vec![
Token::Open("no-ns".unwrap_into(), a),
O(Token::Open("no-ns".unwrap_into(), a)),
// Since we didn't parse @xmlns, it's still an attribute.
Token::AttrName("xmlns".unwrap_into(), b),
Token::AttrValue("noresolve:UNESC".intern(), c),
Token::Close(None, d),
O(Token::AttrName("xmlns".unwrap_into(), b)),
O(Token::AttrValue("noresolve:UNESC".intern(), c)),
O(Token::Close(None, d)),
]),
sut.collect(),
);
@ -147,10 +153,10 @@ fn empty_node_with_prefix_without_attributes_unresolved() {
// Should be the QName, _unresolved_.
assert_eq!(
Ok(vec![
Token::Open(("x", "empty-node").unwrap_into(), a),
Token::AttrName(("xmlns", "x").unwrap_into(), b),
Token::AttrValue("noresolve:UNESC".intern(), c),
Token::Close(None, d),
O(Token::Open(("x", "empty-node").unwrap_into(), a)),
O(Token::AttrName(("xmlns", "x").unwrap_into(), b)),
O(Token::AttrValue("noresolve:UNESC".intern(), c)),
O(Token::Close(None, d)),
]),
sut.collect(),
);
@ -167,12 +173,12 @@ fn prefix_with_empty_local_name_invalid_qname() {
let a = DC.span(1, 2);
let result = sut.collect::<Result<Vec<_>>>();
let result = sut.collect::<SutResultCollect>();
match result {
Ok(_) => panic!("expected failure"),
Err(given) => {
assert_eq!(Error::InvalidQName("x:".into(), a), given);
assert_eq!(PE(Error::InvalidQName("x:".into(), a)), given);
}
}
}
@ -196,14 +202,14 @@ fn multiple_attrs_ordered() {
assert_eq!(
Ok(vec![
Token::Open("ele".unwrap_into(), a),
Token::AttrName("foo".unwrap_into(), b),
Token::AttrValue("a:UNESC".intern(), c),
Token::AttrName("bar".unwrap_into(), d),
Token::AttrValue("b:UNESC".intern(), e),
Token::AttrName(("b", "baz").unwrap_into(), f),
Token::AttrValue("c:UNESC".intern(), g),
Token::Close(None, h),
O(Token::Open("ele".unwrap_into(), a)),
O(Token::AttrName("foo".unwrap_into(), b)),
O(Token::AttrValue("a:UNESC".intern(), c)),
O(Token::AttrName("bar".unwrap_into(), d)),
O(Token::AttrValue("b:UNESC".intern(), e)),
O(Token::AttrName(("b", "baz").unwrap_into(), f)),
O(Token::AttrValue("c:UNESC".intern(), g)),
O(Token::Close(None, h)),
]),
sut.collect(),
);
@ -226,10 +232,10 @@ fn empty_attr_value() {
assert_eq!(
Ok(vec![
Token::Open("ele".unwrap_into(), a),
Token::AttrName("empty".unwrap_into(), b),
Token::AttrValue(":UNESC".intern(), c),
Token::Close(None, d),
O(Token::Open("ele".unwrap_into(), a)),
O(Token::AttrName("empty".unwrap_into(), b)),
O(Token::AttrValue(":UNESC".intern(), c)),
O(Token::Close(None, d)),
]),
sut.collect(),
);
@ -254,12 +260,12 @@ fn permits_duplicate_attrs() {
assert_eq!(
Ok(vec![
Token::Open("dup".unwrap_into(), a),
Token::AttrName("attr".unwrap_into(), b),
Token::AttrValue("a:UNESC".intern(), c),
Token::AttrName("attr".unwrap_into(), d),
Token::AttrValue("b:UNESC".intern(), e),
Token::Close(None, f),
O(Token::Open("dup".unwrap_into(), a)),
O(Token::AttrName("attr".unwrap_into(), b)),
O(Token::AttrValue("a:UNESC".intern(), c)),
O(Token::AttrName("attr".unwrap_into(), d)),
O(Token::AttrValue("b:UNESC".intern(), e)),
O(Token::Close(None, f)),
]),
sut.collect(),
);
@ -282,10 +288,10 @@ fn child_node_self_closing() {
assert_eq!(
Ok(vec![
Token::Open("root".unwrap_into(), a),
Token::Open("child".unwrap_into(), b),
Token::Close(None, c),
Token::Close(Some("root".unwrap_into()), d),
O(Token::Open("root".unwrap_into(), a)),
O(Token::Open("child".unwrap_into(), b)),
O(Token::Close(None, c)),
O(Token::Close(Some("root".unwrap_into()), d)),
]),
sut.collect(),
);
@ -307,12 +313,12 @@ fn sibling_nodes() {
assert_eq!(
Ok(vec![
Token::Open("root".unwrap_into(), a),
Token::Open("child".unwrap_into(), b),
Token::Close(None, c),
Token::Open("child".unwrap_into(), d),
Token::Close(None, e),
Token::Close(Some("root".unwrap_into()), f),
O(Token::Open("root".unwrap_into(), a)),
O(Token::Open("child".unwrap_into(), b)),
O(Token::Close(None, c)),
O(Token::Open("child".unwrap_into(), d)),
O(Token::Close(None, e)),
O(Token::Close(Some("root".unwrap_into()), f)),
]),
sut.collect(),
);
@ -334,12 +340,12 @@ fn child_node_with_attrs() {
assert_eq!(
Ok(vec![
Token::Open("root".unwrap_into(), a),
Token::Open("child".unwrap_into(), b),
Token::AttrName("foo".unwrap_into(), c),
Token::AttrValue("bar:UNESC".intern(), d),
Token::Close(None, e),
Token::Close(Some("root".unwrap_into()), f),
O(Token::Open("root".unwrap_into(), a)),
O(Token::Open("child".unwrap_into(), b)),
O(Token::AttrName("foo".unwrap_into(), c)),
O(Token::AttrValue("bar:UNESC".intern(), d)),
O(Token::Close(None, e)),
O(Token::Close(Some("root".unwrap_into()), f)),
]),
sut.collect(),
);
@ -358,9 +364,9 @@ fn child_text() {
assert_eq!(
Ok(vec![
Token::Open("text".unwrap_into(), a),
Token::Text("foo bar:UNESC".into(), b),
Token::Close(Some("text".unwrap_into()), c),
O(Token::Open("text".unwrap_into(), a)),
O(Token::Text("foo bar:UNESC".into(), b)),
O(Token::Close(Some("text".unwrap_into()), c)),
]),
sut.collect(),
);
@ -382,12 +388,12 @@ fn mixed_child_content() {
assert_eq!(
Ok(vec![
Token::Open("text".unwrap_into(), a),
Token::Text("foo:UNESC".into(), b),
Token::Open("em".unwrap_into(), c),
Token::Text("bar:UNESC".into(), d),
Token::Close(Some("em".unwrap_into()), e),
Token::Close(Some("text".unwrap_into()), f),
O(Token::Open("text".unwrap_into(), a)),
O(Token::Text("foo:UNESC".into(), b)),
O(Token::Open("em".unwrap_into(), c)),
O(Token::Text("bar:UNESC".into(), d)),
O(Token::Close(Some("em".unwrap_into()), e)),
O(Token::Close(Some("text".unwrap_into()), f)),
]),
sut.collect(),
);
@ -422,14 +428,14 @@ fn mixed_child_content_with_newlines() {
assert_eq!(
Ok(vec![
Token::Text("\n:UNESC".into(), a),
Token::Open("root".unwrap_into(), b),
Token::Text("\n :UNESC".into(), c),
Token::Open("child".unwrap_into(), d),
Token::Close(None, e),
Token::Text("\n:UNESC".into(), f),
Token::Close(Some("root".unwrap_into()), g),
Token::Text("\n:UNESC".into(), h),
O(Token::Text("\n:UNESC".into(), a)),
O(Token::Open("root".unwrap_into(), b)),
O(Token::Text("\n :UNESC".into(), c)),
O(Token::Open("child".unwrap_into(), d)),
O(Token::Close(None, e)),
O(Token::Text("\n:UNESC".into(), f)),
O(Token::Close(Some("root".unwrap_into()), g)),
O(Token::Text("\n:UNESC".into(), h)),
]),
sut.collect(),
);
@ -449,10 +455,10 @@ fn comment() {
assert_eq!(
Ok(vec![
Token::Comment("root".into(), a),
Token::Open("root".unwrap_into(), b),
Token::Comment("<child>".into(), c),
Token::Close(Some("root".unwrap_into()), d),
O(Token::Comment("root".into(), a)),
O(Token::Open("root".unwrap_into(), b)),
O(Token::Comment("<child>".into(), c)),
O(Token::Close(Some("root".unwrap_into()), d)),
]),
sut.collect(),
);
@ -478,10 +484,10 @@ lines-->
assert_eq!(
Ok(vec![
Token::Open("mult".unwrap_into(), a),
Token::Comment("comment\non multiple\nlines".into(), b),
Token::Text("\n:UNESC".into(), c),
Token::Close(Some("mult".unwrap_into()), d),
O(Token::Open("mult".unwrap_into(), a)),
O(Token::Comment("comment\non multiple\nlines".into(), b)),
O(Token::Text("\n:UNESC".into(), c)),
O(Token::Close(Some("mult".unwrap_into()), d)),
]),
sut.collect(),
);
@ -502,12 +508,12 @@ fn permits_mismatched_tags() {
assert_eq!(
Ok(vec![
Token::Open("root".unwrap_into(), a),
Token::Open("child".unwrap_into(), b),
Token::Close(None, c),
Token::Close(Some("mismatch".unwrap_into()), d),
O(Token::Open("root".unwrap_into(), a)),
O(Token::Open("child".unwrap_into(), b)),
O(Token::Close(None, c)),
O(Token::Close(Some("mismatch".unwrap_into()), d)),
]),
sut.collect::<Result<Vec<_>>>(),
sut.collect(),
);
}
@ -519,11 +525,11 @@ fn node_name_invalid_utf8() {
// We report at the QName, not the start tag.
let span = DC.span(1, 1);
let result = sut.collect::<Result<Vec<_>>>();
let result = sut.collect::<SutResultCollect>();
match result {
Ok(_) => panic!("expected failure"),
Err(Error::InvalidUtf8(_, bytes, given_span)) => {
Err(PE(Error::InvalidUtf8(_, bytes, given_span))) => {
assert_eq!(bytes, &[INVALID_UTF8_BYTE]);
assert_eq!(span, given_span);
}
@ -541,11 +547,11 @@ fn attr_name_invalid_utf8() {
let span = DC.span(3, 1);
let result = sut.collect::<Result<Vec<_>>>();
let result = sut.collect::<SutResultCollect>();
match result {
Ok(_) => panic!("expected failure"),
Err(Error::InvalidUtf8(_, bytes, given_span)) => {
Err(PE(Error::InvalidUtf8(_, bytes, given_span))) => {
assert_eq!(bytes, &[INVALID_UTF8_BYTE]);
assert_eq!(span, given_span);
}
@ -563,11 +569,11 @@ fn attr_value_invalid_utf8() {
let span = DC.span(9, 4);
let result = sut.collect::<Result<Vec<_>>>();
let result = sut.collect::<SutResultCollect>();
match result {
Ok(_) => panic!("expected failure"),
Err(Error::InvalidUtf8(_, bytes, given_span)) => {
Err(PE(Error::InvalidUtf8(_, bytes, given_span))) => {
// Doesn't make it to the Escaper.
assert_eq!(bytes, &[b'b', b'a', b'd', INVALID_UTF8_BYTE]);
assert_eq!(span, given_span);
@ -590,8 +596,8 @@ fn valid_xml_decl_no_encoding() {
assert_eq!(
Ok(vec![
Token::Open("root".unwrap_into(), a),
Token::Close(None, b),
O(Token::Open("root".unwrap_into(), a)),
O(Token::Close(None, b)),
]),
sut.collect()
);
@ -622,8 +628,8 @@ fn invalid_xml_decl_version() {
let span = DC.span(15, 3);
assert_eq!(
Err(Error::UnsupportedXmlVersion("1.1".intern(), span)),
sut.collect::<Result<Vec<_>>>()
Err(PE(Error::UnsupportedXmlVersion("1.1".intern(), span))),
sut.collect::<SutResultCollect>()
);
}
@ -637,8 +643,8 @@ fn invalid_xml_encoding() {
let span = DC.span(30, 7);
assert_eq!(
Err(Error::UnsupportedEncoding("latin-1".intern(), span)),
sut.collect::<Result<Vec<_>>>()
Err(PE(Error::UnsupportedEncoding("latin-1".intern(), span))),
sut.collect::<SutResultCollect>()
);
}
@ -675,8 +681,8 @@ fn attr_single_no_value_no_eq() {
let span = DC.span(10, 0);
assert_eq!(
Err(Error::AttrValueExpected(None, span)),
sut.collect::<Result<Vec<_>>>()
Err(PE(Error::AttrValueExpected(None, span))),
sut.collect::<SutResultCollect>()
);
}
@ -690,8 +696,8 @@ fn attr_single_no_value_with_eq() {
let span = DC.span(11, 0);
assert_eq!(
Err(Error::AttrValueExpected(None, span)),
sut.collect::<Result<Vec<_>>>()
Err(PE(Error::AttrValueExpected(None, span))),
sut.collect::<SutResultCollect>()
);
}
@ -706,8 +712,8 @@ fn attr_multi_no_value_no_eq() {
assert_eq!(
// quick-xml doesn't provide the name
Err(Error::AttrValueExpected(None, span)),
sut.collect::<Result<Vec<_>>>()
Err(PE(Error::AttrValueExpected(None, span))),
sut.collect::<SutResultCollect>()
);
}
@ -723,8 +729,8 @@ fn attr_multi_no_value_with_eq() {
let span = DC.span(11, 0);
assert_eq!(
Err(Error::AttrValueUnquoted(None, span)),
sut.collect::<Result<Vec<_>>>()
Err(PE(Error::AttrValueUnquoted(None, span))),
sut.collect::<SutResultCollect>()
);
}
@ -739,8 +745,8 @@ fn attr_multiple_no_value_no_eq_then_good() {
assert_eq!(
// quick-xml doesn't provide the name
Err(Error::AttrValueExpected(None, span)),
sut.collect::<Result<Vec<_>>>()
Err(PE(Error::AttrValueExpected(None, span))),
sut.collect::<SutResultCollect>()
);
}
@ -754,8 +760,8 @@ fn empty_element_qname_no_attrs() {
let span = DC.span(1, 0);
assert_eq!(
Err(Error::InvalidQName("".intern(), span)),
sut.collect::<Result<Vec<_>>>()
Err(PE(Error::InvalidQName("".intern(), span))),
sut.collect::<SutResultCollect>()
);
}
@ -769,8 +775,8 @@ fn empty_element_qname_with_space_no_attrs() {
let span = DC.span(1, 0);
assert_eq!(
Err(Error::InvalidQName("".intern(), span)),
sut.collect::<Result<Vec<_>>>()
Err(PE(Error::InvalidQName("".intern(), span))),
sut.collect::<SutResultCollect>()
);
}
@ -783,8 +789,8 @@ fn empty_element_qname_with_attr() {
let span = DC.span(1, 9);
assert_eq!(
Err(Error::InvalidQName("foo=\"bar\"".intern(), span)),
sut.collect::<Result<Vec<_>>>()
Err(PE(Error::InvalidQName("foo=\"bar\"".intern(), span))),
sut.collect::<SutResultCollect>()
);
}
@ -798,7 +804,7 @@ fn empty_element_qname_with_space_with_attr() {
let span = DC.span(1, 0);
assert_eq!(
Err(Error::InvalidQName("".intern(), span)),
sut.collect::<Result<Vec<_>>>()
Err(PE(Error::InvalidQName("".intern(), span))),
sut.collect::<SutResultCollect>()
);
}