diff --git a/sehn/Cargo.toml b/sehn/Cargo.toml index 28469ef..2de5a1d 100644 --- a/sehn/Cargo.toml +++ b/sehn/Cargo.toml @@ -5,4 +5,8 @@ authors = ["James Dyson "] edition = "2018" [dependencies] -itoa = "0.4" \ No newline at end of file +itoa = "0.4" + +[features] +default = ["std"] +std = [] diff --git a/sehn/examples/basic.rs b/sehn/examples/basic.rs index b68389f..83ffa46 100644 --- a/sehn/examples/basic.rs +++ b/sehn/examples/basic.rs @@ -4,18 +4,18 @@ use std::collections::BTreeMap; use sehn::*; -fn print_and_clear(s: BaseSerializer) { +fn print_and_clear(s: BaseSerializer>>) { let out = s.into_inner(); - println!("{}", out.as_str().unwrap()); + println!("{}", out.as_str()); out.clear(); } fn main() { - let mut w = StringWriter::new(); + let mut w = GenericWriter::from(Vec::new()); /////////////////////////////////////////////////////////////////////////// - let mut s = default_base_serializer(&mut w); + let mut s = BaseSerializer::new(&mut w); let mut obj = BTreeMap::new(); obj.insert("hello", Tag::new("one", vec![1])); @@ -26,7 +26,7 @@ fn main() { /////////////////////////////////////////////////////////////////////////// - let mut s = default_base_serializer(&mut w); + let mut s = BaseSerializer::new(&mut w); let lines = vec![ "hello", diff --git a/sehn/examples/no-std.rs b/sehn/examples/no-std.rs new file mode 100644 index 0000000..3bef7af --- /dev/null +++ b/sehn/examples/no-std.rs @@ -0,0 +1,13 @@ +extern crate sehn; + +use sehn::*; + +fn main() { + let mut buf = [0u8; 2048]; + let mut w: GenericWriter<_> = SliceBuffer::new(&mut buf).into(); + let mut s = BaseSerializer::new(&mut w); + + s.serialize_unit("hello", 1.0).unwrap(); + + println!("{}", w.as_str()); +} \ No newline at end of file diff --git a/sehn/src/lib.rs b/sehn/src/lib.rs index 3ffd664..d7a42cb 100644 --- a/sehn/src/lib.rs +++ b/sehn/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(not(feature = "std"), no_std)] + pub mod se; pub mod de; pub mod value; diff --git a/sehn/src/se/base/error.rs b/sehn/src/se/base/error.rs new file mode 100644 index 0000000..7005c02 --- /dev/null +++ b/sehn/src/se/base/error.rs @@ -0,0 +1,33 @@ +use core::fmt; + +pub trait WriteError: fmt::Debug {} + +impl WriteError for () {} + +pub enum SerializerError + where WE: WriteError +{ + Write(WE), + /// A unexpected error (should never get this). + Unexpected(&'static str) +} + +impl From for SerializerError + where WE: WriteError +{ + fn from(err: WE) -> Self { + SerializerError::Write(err) + } +} + +impl fmt::Debug for SerializerError + where WE: WriteError +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + use SerializerError::*; + match self { + Write(ref err) => write!(f, "write error: {:?}", err), + Unexpected(ref err) => write!(f, "unexpected error: {}", err) + } + } +} \ No newline at end of file diff --git a/sehn/src/se/base/mod.rs b/sehn/src/se/base/mod.rs index 5c6ef7f..d11e8a7 100644 --- a/sehn/src/se/base/mod.rs +++ b/sehn/src/se/base/mod.rs @@ -1,9 +1,11 @@ mod real; +mod error; use core::marker::PhantomData; +use crate::grammar::*; + use super::{ - Write, Serialize, Serializer, SerializeDict, @@ -17,7 +19,22 @@ use self::real::{ FastRealSerializer }; -use crate::grammar::*; +pub use self::error::*; + +pub trait Write { + /// The core error that may bubble from + /// attempting to write. + type Error: WriteError; + + // fn write_delim(&mut self, delim: u8) -> Result<(), Self::Error>; + // fn write_utf8(&mut self, slice: &[u8]) -> Result<(), Self::Error>; + + /// Write an ASCII byte (unchecked). + unsafe fn write_delim_unchecked(&mut self, delim: u8) -> Result<(), Self::Error>; + + /// Write UTF8 bytes (unchecked). + unsafe fn write_utf8_unchecked(&mut self, slice: &[u8]) -> Result<(), Self::Error>; +} pub trait Config { type RealSerializer: RealSerializer; @@ -29,17 +46,29 @@ impl Config for DefaultConfig { type RealSerializer = FastRealSerializer; } -pub struct BaseSerializer { +pub struct BaseSerializer +where + C: Config, + W: Write +{ out: W, cfg: PhantomData } +impl BaseSerializer + where W: Write +{ + pub fn new(out: W) -> Self { + Self::with_config(out) + } +} + impl BaseSerializer where C: Config, W: Write { - pub fn new(out: W) -> Self { + pub fn with_config(out: W) -> Self { Self { out, cfg: PhantomData } } @@ -48,11 +77,21 @@ where } #[inline] - pub fn serialize_real(&mut self, r: R) -> Result<(), W::Error> + pub fn serialize_real(&mut self, r: R) -> Result<(), SerializerError> where C::RealSerializer: PrimitiveRealSerializer { - C::RealSerializer::serialize_real::(&mut self.out, r) + Ok(C::RealSerializer::serialize_real::(&mut self.out, r)?) + } + + #[inline] + fn write_delim(&mut self, delim: u8) -> Result<(), W::Error> { + unsafe { self.out.write_delim_unchecked(delim) } + } + + #[inline] + fn write_utf8(&mut self, slice: &[u8]) -> Result<(), W::Error> { + unsafe { self.out.write_utf8_unchecked(slice) } } } @@ -61,7 +100,7 @@ where C: Config, W: Write { - type Error = W::Error; + type Error = SerializerError; type SerializeDict = SerializeDictBase<'se, C, W>; type SerializeList = SerializeListBase<'se, C, W>; @@ -122,21 +161,21 @@ where where V: Serialize { self.serialize_atom(name)?; - self.out.write_delim(GRAMMAR_PAREN_OPEN)?; + self.write_delim(GRAMMAR_PAREN_OPEN)?; self.serialize_any(value)?; - self.out.write_delim(GRAMMAR_PAREN_CLOSE) + Ok(self.write_delim(GRAMMAR_PAREN_CLOSE)?) } #[inline] fn serialize_atom<'a>(self, atom: &'a str) -> Result<(), Self::Error> { - self.out.write_utf8(atom.as_bytes()) + Ok(self.write_utf8(atom.as_bytes())?) } #[inline] fn serialize_text<'a>(self, text: &'a str) -> Result<(), Self::Error> { - self.out.write_delim(GRAMMAR_QUOTE)?; - self.out.write_utf8(text.as_bytes())?; - self.out.write_delim(GRAMMAR_QUOTE) + self.write_delim(GRAMMAR_QUOTE)?; + self.write_utf8(text.as_bytes())?; + Ok(self.write_delim(GRAMMAR_QUOTE)?) } #[inline] @@ -198,8 +237,8 @@ where W: Write { #[inline] - fn start(ser: &'se mut BaseSerializer) -> Result { - ser.out.write_delim(GRAMMAR_PAREN_OPEN)?; + fn start(ser: &'se mut BaseSerializer) -> Result> { + ser.write_delim(GRAMMAR_PAREN_OPEN)?; Ok(Self { ser, first: true @@ -207,7 +246,7 @@ where } #[inline] - pub fn serialize(ser: &'se mut BaseSerializer, list: L) -> Result<(), W::Error> + pub fn serialize(ser: &'se mut BaseSerializer, list: L) -> Result<(), SerializerError> where V: Serialize, L: IntoIterator @@ -216,7 +255,7 @@ where for item in list.into_iter() { state.serialize_item(item)?; } - state.end() + Ok(state.end()?) } } @@ -225,7 +264,7 @@ where C: Config, W: Write { - type Error = W::Error; + type Error = SerializerError; #[inline] fn serialize_item(&mut self, item: I) -> Result<(), Self::Error> @@ -234,14 +273,14 @@ where if self.first { self.first = false; } else { - self.ser.out.write_delim(GRAMMAR_COMMA)?; + self.ser.write_delim(GRAMMAR_COMMA)?; } self.ser.serialize_any(&item) } #[inline] fn end(self) -> Result<(), Self::Error> { - self.ser.out.write_delim(GRAMMAR_BRACE_CLOSE) + Ok(self.ser.write_delim(GRAMMAR_BRACE_CLOSE)?) } } @@ -262,8 +301,8 @@ where W: Write { #[inline] - fn start(ser: &'se mut BaseSerializer) -> Result { - ser.out.write_delim(GRAMMAR_BRACE_OPEN)?; + fn start(ser: &'se mut BaseSerializer) -> Result> { + ser.write_delim(GRAMMAR_BRACE_OPEN)?; Ok(Self { ser, first: true @@ -271,7 +310,7 @@ where } #[inline] - pub fn serialize(ser: &'se mut BaseSerializer, dict: D) -> Result<(), W::Error> + pub fn serialize(ser: &'se mut BaseSerializer, dict: D) -> Result<(), SerializerError> where K: Serialize, V: Serialize, @@ -290,7 +329,7 @@ where C: Config, W: Write { - type Error = W::Error; + type Error = SerializerError; #[inline] fn serialize_kv(&mut self, key: K, value: V) -> Result<(), Self::Error> @@ -301,16 +340,16 @@ where if self.first { self.first = false; } else { - self.ser.out.write_delim(GRAMMAR_COMMA)?; + self.ser.write_delim(GRAMMAR_COMMA)?; } self.ser.serialize_any(&key)?; - self.ser.out.write_delim(GRAMMAR_COLON)?; + self.ser.write_delim(GRAMMAR_COLON)?; self.ser.serialize_any(&value) } #[inline] fn end(self) -> Result<(), Self::Error> { - self.ser.out.write_delim(GRAMMAR_BRACE_CLOSE) + Ok(self.ser.write_delim(GRAMMAR_BRACE_CLOSE)?) } } @@ -330,15 +369,15 @@ where W: Write { #[inline] - fn start(ser: &'se mut BaseSerializer) -> Result { - ser.out.write_delim(GRAMMAR_BTICK)?; + fn start(ser: &'se mut BaseSerializer) -> Result> { + ser.write_delim(GRAMMAR_BTICK)?; Ok(Self { ser }) } #[inline] - pub fn serialize<'a, L>(ser: &'se mut BaseSerializer, lines: L) -> Result<(), W::Error> + pub fn serialize<'a, L>(ser: &'se mut BaseSerializer, lines: L) -> Result<(), SerializerError> where L: IntoIterator { @@ -355,7 +394,7 @@ where C: Config, W: Write { - type Error = W::Error; + type Error = SerializerError; #[inline] fn serialize_line(&mut self, line: &str) -> Result<(), Self::Error> { @@ -364,6 +403,6 @@ where #[inline] fn end(self) -> Result<(), Self::Error> { - self.ser.out.write_delim(GRAMMAR_BTICK) + Ok(self.ser.write_delim(GRAMMAR_BTICK)?) } } \ No newline at end of file diff --git a/sehn/src/se/base/real/fast.rs b/sehn/src/se/base/real/fast.rs index 40fdada..d7b9421 100644 --- a/sehn/src/se/base/real/fast.rs +++ b/sehn/src/se/base/real/fast.rs @@ -1,6 +1,8 @@ use core::fmt::Write as FmtWrite; -use crate::se::{Write, SerializerError}; + use super::{ + Write, + SerializerError, dec_buf::DecBuf, RealSerializer, PrimitiveRealSerializer @@ -9,10 +11,11 @@ use super::{ macro_rules! impl_write_real_int_for_fast_serializer { ($($prim:ident)*) => { $(impl PrimitiveRealSerializer<$prim> for FastRealSerializer { - fn serialize_real(out: &mut W, r: $prim) -> Result<(), W::Error> { + fn serialize_real(out: &mut W, r: $prim) -> Result<(), SerializerError> { let mut buf = itoa::Buffer::new(); let real_str = buf.format(r); - out.write_utf8(real_str.as_bytes()) + unsafe { out.write_utf8_unchecked(real_str.as_bytes())? }; + Ok(()) } })* } @@ -21,12 +24,13 @@ macro_rules! impl_write_real_int_for_fast_serializer { macro_rules! impl_write_real_float_for_fast_serializer { ($($prim:ident)*) => { $(impl PrimitiveRealSerializer<$prim> for FastRealSerializer { - fn serialize_real(out: &mut W, r: $prim) -> Result<(), W::Error> { + fn serialize_real(out: &mut W, r: $prim) -> Result<(), SerializerError> { let mut buf = DecBuf::new(); write!(buf, "{}", r).map_err(|_| SerializerError::Unexpected("failed to format real") )?; - out.write_utf8(buf.as_bytes()) + unsafe { out.write_utf8_unchecked(buf.as_bytes())? }; + Ok(()) } })* } diff --git a/sehn/src/se/base/real/mod.rs b/sehn/src/se/base/real/mod.rs index 4827701..2f4a866 100644 --- a/sehn/src/se/base/real/mod.rs +++ b/sehn/src/se/base/real/mod.rs @@ -3,12 +3,11 @@ mod dec_buf; pub use self::fast::*; -use crate::se::Write; +use super::{Write, SerializerError}; pub trait PrimitiveRealSerializer { - fn serialize_real(w: &mut W, i: T) -> Result<(), W::Error> - where - W: Write; + fn serialize_real(w: &mut W, i: T) -> Result<(), SerializerError> + where W: Write; } pub trait RealSerializer: diff --git a/sehn/src/se/error.rs b/sehn/src/se/error.rs deleted file mode 100644 index 504b05e..0000000 --- a/sehn/src/se/error.rs +++ /dev/null @@ -1,20 +0,0 @@ -use core::fmt; - -pub enum SerializerError { - /// A unexpected error (should never get this). - Unexpected(&'static str) -} - -impl fmt::Debug for SerializerError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use SerializerError::*; - match self { - Unexpected(ref err) => write!(f, "unexpected error: {}", err) - } - } -} - -pub trait Error: fmt::Debug + From {} - -impl Error for T where - T: fmt::Debug + From {} \ No newline at end of file diff --git a/sehn/src/se/impls.rs b/sehn/src/se/impls.rs index c59b815..a111d77 100644 --- a/sehn/src/se/impls.rs +++ b/sehn/src/se/impls.rs @@ -1,6 +1,8 @@ +#[cfg(any(feature = "std", feature = "alloc"))] use std::hash::{Hash, BuildHasher}; -use std::collections::HashMap; -use std::collections::BTreeMap; + +#[cfg(any(feature = "std", feature = "alloc"))] +use std::collections::*; use super::{Serialize, Serializer}; @@ -37,7 +39,7 @@ impl Serialize for str { /////////////////////////////////////////////////////////////////////////////// -//#[cfg(any(feature = "std", feature = "alloc"))] +#[cfg(any(feature = "std", feature = "alloc"))] macro_rules! seq_impl { ($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => { impl Serialize for $ty @@ -56,23 +58,23 @@ macro_rules! seq_impl { } } -//#[cfg(any(feature = "std", feature = "alloc"))] +#[cfg(any(feature = "std", feature = "alloc"))] seq_impl!(Vec); -// #[cfg(any(feature = "std", feature = "alloc"))] -// seq_impl!(BinaryHeap); +#[cfg(any(feature = "std", feature = "alloc"))] +seq_impl!(BinaryHeap); -// #[cfg(any(feature = "std", feature = "alloc"))] -// seq_impl!(BTreeSet); +#[cfg(any(feature = "std", feature = "alloc"))] +seq_impl!(BTreeSet); -// #[cfg(feature = "std")] -// seq_impl!(HashSet); +#[cfg(feature = "std")] +seq_impl!(HashSet); -// #[cfg(any(feature = "std", feature = "alloc"))] -// seq_impl!(LinkedList); +#[cfg(any(feature = "std", feature = "alloc"))] +seq_impl!(LinkedList); -// #[cfg(any(feature = "std", feature = "alloc"))] -// seq_impl!(VecDeque); +#[cfg(any(feature = "std", feature = "alloc"))] +seq_impl!(VecDeque); /////////////////////////////////////////////////////////////////////////////// @@ -91,7 +93,7 @@ where /////////////////////////////////////////////////////////////////////////////// -//#[cfg(any(feature = "std", feature = "alloc"))] +#[cfg(any(feature = "std", feature = "alloc"))] macro_rules! dict_impl { ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => { impl Serialize for $ty @@ -111,10 +113,10 @@ macro_rules! dict_impl { } } -//#[cfg(any(feature = "std", feature = "alloc"))] +#[cfg(any(feature = "std", feature = "alloc"))] dict_impl!(BTreeMap); -//#[cfg(feature = "std")] +#[cfg(feature = "std")] dict_impl!(HashMap); /////////////////////////////////////////////////////////////////////////////// @@ -140,5 +142,5 @@ macro_rules! deref_impl { deref_impl!(<'a, T: ?Sized> Serialize for &'a T where T: Serialize); deref_impl!(<'a, T: ?Sized> Serialize for &'a mut T where T: Serialize); -//#[cfg(any(feature = "std", feature = "alloc"))] +#[cfg(any(feature = "std", feature = "alloc"))] deref_impl!( Serialize for Box where T: Serialize); \ No newline at end of file diff --git a/sehn/src/se/mod.rs b/sehn/src/se/mod.rs index 479f22e..e182721 100644 --- a/sehn/src/se/mod.rs +++ b/sehn/src/se/mod.rs @@ -1,28 +1,15 @@ mod base; -mod error; mod impls; pub use self::base::*; -pub use self::error::*; - -pub trait Write { - /// The core error that may bubble from - /// attempting to write. - type Error: Error; - - fn write_delim(&mut self, delim: u8) -> Result<(), Self::Error>; - - fn write_utf8(&mut self, buf: &[u8]) -> Result<(), Self::Error>; -} pub trait Serialize { fn serialize(&self, s: S) -> Result<(), S::Error> - where - S: Serializer; + where S: Serializer; } pub trait SerializeDict { - type Error: Error; + type Error; fn serialize_kv(&mut self, key: K, value: V) -> Result<(), Self::Error> where @@ -33,7 +20,7 @@ pub trait SerializeDict { } pub trait SerializeList { - type Error: Error; + type Error; fn serialize_item(&mut self, item: I) -> Result<(), Self::Error> where I: Serialize; @@ -42,7 +29,7 @@ pub trait SerializeList { } pub trait SerializeMultilineText { - type Error: Error; + type Error; fn serialize_line(&mut self, line: &str) -> Result<(), Self::Error>; @@ -50,7 +37,7 @@ pub trait SerializeMultilineText { } pub trait Serializer: Sized { - type Error: Error; + type Error; type SerializeDict: SerializeDict; type SerializeList: SerializeList; diff --git a/sehn/src/utils/buffer.rs b/sehn/src/utils/buffer.rs new file mode 100644 index 0000000..e867296 --- /dev/null +++ b/sehn/src/utils/buffer.rs @@ -0,0 +1,120 @@ +use crate::se::WriteError; + +pub trait GenericWriteBuffer: Sized { + type Error; + + fn clear(&mut self); + + fn push_byte(&mut self, byte: u8) -> Result<(), Self::Error>; + + fn push_slice(&mut self, slice: &[u8]) -> Result<(), Self::Error>; +} + +pub trait GenericReadBuffer: Sized { + fn len(&self) -> usize; + + fn as_slice(&self) -> &[u8]; + + #[cfg(any(feature = "std", feature = "alloc"))] + fn to_vec(self) -> Vec { + self.as_slice().to_vec() + } +} + +/////////////////////////////////////////////////////////////////////////////// + +#[derive(Debug)] +pub struct SliceBufferError; + +impl WriteError for SliceBufferError {} + +pub struct SliceBuffer<'a> { + buf: &'a mut [u8], + len: usize +} + +impl<'a> SliceBuffer<'a> { + pub fn new(buf: &'a mut [u8]) -> Self { + Self { buf, len: 0 } + } +} + +impl<'a> GenericReadBuffer for SliceBuffer<'a> { + #[inline] + fn len(&self) -> usize { + self.len + } + + fn as_slice(&self) -> &[u8] { + &self.buf[..self.len] + } +} + +impl<'a> GenericWriteBuffer for SliceBuffer<'a> { + type Error = SliceBufferError; + + #[inline] + fn clear(&mut self) { + self.len = 0; + } + + fn push_byte(&mut self, byte: u8) -> Result<(), Self::Error> { + let new_len = self.len + 1; + if new_len > self.buf.len() { + Err(SliceBufferError) + } else { + self.buf[self.len] = byte; + self.len = new_len; + Ok(()) + } + } + + fn push_slice(&mut self, slice: &[u8]) -> Result<(), Self::Error> { + let new_len = self.len + slice.len(); + if new_len > self.buf.len() { + Err(SliceBufferError) + } else { + self.buf[self.len..new_len].copy_from_slice(slice); + self.len = new_len; + Ok(()) + } + } +} + +/////////////////////////////////////////////////////////////////////////////// + +#[cfg(any(feature = "std", feature = "alloc"))] +impl GenericWriteBuffer for Vec { + type Error = (); + + #[inline] + fn clear(&mut self) { + self.clear(); + } + + #[inline] + fn push_byte(&mut self, byte: u8) -> Result<(), Self::Error> { + Ok(self.push(byte)) + } + + #[inline] + fn push_slice(&mut self, slice: &[u8]) -> Result<(), Self::Error> { + Ok(self.extend_from_slice(slice)) + } +} + +#[cfg(any(feature = "std", feature = "alloc"))] +impl GenericReadBuffer for Vec { + fn len(&self) -> usize { + self.len() + } + + fn as_slice(&self) -> &[u8] { + self.as_slice() + } + + #[cfg(any(feature = "std", feature = "alloc"))] + fn to_vec(self) -> Vec { + self + } +} \ No newline at end of file diff --git a/sehn/src/utils/mod.rs b/sehn/src/utils/mod.rs index cdd9d99..a30d3f8 100644 --- a/sehn/src/utils/mod.rs +++ b/sehn/src/utils/mod.rs @@ -1,5 +1,18 @@ -mod to_string; -mod string_writer; +mod buffer; +mod writer; -pub use self::to_string::*; -pub use self::string_writer::*; \ No newline at end of file +#[cfg(any(feature = "std", feature = "alloc"))] +use crate::se::*; + +pub use self::writer::*; +pub use self::buffer::*; + +#[cfg(any(feature = "std", feature = "alloc"))] +pub fn to_string(value: T) -> Result> + where T: Serialize +{ + let mut w = GenericWriter::from(Vec::new()); + let mut s = BaseSerializer::new(&mut w); + value.serialize(&mut s)?; + Ok(w.to_string()) +} \ No newline at end of file diff --git a/sehn/src/utils/string_writer.rs b/sehn/src/utils/string_writer.rs deleted file mode 100644 index a2a8f5b..0000000 --- a/sehn/src/utils/string_writer.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::str::Utf8Error; -use std::string::FromUtf8Error; - -use crate::se::{Write, SerializerError}; - -pub struct StringWriter { - buf: Vec -} - -impl StringWriter { - pub fn new() -> Self { - Self { - buf: Vec::new() - } - } - - pub fn clear(&mut self) { - self.buf.clear(); - } - - pub fn as_str(&self) -> Result<&str, Utf8Error> { - std::str::from_utf8(self.buf.as_ref()) - } - - pub fn to_string(self) -> Result { - String::from_utf8(self.buf) - } -} - -impl Write for &mut StringWriter { - type Error = SerializerError; - - fn write_utf8(&mut self, buf: &[u8]) -> Result<(), Self::Error> { - self.buf.extend_from_slice(buf); - Ok(()) - } - - fn write_delim(&mut self, delim: u8) -> Result<(), Self::Error> { - self.buf.push(delim); - Ok(()) - } -} \ No newline at end of file diff --git a/sehn/src/utils/to_string.rs b/sehn/src/utils/to_string.rs deleted file mode 100644 index 29bdedc..0000000 --- a/sehn/src/utils/to_string.rs +++ /dev/null @@ -1,17 +0,0 @@ -use crate::se::*; -use super::StringWriter; - -pub fn default_base_serializer(w: W) -> BaseSerializer - where W: Write -{ - BaseSerializer::new(w) -} - -pub fn to_string(value: T) -> Result - where T: Serialize -{ - let mut w = StringWriter::new(); - let mut s = default_base_serializer(&mut w); - value.serialize(&mut s)?; - Ok(w.to_string().unwrap()) -} \ No newline at end of file diff --git a/sehn/src/utils/writer.rs b/sehn/src/utils/writer.rs new file mode 100644 index 0000000..7b9642b --- /dev/null +++ b/sehn/src/utils/writer.rs @@ -0,0 +1,55 @@ +use crate::se::*; +use super::{GenericWriteBuffer, GenericReadBuffer}; + +pub struct GenericWriter + where T: GenericWriteBuffer +{ + buf: T +} + +impl From for GenericWriter + where T: GenericWriteBuffer +{ + fn from(buf: T) -> Self { + Self { buf } + } +} + +impl GenericWriter + where T: GenericWriteBuffer + GenericReadBuffer +{ + pub fn into_inner(self) -> T { + self.buf + } + + pub fn clear(&mut self) { + self.buf.clear(); + } + + pub fn as_str(&self) -> &str { + unsafe { core::str::from_utf8_unchecked(self.buf.as_slice()) } + } + + #[cfg(any(feature = "std", feature = "alloc"))] + pub fn to_string(self) -> String { + unsafe { String::from_utf8_unchecked(self.buf.to_vec()) } + } +} + +impl Write for &mut GenericWriter +where + T: GenericWriteBuffer + GenericReadBuffer, + T::Error: WriteError +{ + type Error = T::Error; + + #[inline] + unsafe fn write_delim_unchecked(&mut self, delim: u8) -> Result<(), Self::Error> { + self.buf.push_byte(delim) + } + + #[inline] + unsafe fn write_utf8_unchecked(&mut self, slice: &[u8]) -> Result<(), Self::Error> { + self.buf.push_slice(slice) + } +} \ No newline at end of file