transformable/impls/
string.rs1use super::*;
2
3#[cfg(not(feature = "std"))]
4use ::std::{boxed::Box, string::String};
5
6use ::std::sync::Arc;
7
8use core::borrow::Borrow;
9
10#[derive(Debug, thiserror::Error)]
12pub enum StringTransformError {
13 #[error(
15 "buffer is too small, use `Transformable::encoded_len` to pre-allocate a buffer with enough space"
16 )]
17 EncodeBufferTooSmall,
18 #[error("not enough bytes to decode")]
20 NotEnoughBytes,
21 #[error(transparent)]
23 Utf8Error(#[from] core::str::Utf8Error),
24}
25
26macro_rules! impl_string {
27 ($ty: ty => $test_fn:ident($init: expr)) => {
28 impl Transformable for $ty {
29 type Error = StringTransformError;
30
31 fn encode(&self, dst: &mut [u8]) -> Result<usize, Self::Error> {
32 let src: &str = self.borrow();
33 encode_bytes(src.as_bytes(), dst).map_err(|_| Self::Error::EncodeBufferTooSmall)
34 }
35
36 #[cfg(feature = "std")]
37 fn encode_to_writer<W: std::io::Write>(&self, dst: &mut W) -> std::io::Result<usize> {
38 let src: &str = self.borrow();
39 encode_bytes_to(src.as_bytes(), dst)
40 }
41
42 #[cfg(feature = "async")]
43 async fn encode_to_async_writer<W: futures_util::io::AsyncWrite + Send + Unpin>(
44 &self,
45 dst: &mut W,
46 ) -> std::io::Result<usize> {
47 let src: &str = self.borrow();
48 encode_bytes_to_async(src.as_bytes(), dst).await
49 }
50
51 fn encoded_len(&self) -> usize {
52 let src: &str = self.borrow();
53 encoded_bytes_len(src.as_bytes())
54 }
55
56 fn decode(src: &[u8]) -> Result<(usize, Self), Self::Error>
57 where
58 Self: Sized,
59 {
60 decode_bytes(src)
61 .map_err(|_| Self::Error::NotEnoughBytes)
62 .and_then(|(readed, bytes)| {
63 core::str::from_utf8(bytes.as_ref())
64 .map(|s| (readed, Self::from(s)))
65 .map_err(Into::into)
66 })
67 }
68
69 #[cfg(feature = "std")]
70 fn decode_from_reader<R: std::io::Read>(src: &mut R) -> std::io::Result<(usize, Self)>
71 where
72 Self: Sized,
73 {
74 decode_bytes_from(src).and_then(|(readed, bytes)| {
75 core::str::from_utf8(bytes.as_ref())
76 .map(|s| (readed, Self::from(s)))
77 .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))
78 })
79 }
80
81 #[cfg(feature = "async")]
82 async fn decode_from_async_reader<R: futures_util::io::AsyncRead + Send + Unpin>(
83 src: &mut R,
84 ) -> std::io::Result<(usize, Self)>
85 where
86 Self: Sized,
87 {
88 decode_bytes_from_async(src)
89 .await
90 .and_then(|(readed, bytes)| {
91 core::str::from_utf8(bytes.as_ref())
92 .map(|s| (readed, Self::from(s)))
93 .map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))
94 })
95 }
96 }
97
98 test_transformable!($ty => $test_fn($init));
99 };
100}
101
102impl_string!(String => test_string_transformable(String::from("hello world")));
103
104#[cfg(feature = "smol_str03")]
105impl_string!(smol_str03::SmolStr => test_smol_str03_transformable(smol_str03::SmolStr::from("hello world")));
106
107#[cfg(feature = "smol_str02")]
108impl_string!(smol_str02::SmolStr => test_smol_str02_transformable(smol_str02::SmolStr::from("hello world")));
109
110impl_string!(Box<str> => test_box_str_transformable(Box::from("hello world")));
111
112impl_string!(Arc<str> => test_arc_str_transformable(Arc::from("hello world")));
113
114#[cfg(feature = "triomphe01")]
115use ::triomphe01::Arc as TriompheArc;
116
117#[cfg(feature = "triomphe01")]
118impl_string!(TriompheArc<str> => test_triomphe_arc_u8_transformable(TriompheArc::from("hello world")));