This doesn't fix all of the clippy warnings in these crates. There are
decisions that needs to be made in there that I'm not willing to make.
Signed-off-by: pep <pep@bouah.net>
- Move Element.attributes to `AttrMap`, slowly using rxml's features and
unrolling our own.
- Add Element::attr_ns that requires the attribute namespace.
Element:attr defaults to rxml::Namespace::none() but the interface
changes nonetheless for a &NcNameStr. Similar changes on
`ElementBuilder` methods.
- Remove iterator structs for attributes, return a ref on the AttrMap
directly as we don't need to keep attributes' internals hidden
anymore.
- Enable rxml's `macros` feature within tests to access the `xml_ncname`
macro.
Signed-off-by: pep <pep@bouah.net>
That way, callers can put multiple candidate implementations in, for
example, a sorted vector and more efficiently select candidates to try
when looking at a new element.
That way, we don't need to know the specific type of iterator or even
iteree anymore. This can turn out useful when working with `Box<dyn _>`,
that is, in contexts where we don't know the (possible or actual) types
at compile time.
By removing the implicit `Sized` bound, they can be used with `dyn _`.
The `Sized` bound is unnecessary for a boxed value, so it is a
superfluous restriction. Also, the use with `dyn _` may turn out useful
in the future when we want to allow type-erased XSOs.
The main lib.rs is getting a bit cluttered, so I'm trying to bring some
order into the chaos by moving some things into other modules.
skip-changelog, because there are no user-facing changes (names which
have been moved are doc(inline)'d and pub use'd in the main lib, and
other things (trait implementations) aren't addressable by users).
This gives us all the goodies of `default`, `type_` and `codec` without
having to duplicate lots of code (and I think the `match`-iness of the
new macro code is still within limits).
However, we still keep them as separate `#[xml(..)]` attributes, because
their semantics are very different and it is sensible to make them stand
out.
skip-changelog, because `#[xml(lang)]` was introduced in this version.
Using `#[doc(inline)]` there makes it appear in two places in the
documentation, which may be confusing (as it's not fully obvious that
both places are in fact the same trait).
The previous wording was a bit ominous in places ("Because of the
unfortunate situation as described in `FromXmlText`"). This should be
clearer and provides hopefully clearer instructions.
It is not necessary anymore, because we switched from `IntoXml` to
`AsXml`, allowing `transform` to work with a reference instead of
consuming its input.
Before that, `try_from_element` was the only way to fallibly attempt to
parse something from `Element` without having to clone the entire DOM.
This was a bit tricky to build, because it is possible to have an
indirection through a `static` there. Thanks to Rust's extensive
const-fn capabilities, though, it's in fact possible to cover all cases.
We still do two different checks to improve user experience. If we can,
from within the proc macro, determine that two fields refer to the same
XML attribute (because their namespace/name values use the same Rust
tokens), then we reject the fields with a clear error message pointing
at both fields.
In the other case, when there's e.g. `#[xml(lang)]` and
`#[xml(attribute(namespace = rxml::XMLNS_XML, name = "lang"))]`, the
macro cannot be sure that XMLNS_XML is in fact the XML namespace. For
that case, we generate code which is evaluated at compile time (and
has no runtime impact) which panics if the namespace and name of two
attribute-matching fields is the same.
The error message will be less clear (because it contains extra,
unchangeable wording like "evaluation of constant value failed" and "the
evaluated program panicked at", which may be a bit confusing) than the
message generated by the macros themselves, but it's a price we have to
pay unfortunately.
Note that this check may seem cosmetic and purely for better user
experience, but it is in fact needed to avoid generating not-well-formed
and/or not-namespace-well-formed XML: As `AsXml` generates `xso::Item`,
where each attribute is emitted separated (and not aggregated in a
map structure), a naive (and efficient) implementation of a writer might
not double-check that no duplicate attributes are generated.
This allows exactly one arbitrary payload in any element, and is handled
after every other element with a more specific matcher has been parsed.
Both the #[xml(element(n = 1))] meta and its shortcut #[xml(element)]
are allowed and treated the exact same way.
The `xso::text::Base64` struct remains as a shorthand (because frankly,
I find the const names in the base64 crate very unwieldly), but you can
now use any of the base64 engines as codec.
This reverts commit 4e5f0bc961.
Unfortunately, in std contexts, the `alloc` crate is not imported. That
means we cannot rely on it being accessible and it in fact breaks builds
of crates which are not `no_std`.
Fixes#155.
It was broken in multiple ways:
- xso did not honour it: unknown children and attributes would cause a
parse error even with `--features disable-validation` set on parsers.
For this, we introduce a new feature flag on xso, `non-pedantic`,
which defaults unknown children and attributes to discard instead of
fail.
Note that individual XSOs can still choose to be always pedantic or
always lenient by explicitly declaring the intent via the
`on_unknown_child` and `on_unknown_attribute` metas.
- Many tests in `xmpp_parsers` were broken with `--features
disable-validation`. They now all pass while *still* being rn with
`disable-validation` set: In that case, they test that parsing in fact
succeeds.
This avoids the need for an expensive clone. Since we switched to AsXml
instead of IntoXml, we don't necessarily have to clone the data when
building new elements, only when it's absolutely necessary. The clones
then happen implicitly in the ItemToEvent iterator used internally.
This mostly fixes#86, with the caveat that there's no absolutely cheap
test: On success, the entire element will be copied, while on failure,
you learn about it rather quickly.