Commit graph xmpp-rs/xso/src/lib.rs
Author SHA1 Message Date
Jonas Schäfer
ccdf27117d Fix docs build with current nightly
skip-changelog, we don't officially support nightly.

See-Also: https://github.com/rust-lang/rfcs/pull/3631
See-Also: https://github.com/rust-lang/rust/pull/138907
2025-10-08 13:03:39 +02:00
Jonas Schäfer
bdae845b14 xso: relax the feature = "std" requirement for xso::dynxso 2025-07-13 11:10:51 +00:00
Jonas Schäfer
7f5542e8d4 xso: add support for dynamically typed XSOs 2025-07-13 11:10:51 +00:00
Jonas Schäfer
126588b47d xso: allow FromXml implementations to provide matching hints
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.
2025-07-13 11:10:51 +00:00
Jonas Schäfer
d7b62488dc xso: add type-erased and dyn-compatible variant of AsXml
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.
2025-07-13 11:10:51 +00:00
Jonas Schäfer
8c7b503f12 xso: reorganise the code a little
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).
2025-05-06 07:42:57 +02:00
Jonas Schäfer
a222dc70de xso: provide nicer error messages on missing trait implementations 2025-05-02 17:16:59 +02:00
Jonas Schäfer
25d89e02ea xso: make convert_via_fromstr_and_display available
Useful for dependent crates which want an easy way to provide the
AsXmlText / FromXmlText traits.
2025-05-02 17:16:59 +02:00
Jonas Schäfer
341d49fecf xso: extend the documentation overall
Sprinkling it with examples, adding more words to make things
(hopefully) clearer, using a similar structure for different items etc.
etc.
2025-04-27 14:08:38 +02:00
Jonas Schäfer
cffb5e7e65 xso: make Context use a builder-like pattern
That way, we can (hopefully) add more fields in the future without
breaking stuff.

I don't yet know what such fields could be, though.
2025-04-27 14:08:38 +02:00
Jonas Schäfer
57972e9db0 xso: make from_bytes available without std
This also deuglifies some of the parsing code by avoiding the
interaction with the I/O errors emitted from rxml::Reader.
2025-04-27 14:08:38 +02:00
Jonas Schäfer
ebe53b8eab xso: remove #[doc(inline)] from TextCodec
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).
2025-04-27 14:08:38 +02:00
Jonas Schäfer
67e7e9da15 xso: improve documentation around text traits for third-party types
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.
2025-04-27 14:08:38 +02:00
Jonas Schäfer
c4de8725fc xso: deprecate try_from_element
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.
2025-04-27 13:44:06 +02:00
Jonas Schäfer
9fdb1564f6 xso: reject attempts to match the same XML attribute in different fields
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.
2025-04-27 11:18:50 +02:00
Jonas Schäfer
d9a21dd8c9 Track xml:lang throughout parsing 2025-04-22 17:55:44 +02:00
Maxime “pep” Buquet
b89d3ab04d xso: Add PrintRawXml helper struct with Display
Add a helper struct to be able to display Raw Xml, useful for debug
logs.

Signed-off-by: Maxime “pep” Buquet <pep@bouah.net>
2025-02-12 20:17:41 +01:00
Emmanuel Gil Peyrot
356ad0d46e xso: Fix all failing clippy tests
They are all sensible to me.

