Skip to content

Commit

Permalink
Added serde feature (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
imbrem authored Apr 13, 2023
1 parent 8f93793 commit a7c5ced
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 1 deletion.
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,8 @@ license = "MIT OR Apache-2.0"
categories = ["data-structures", "no-std"]
keywords = ["string", "vector", "sso", "cow"]

[dependencies]
serde = { version = "1.0", optional = true, default-features = false }

[target.'cfg(loom)'.dependencies]
loom = { version = "0.5", optional = true }
loom = { version = "0.5", optional = true }
52 changes: 52 additions & 0 deletions src/string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,3 +438,55 @@ impl From<&EcoString> for String {
const fn exceeded_inline_capacity() -> ! {
panic!("exceeded inline capacity");
}

#[cfg(feature = "serde")]
mod serde {
use crate::EcoString;
use core::fmt;
use serde::de::{Deserializer, Error, Unexpected, Visitor};

impl serde::Serialize for EcoString {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.as_str().serialize(serializer)
}
}

impl<'de> serde::Deserialize<'de> for EcoString {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct EcoStringVisitor;

impl<'a> Visitor<'a> for EcoStringVisitor {
type Value = EcoString;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a string")
}

fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: Error,
{
Ok(EcoString::from(v))
}

fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
where
E: Error,
{
if let Ok(utf8) = core::str::from_utf8(v) {
return Ok(EcoString::from(utf8));
}
Err(Error::invalid_value(Unexpected::Bytes(v), &self))
}
}

deserializer.deserialize_str(EcoStringVisitor)
}
}
}
47 changes: 47 additions & 0 deletions src/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1172,3 +1172,50 @@ fn ref_count_overflow<T>(ptr: NonNull<u8>, len: usize) -> ! {
fn out_of_bounds(index: usize, len: usize) -> ! {
panic!("index is out bounds (index: {index}, len: {len})");
}

#[cfg(feature = "serde")]
mod serde {
use crate::EcoVec;
use core::{fmt, marker::PhantomData};
use serde::de::{Deserializer, Visitor};

impl<T: serde::Serialize> serde::Serialize for EcoVec<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
(&self[..]).serialize(serializer)
}
}

struct EcoVecVisitor<T>(PhantomData<T>);

impl<'a, T: serde::Deserialize<'a> + Clone> Visitor<'a> for EcoVecVisitor<T> {
type Value = EcoVec<T>;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a sequence")
}

fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'a>,
{
let len = seq.size_hint().unwrap_or(0);
let mut values = EcoVec::with_capacity(len);
while let Some(value) = seq.next_element()? {
values.push(value)
}
Ok(values)
}
}

impl<'de, T: serde::Deserialize<'de> + Clone> serde::Deserialize<'de> for EcoVec<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_seq(EcoVecVisitor(PhantomData))
}
}
}

0 comments on commit a7c5ced

Please sign in to comment.