xso: implement TextCodec<_> on all T: base64::engine::Engine
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 commit is contained in:
parent
95773505e4
commit
69787569c9
2 changed files with 53 additions and 8 deletions
|
|
@ -27,6 +27,8 @@ Version NEXT:
|
|||
jid::DomainPart, and jid::ResourcePart (!485)
|
||||
- Support for optional child elements, the presence of which are
|
||||
translated into a boolean (`#[xml(flag)]`).
|
||||
- Generic TextCodec implementation for all base64 engines provided by
|
||||
the base64 crate (if the `base64` feature is enabled).
|
||||
|
||||
Version 0.1.2:
|
||||
2024-07-26 Jonas Schäfer <jonas@zombofant.net>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use alloc::{
|
|||
use crate::{error::Error, AsXmlText, FromXmlText};
|
||||
|
||||
#[cfg(feature = "base64")]
|
||||
use base64::engine::{general_purpose::STANDARD as StandardBase64Engine, Engine as _};
|
||||
use base64::engine::general_purpose::STANDARD as StandardBase64Engine;
|
||||
|
||||
macro_rules! convert_via_fromstr_and_display {
|
||||
($($(#[cfg $cfg:tt])?$t:ty,)+) => {
|
||||
|
|
@ -291,38 +291,47 @@ impl TextFilter for StripWhitespace {
|
|||
}
|
||||
}
|
||||
|
||||
/// Text codec transforming text to binary using standard base64.
|
||||
/// Text codec transforming text to binary using standard `base64`.
|
||||
///
|
||||
/// The `Filter` type argument can be used to employ additional preprocessing
|
||||
/// of incoming text data. Most interestingly, passing [`StripWhitespace`]
|
||||
/// will make the implementation ignore any whitespace within the text.
|
||||
///
|
||||
/// `Base64` uses the [`base64::engine::general_purpose::STANDARD`] engine.
|
||||
/// [`TextCodec`] is also automatically implemented for any value which
|
||||
/// implements [`base64::engine::Engine`], allowing you to choose different
|
||||
/// alphabets easily.
|
||||
#[cfg(feature = "base64")]
|
||||
pub struct Base64;
|
||||
|
||||
#[cfg(feature = "base64")]
|
||||
impl TextCodec<Vec<u8>> for Base64 {
|
||||
fn decode(&self, s: String) -> Result<Vec<u8>, Error> {
|
||||
StandardBase64Engine
|
||||
.decode(s.as_bytes())
|
||||
base64::engine::Engine::decode(&StandardBase64Engine, s.as_bytes())
|
||||
.map_err(Error::text_parse_error)
|
||||
}
|
||||
|
||||
fn encode<'x>(&self, value: &'x Vec<u8>) -> Result<Option<Cow<'x, str>>, Error> {
|
||||
Ok(Some(Cow::Owned(StandardBase64Engine.encode(&value))))
|
||||
Ok(Some(Cow::Owned(base64::engine::Engine::encode(
|
||||
&StandardBase64Engine,
|
||||
&value,
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "base64")]
|
||||
impl<'x> TextCodec<Cow<'x, [u8]>> for Base64 {
|
||||
fn decode(&self, s: String) -> Result<Cow<'x, [u8]>, Error> {
|
||||
StandardBase64Engine
|
||||
.decode(s.as_bytes())
|
||||
base64::engine::Engine::decode(&StandardBase64Engine, s.as_bytes())
|
||||
.map_err(Error::text_parse_error)
|
||||
.map(Cow::Owned)
|
||||
}
|
||||
|
||||
fn encode<'a>(&self, value: &'a Cow<'x, [u8]>) -> Result<Option<Cow<'a, str>>, Error> {
|
||||
Ok(Some(Cow::Owned(StandardBase64Engine.encode(&value))))
|
||||
Ok(Some(Cow::Owned(base64::engine::Engine::encode(
|
||||
&StandardBase64Engine,
|
||||
&value,
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -347,6 +356,40 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "base64")]
|
||||
impl<T: base64::engine::Engine> TextCodec<Vec<u8>> for T {
|
||||
fn decode(&self, s: String) -> Result<Vec<u8>, Error> {
|
||||
base64::engine::Engine::decode(self, s.as_bytes()).map_err(Error::text_parse_error)
|
||||
}
|
||||
|
||||
fn encode<'x>(&self, value: &'x Vec<u8>) -> Result<Option<Cow<'x, str>>, Error> {
|
||||
Ok(Some(Cow::Owned(base64::engine::Engine::encode(
|
||||
self, &value,
|
||||
))))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "base64")]
|
||||
impl<'a, T: base64::engine::Engine, U> TextCodec<Option<U>> for T
|
||||
where
|
||||
T: TextCodec<U>,
|
||||
{
|
||||
fn decode(&self, s: String) -> Result<Option<U>, Error> {
|
||||
if s.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
Ok(Some(TextCodec::decode(self, s)?))
|
||||
}
|
||||
|
||||
fn encode<'x>(&self, decoded: &'x Option<U>) -> Result<Option<Cow<'x, str>>, Error> {
|
||||
decoded
|
||||
.as_ref()
|
||||
.map(|x| TextCodec::encode(self, x))
|
||||
.transpose()
|
||||
.map(Option::flatten)
|
||||
}
|
||||
}
|
||||
|
||||
/// Text codec transforming text to binary using hexadecimal nibbles.
|
||||
///
|
||||
/// The length must be known at compile-time.
|
||||
|
|
|
|||
Loading…
Reference in a new issue