skip-changelog: Internal changes.
2025-02-12 19:11:32 +00:00
Jonas Schäfer
beae4ae66b xso: fix no_std support
This reverts the Revert in 6ec275d3 which had to be done in order to
un-break usage of xso in std crates.
2025-01-26 15:07:17 +00:00
Jonas Schäfer
727e57b756 Implement #[xml(flag)] meta 2025-01-21 19:12:43 +01:00
Jonas Schäfer
b8af0d8fa2 xmpp_parsers: --features disable-validation
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.
2024-12-20 14:50:14 +01:00
Jonas Schäfer
58698f633f xso: only take reference in transform
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.
2024-12-20 12:44:43 +01:00
c8d3c068e0 xso: Replace std::io calls with use std::io 2024-12-19 20:51:57 +01:00
1c1b960265 xso: Add std feature ; default-features compiles in no-std 2024-12-19 20:38:28 +01:00
Jonas Schäfer
7074344834 xso: correctly handle I/O errors during start event in from_reader
Without this, it'd panic, which is "not ideal", as they say.
2024-12-18 14:47:08 +00:00
Jonas Schäfer
fa039c588b xso: improve wording in AsXmlText and AsOptionalXmlText 2024-12-16 19:04:23 +01:00
Jonas Schäfer
66233b0150 xso: add support for ignoring unknown children 2024-10-26 17:37:32 +00:00
Jonas Schäfer
290460ba9d xso: add support for ignoring unknown attributes 2024-10-26 17:37:32 +00:00
Jonas Schäfer
74c81b6a37 xso: add from_reader 2024-10-03 12:57:32 +02:00
Jonas Schäfer
efc859abc0 xmlstream: re-introduce syntax-highlit logging of XML stream I/O 2024-09-01 10:02:36 +02:00
Jonas Schäfer
f77c21f0fc Update to rxml 0.12.0 2024-08-12 16:16:32 +02:00
Jonas Schäfer
6b4886857e xso: offer is_xml_whitespace function 2024-08-12 12:32:12 +02:00
Jonas Schäfer
f1ab857c6e xso: move helper iterators and builders into separate module
This declutters the main `xso` namespace. In addition, if (when) we
introduce more complex generic implementations, we might want to have
tests for these, and those can then live there, too, without making the
main `lib.rs` file gigantic (or moving the tests too far away from the
tested code).
2024-08-11 07:45:05 +02:00
2103ef0191 Remove manual doc_cfg feature because we have doc_auto_cfg 2024-08-05 11:14:41 +02:00
fa99c09585 Indicate which feature flag for each module/type 2024-08-05 11:14:41 +02:00
Jonas Schäfer
c7c180feb6 xso: implement support for defaulting extracts 2024-08-04 16:07:14 +02:00
Emmanuel Gil Peyrot
f318dd460d xso: Use core instead of std wherever possible 2024-08-04 12:41:17 +00:00
Jonas Schäfer
cd9f2033f3 xso: add support for boxed children
This allows building recursive tree structures.
2024-07-27 08:24:25 +02:00
Jonas Schäfer
01336802b4 xso-proc: add support for optional children 2024-07-27 08:24:25 +02:00
Jonas Schäfer
c40023a65e xso: add feature flag marker to derive macros 2024-07-26 17:11:48 +02:00
Jonas Schäfer
204c82e6b0 xso: add more doc comments throughout 2024-07-25 22:22:55 +02:00
Emmanuel Gil Peyrot
6e1f24c385 xso: Apply clippy’s suggestions 2024-07-25 07:35:19 +00:00
Jonas Schäfer
7bc7e7a684 xso: remove remnants of IntoXml 2024-07-24 16:05:06 +02:00
Jonas Schäfer
ccf38cdf9b Port everything over to AsXml 2024-07-24 16:05:06 +02:00
Jonas Schäfer
4910b01244 xso: add text conversion traits for AsXml 2024-07-24 16:05:06 +02:00
Jonas Schäfer
d29b89d307 xso: introduce AsXml trait
This will soon replace the IntoXml trait. The idea here is that we
don't generally need to take ownership of values which are going to
be transformed into XML: most of the time, the XML text is created
by building a string from some more specific type, such as an
integer or an enum. Requiring to clone an entire structure for this
purpose is wasteful.

In other cases, we actually could reference data right from the structs
we are converting to XML. In those cases, assuming that an iterator
always generates owned data would be incorrect, too.

Hence, we introduce a new `Item` type which closely mirrors the
`rxml::Item` type, but where the constituents are `Cow`. In the upcoming
changes, we are going to work toward replacing all uses of `IntoXml`
with `AsXml`, as well as modifying the macros accordingly.
2024-07-24 16:05:06 +02:00
Emmanuel Gil Peyrot
b18385cfff xso: Fix all clippy warnings 2024-07-03 16:28:11 +02:00
Jonas Schäfer
c83ff286e0 xso-proc: add support for text codecs
Text codecs allow to customize the conversion of data from/to XML,
in particular in two scenarios:

1. When the type for which the behaviour is to be defined comes from a
   foreign crate, preventing the implementation of
   FromXmlText/IntoXmlText.

2. When there is not one obvious, or more than one sensible, way to
   convert a value to XML text and back.
2024-07-02 06:56:30 +02:00
Jonas Schäfer
2fb9fc6959 xso: add more doc_cfg labels 2024-06-30 13:05:37 +02:00
Jonas Schäfer
1f679c3af7 xso: add traits for XML text <-> value conversion
The traits have undergone a couple iterations and this is what we end up
with. The core issue which makes this entire thing ugly is the
Orphan Rule, preventing some trait implementations relating to types
which haven't been defined in this crate.

In an ideal world, we would implement FromXmlText and IntoXmlText for
all types implementing FromStr and/or fmt::Display.

This comes with two severe issues:

1. Downstream crates cannot chose to have different
   parsing/serialisation behaviour for "normal" text vs. xml.

2. We ourselves cannot define a behaviour for `Option<T>`. `Option<T>`
   does not implement `FromStr` (nor `Display`), but the standard
   library *could* do that at some point, and thus Rust doesn't let us
   implement e.g. `FromXmlText for Option<T> where T: FromXmlText`,
   if we also implement it on `T: FromStr`.

The second one hurts particularly once we get to optional attributes:
For these, we need to "detect" that the type is in fact `Option<T>`,
because we then need to invoke `FromXmlText` on `T` instead of
`Option<T>`. Unfortunately, we cannot do that: macros operate on token
streams and we have no type information available.

We can of course match on the name `Option`, but that breaks down when
users re-import `Option` under a different name. Even just enumerating
all the possible correct ways of using `Option` from the standard
library (there are more than three) would be a nuisance at best.

Hence, we need *another* trait or at least a specialized implementation
of `FromXmlText for Option<T>`, and we cannot do that if we blanket-impl
`FromXmlText` on `T: FromStr`.

That makes the traits what they are, and introduces the requirement that
we know about any upstream crate which anyone might want to parse from
or to XML. This sucks a lot, but that's the state of the world. We are
late to the party, and we cannot expect everyone to do the same they
have done for `serde` (many crates have a `feature = "serde"` which then
provides Serialize/Deserialize trait impls for their types).
2024-06-30 13:01:36 +02:00