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-7145main
parent
f8c28655dc
commit
8d92667388
|
@ -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![],
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -565,6 +565,8 @@ impl parse::Token for Token {
|
|||
}
|
||||
}
|
||||
|
||||
impl parse::Object for Token {}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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>()
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue