cow capped string
This commit is contained in:
1 parent
876d92c3e8
commit
afa8e15ace
1 file changed
+65
-2
@@ -3,6 +3,68 @@
|
|||||||
|
|
||||||
use core::{str, ops::Deref, borrow::Borrow, fmt};
|
use core::{str, ops::Deref, borrow::Borrow, fmt};
|
||||||
|
|
||||||
|
/// TODO: documentation
|
||||||
|
pub enum CowCappedString<'a, const N: usize> {
|
||||||
|
/// TODO: documentation
|
||||||
|
Borrowed(&'a str),
|
||||||
|
/// TODO: documentation
|
||||||
|
Owned(CappedString<N>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl<'de, const N: usize> serde::Deserialize<'de> for CowCappedString<'de, N> {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where
|
||||||
|
D: serde::Deserializer<'de>
|
||||||
|
{
|
||||||
|
deserializer.deserialize_str(CowCappedStringVisitor::<N>)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
struct CowCappedStringVisitor<const N: usize>;
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
impl<'de, const N: usize> serde::de::Visitor<'de> for CowCappedStringVisitor<N> {
|
||||||
|
type Value = CowCappedString<'de, N>;
|
||||||
|
|
||||||
|
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, "a borrowed string or a string up to {} bytes long", N)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
CappedStringVisitor::<N>.visit_str(v)
|
||||||
|
.map(CowCappedString::Owned)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
CappedStringVisitor::<N>.visit_bytes(v)
|
||||||
|
.map(CowCappedString::Owned)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_str<E>(self, v: &'de str) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
Ok(CowCappedString::Borrowed(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
|
||||||
|
where
|
||||||
|
E: serde::de::Error,
|
||||||
|
{
|
||||||
|
str::from_utf8(v)
|
||||||
|
.map_err(|_| E::invalid_value(serde::de::Unexpected::Bytes(v), &self))
|
||||||
|
.and_then(|v| self.visit_borrowed_str(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A string type which stores up to `N` bytes of string data inline.
|
/// A string type which stores up to `N` bytes of string data inline.
|
||||||
pub struct CappedString<const N: usize> {
|
pub struct CappedString<const N: usize> {
|
||||||
/// The string data. It is an invariant that the first `len` bytes must be valid UTF-8.
|
/// The string data. It is an invariant that the first `len` bytes must be valid UTF-8.
|
||||||
@@ -134,8 +196,10 @@ impl<'de, const N: usize> serde::Deserialize<'de> for CappedString<N> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
struct CappedStringVisitor<const N: usize>;
|
struct CappedStringVisitor<const N: usize>;
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
impl<'de, const N: usize> serde::de::Visitor<'de> for CappedStringVisitor<N> {
|
impl<'de, const N: usize> serde::de::Visitor<'de> for CappedStringVisitor<N> {
|
||||||
type Value = CappedString<N>;
|
type Value = CappedString<N>;
|
||||||
|
|
||||||
@@ -157,8 +221,7 @@ impl<'de, const N: usize> serde::de::Visitor<'de> for CappedStringVisitor<N> {
|
|||||||
{
|
{
|
||||||
str::from_utf8(v)
|
str::from_utf8(v)
|
||||||
.map_err(|_| E::invalid_value(serde::de::Unexpected::Bytes(v), &self))
|
.map_err(|_| E::invalid_value(serde::de::Unexpected::Bytes(v), &self))
|
||||||
.and_then(|v| CappedString::from_str(v)
|
.and_then(|v| self.visit_str(v))
|
||||||
.ok_or_else(|| E::invalid_length(v.len(), &self)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user