Better errors, no-std, generic writer system

This commit is contained in:
James Dyson 2019-01-21 13:25:44 +00:00
parent cca35eadde
commit 6ca24956ad
16 changed files with 358 additions and 166 deletions

View File

@ -5,4 +5,8 @@ authors = ["James Dyson <theavitex@gmail.com>"]
edition = "2018" edition = "2018"
[dependencies] [dependencies]
itoa = "0.4" itoa = "0.4"
[features]
default = ["std"]
std = []

View File

@ -4,18 +4,18 @@ use std::collections::BTreeMap;
use sehn::*; use sehn::*;
fn print_and_clear(s: BaseSerializer<DefaultConfig, &mut StringWriter>) { fn print_and_clear(s: BaseSerializer<DefaultConfig, &mut GenericWriter<Vec<u8>>>) {
let out = s.into_inner(); let out = s.into_inner();
println!("{}", out.as_str().unwrap()); println!("{}", out.as_str());
out.clear(); out.clear();
} }
fn main() { 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(); let mut obj = BTreeMap::new();
obj.insert("hello", Tag::new("one", vec![1])); 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![ let lines = vec![
"hello", "hello",

13
sehn/examples/no-std.rs Normal file
View File

@ -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());
}

View File

@ -1,3 +1,5 @@
#![cfg_attr(not(feature = "std"), no_std)]
pub mod se; pub mod se;
pub mod de; pub mod de;
pub mod value; pub mod value;

33
sehn/src/se/base/error.rs Normal file
View File

@ -0,0 +1,33 @@
use core::fmt;
pub trait WriteError: fmt::Debug {}
impl WriteError for () {}
pub enum SerializerError<WE>
where WE: WriteError
{
Write(WE),
/// A unexpected error (should never get this).
Unexpected(&'static str)
}
impl<WE> From<WE> for SerializerError<WE>
where WE: WriteError
{
fn from(err: WE) -> Self {
SerializerError::Write(err)
}
}
impl<WE> fmt::Debug for SerializerError<WE>
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)
}
}
}

View File

@ -1,9 +1,11 @@
mod real; mod real;
mod error;
use core::marker::PhantomData; use core::marker::PhantomData;
use crate::grammar::*;
use super::{ use super::{
Write,
Serialize, Serialize,
Serializer, Serializer,
SerializeDict, SerializeDict,
@ -17,7 +19,22 @@ use self::real::{
FastRealSerializer 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 { pub trait Config {
type RealSerializer: RealSerializer; type RealSerializer: RealSerializer;
@ -29,17 +46,29 @@ impl Config for DefaultConfig {
type RealSerializer = FastRealSerializer; type RealSerializer = FastRealSerializer;
} }
pub struct BaseSerializer<C: Config, W: Write> { pub struct BaseSerializer<C, W>
where
C: Config,
W: Write
{
out: W, out: W,
cfg: PhantomData<C> cfg: PhantomData<C>
} }
impl<W> BaseSerializer<DefaultConfig, W>
where W: Write
{
pub fn new(out: W) -> Self {
Self::with_config(out)
}
}
impl<C, W> BaseSerializer<C, W> impl<C, W> BaseSerializer<C, W>
where where
C: Config, C: Config,
W: Write W: Write
{ {
pub fn new(out: W) -> Self { pub fn with_config(out: W) -> Self {
Self { out, cfg: PhantomData } Self { out, cfg: PhantomData }
} }
@ -48,11 +77,21 @@ where
} }
#[inline] #[inline]
pub fn serialize_real<R>(&mut self, r: R) -> Result<(), W::Error> pub fn serialize_real<R>(&mut self, r: R) -> Result<(), SerializerError<W::Error>>
where where
C::RealSerializer: PrimitiveRealSerializer<R> C::RealSerializer: PrimitiveRealSerializer<R>
{ {
C::RealSerializer::serialize_real::<W>(&mut self.out, r) Ok(C::RealSerializer::serialize_real::<W>(&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, C: Config,
W: Write W: Write
{ {
type Error = W::Error; type Error = SerializerError<W::Error>;
type SerializeDict = SerializeDictBase<'se, C, W>; type SerializeDict = SerializeDictBase<'se, C, W>;
type SerializeList = SerializeListBase<'se, C, W>; type SerializeList = SerializeListBase<'se, C, W>;
@ -122,21 +161,21 @@ where
where V: Serialize where V: Serialize
{ {
self.serialize_atom(name)?; self.serialize_atom(name)?;
self.out.write_delim(GRAMMAR_PAREN_OPEN)?; self.write_delim(GRAMMAR_PAREN_OPEN)?;
self.serialize_any(value)?; self.serialize_any(value)?;
self.out.write_delim(GRAMMAR_PAREN_CLOSE) Ok(self.write_delim(GRAMMAR_PAREN_CLOSE)?)
} }
#[inline] #[inline]
fn serialize_atom<'a>(self, atom: &'a str) -> Result<(), Self::Error> { 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] #[inline]
fn serialize_text<'a>(self, text: &'a str) -> Result<(), Self::Error> { fn serialize_text<'a>(self, text: &'a str) -> Result<(), Self::Error> {
self.out.write_delim(GRAMMAR_QUOTE)?; self.write_delim(GRAMMAR_QUOTE)?;
self.out.write_utf8(text.as_bytes())?; self.write_utf8(text.as_bytes())?;
self.out.write_delim(GRAMMAR_QUOTE) Ok(self.write_delim(GRAMMAR_QUOTE)?)
} }
#[inline] #[inline]
@ -198,8 +237,8 @@ where
W: Write W: Write
{ {
#[inline] #[inline]
fn start(ser: &'se mut BaseSerializer<C, W>) -> Result<Self, W::Error> { fn start(ser: &'se mut BaseSerializer<C, W>) -> Result<Self, SerializerError<W::Error>> {
ser.out.write_delim(GRAMMAR_PAREN_OPEN)?; ser.write_delim(GRAMMAR_PAREN_OPEN)?;
Ok(Self { Ok(Self {
ser, ser,
first: true first: true
@ -207,7 +246,7 @@ where
} }
#[inline] #[inline]
pub fn serialize<V, L>(ser: &'se mut BaseSerializer<C, W>, list: L) -> Result<(), W::Error> pub fn serialize<V, L>(ser: &'se mut BaseSerializer<C, W>, list: L) -> Result<(), SerializerError<W::Error>>
where where
V: Serialize, V: Serialize,
L: IntoIterator<Item = V> L: IntoIterator<Item = V>
@ -216,7 +255,7 @@ where
for item in list.into_iter() { for item in list.into_iter() {
state.serialize_item(item)?; state.serialize_item(item)?;
} }
state.end() Ok(state.end()?)
} }
} }
@ -225,7 +264,7 @@ where
C: Config, C: Config,
W: Write W: Write
{ {
type Error = W::Error; type Error = SerializerError<W::Error>;
#[inline] #[inline]
fn serialize_item<I>(&mut self, item: I) -> Result<(), Self::Error> fn serialize_item<I>(&mut self, item: I) -> Result<(), Self::Error>
@ -234,14 +273,14 @@ where
if self.first { if self.first {
self.first = false; self.first = false;
} else { } else {
self.ser.out.write_delim(GRAMMAR_COMMA)?; self.ser.write_delim(GRAMMAR_COMMA)?;
} }
self.ser.serialize_any(&item) self.ser.serialize_any(&item)
} }
#[inline] #[inline]
fn end(self) -> Result<(), Self::Error> { 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 W: Write
{ {
#[inline] #[inline]
fn start(ser: &'se mut BaseSerializer<C, W>) -> Result<Self, W::Error> { fn start(ser: &'se mut BaseSerializer<C, W>) -> Result<Self, SerializerError<W::Error>> {
ser.out.write_delim(GRAMMAR_BRACE_OPEN)?; ser.write_delim(GRAMMAR_BRACE_OPEN)?;
Ok(Self { Ok(Self {
ser, ser,
first: true first: true
@ -271,7 +310,7 @@ where
} }
#[inline] #[inline]
pub fn serialize<K, V, D>(ser: &'se mut BaseSerializer<C, W>, dict: D) -> Result<(), W::Error> pub fn serialize<K, V, D>(ser: &'se mut BaseSerializer<C, W>, dict: D) -> Result<(), SerializerError<W::Error>>
where where
K: Serialize, K: Serialize,
V: Serialize, V: Serialize,
@ -290,7 +329,7 @@ where
C: Config, C: Config,
W: Write W: Write
{ {
type Error = W::Error; type Error = SerializerError<W::Error>;
#[inline] #[inline]
fn serialize_kv<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error> fn serialize_kv<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
@ -301,16 +340,16 @@ where
if self.first { if self.first {
self.first = false; self.first = false;
} else { } else {
self.ser.out.write_delim(GRAMMAR_COMMA)?; self.ser.write_delim(GRAMMAR_COMMA)?;
} }
self.ser.serialize_any(&key)?; self.ser.serialize_any(&key)?;
self.ser.out.write_delim(GRAMMAR_COLON)?; self.ser.write_delim(GRAMMAR_COLON)?;
self.ser.serialize_any(&value) self.ser.serialize_any(&value)
} }
#[inline] #[inline]
fn end(self) -> Result<(), Self::Error> { 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 W: Write
{ {
#[inline] #[inline]
fn start(ser: &'se mut BaseSerializer<C, W>) -> Result<Self, W::Error> { fn start(ser: &'se mut BaseSerializer<C, W>) -> Result<Self, SerializerError<W::Error>> {
ser.out.write_delim(GRAMMAR_BTICK)?; ser.write_delim(GRAMMAR_BTICK)?;
Ok(Self { Ok(Self {
ser ser
}) })
} }
#[inline] #[inline]
pub fn serialize<'a, L>(ser: &'se mut BaseSerializer<C, W>, lines: L) -> Result<(), W::Error> pub fn serialize<'a, L>(ser: &'se mut BaseSerializer<C, W>, lines: L) -> Result<(), SerializerError<W::Error>>
where where
L: IntoIterator<Item = &'a str> L: IntoIterator<Item = &'a str>
{ {
@ -355,7 +394,7 @@ where
C: Config, C: Config,
W: Write W: Write
{ {
type Error = W::Error; type Error = SerializerError<W::Error>;
#[inline] #[inline]
fn serialize_line(&mut self, line: &str) -> Result<(), Self::Error> { fn serialize_line(&mut self, line: &str) -> Result<(), Self::Error> {
@ -364,6 +403,6 @@ where
#[inline] #[inline]
fn end(self) -> Result<(), Self::Error> { fn end(self) -> Result<(), Self::Error> {
self.ser.out.write_delim(GRAMMAR_BTICK) Ok(self.ser.write_delim(GRAMMAR_BTICK)?)
} }
} }

View File

@ -1,6 +1,8 @@
use core::fmt::Write as FmtWrite; use core::fmt::Write as FmtWrite;
use crate::se::{Write, SerializerError};
use super::{ use super::{
Write,
SerializerError,
dec_buf::DecBuf, dec_buf::DecBuf,
RealSerializer, RealSerializer,
PrimitiveRealSerializer PrimitiveRealSerializer
@ -9,10 +11,11 @@ use super::{
macro_rules! impl_write_real_int_for_fast_serializer { macro_rules! impl_write_real_int_for_fast_serializer {
($($prim:ident)*) => { ($($prim:ident)*) => {
$(impl PrimitiveRealSerializer<$prim> for FastRealSerializer { $(impl PrimitiveRealSerializer<$prim> for FastRealSerializer {
fn serialize_real<W: Write>(out: &mut W, r: $prim) -> Result<(), W::Error> { fn serialize_real<W: Write>(out: &mut W, r: $prim) -> Result<(), SerializerError<W::Error>> {
let mut buf = itoa::Buffer::new(); let mut buf = itoa::Buffer::new();
let real_str = buf.format(r); 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 { macro_rules! impl_write_real_float_for_fast_serializer {
($($prim:ident)*) => { ($($prim:ident)*) => {
$(impl PrimitiveRealSerializer<$prim> for FastRealSerializer { $(impl PrimitiveRealSerializer<$prim> for FastRealSerializer {
fn serialize_real<W: Write>(out: &mut W, r: $prim) -> Result<(), W::Error> { fn serialize_real<W: Write>(out: &mut W, r: $prim) -> Result<(), SerializerError<W::Error>> {
let mut buf = DecBuf::new(); let mut buf = DecBuf::new();
write!(buf, "{}", r).map_err(|_| write!(buf, "{}", r).map_err(|_|
SerializerError::Unexpected("failed to format real") SerializerError::Unexpected("failed to format real")
)?; )?;
out.write_utf8(buf.as_bytes()) unsafe { out.write_utf8_unchecked(buf.as_bytes())? };
Ok(())
} }
})* })*
} }

View File

@ -3,12 +3,11 @@ mod dec_buf;
pub use self::fast::*; pub use self::fast::*;
use crate::se::Write; use super::{Write, SerializerError};
pub trait PrimitiveRealSerializer<T> { pub trait PrimitiveRealSerializer<T> {
fn serialize_real<W>(w: &mut W, i: T) -> Result<(), W::Error> fn serialize_real<W>(w: &mut W, i: T) -> Result<(), SerializerError<W::Error>>
where where W: Write;
W: Write;
} }
pub trait RealSerializer: pub trait RealSerializer:

View File

@ -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<SerializerError> {}
impl<T> Error for T where
T: fmt::Debug + From<SerializerError> {}

View File

@ -1,6 +1,8 @@
#[cfg(any(feature = "std", feature = "alloc"))]
use std::hash::{Hash, BuildHasher}; 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}; 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 { macro_rules! seq_impl {
($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => { ($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => {
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*> impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
@ -56,23 +58,23 @@ macro_rules! seq_impl {
} }
} }
//#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
seq_impl!(Vec<T>); seq_impl!(Vec<T>);
// #[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
// seq_impl!(BinaryHeap<T: Ord>); seq_impl!(BinaryHeap<T: Ord>);
// #[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
// seq_impl!(BTreeSet<T: Ord>); seq_impl!(BTreeSet<T: Ord>);
// #[cfg(feature = "std")] #[cfg(feature = "std")]
// seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>); seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
// #[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
// seq_impl!(LinkedList<T>); seq_impl!(LinkedList<T>);
// #[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
// seq_impl!(VecDeque<T>); seq_impl!(VecDeque<T>);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -91,7 +93,7 @@ where
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
//#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
macro_rules! dict_impl { macro_rules! dict_impl {
($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => { ($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*> impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
@ -111,10 +113,10 @@ macro_rules! dict_impl {
} }
} }
//#[cfg(any(feature = "std", feature = "alloc"))] #[cfg(any(feature = "std", feature = "alloc"))]
dict_impl!(BTreeMap<K: Ord, V>); dict_impl!(BTreeMap<K: Ord, V>);
//#[cfg(feature = "std")] #[cfg(feature = "std")]
dict_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>); dict_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -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 T where T: Serialize);
deref_impl!(<'a, T: ?Sized> Serialize for &'a mut 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!(<T: ?Sized> Serialize for Box<T> where T: Serialize); deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);

View File

@ -1,28 +1,15 @@
mod base; mod base;
mod error;
mod impls; mod impls;
pub use self::base::*; 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 { pub trait Serialize {
fn serialize<S>(&self, s: S) -> Result<(), S::Error> fn serialize<S>(&self, s: S) -> Result<(), S::Error>
where where S: Serializer;
S: Serializer;
} }
pub trait SerializeDict { pub trait SerializeDict {
type Error: Error; type Error;
fn serialize_kv<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error> fn serialize_kv<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error>
where where
@ -33,7 +20,7 @@ pub trait SerializeDict {
} }
pub trait SerializeList { pub trait SerializeList {
type Error: Error; type Error;
fn serialize_item<I>(&mut self, item: I) -> Result<(), Self::Error> fn serialize_item<I>(&mut self, item: I) -> Result<(), Self::Error>
where I: Serialize; where I: Serialize;
@ -42,7 +29,7 @@ pub trait SerializeList {
} }
pub trait SerializeMultilineText { pub trait SerializeMultilineText {
type Error: Error; type Error;
fn serialize_line(&mut self, line: &str) -> Result<(), Self::Error>; fn serialize_line(&mut self, line: &str) -> Result<(), Self::Error>;
@ -50,7 +37,7 @@ pub trait SerializeMultilineText {
} }
pub trait Serializer: Sized { pub trait Serializer: Sized {
type Error: Error; type Error;
type SerializeDict: SerializeDict; type SerializeDict: SerializeDict;
type SerializeList: SerializeList; type SerializeList: SerializeList;

120
sehn/src/utils/buffer.rs Normal file
View File

@ -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<u8> {
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<u8> {
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<u8> {
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<u8> {
self
}
}

View File

@ -1,5 +1,18 @@
mod to_string; mod buffer;
mod string_writer; mod writer;
pub use self::to_string::*; #[cfg(any(feature = "std", feature = "alloc"))]
pub use self::string_writer::*; use crate::se::*;
pub use self::writer::*;
pub use self::buffer::*;
#[cfg(any(feature = "std", feature = "alloc"))]
pub fn to_string<T>(value: T) -> Result<String, SerializerError<()>>
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())
}

View File

@ -1,42 +0,0 @@
use std::str::Utf8Error;
use std::string::FromUtf8Error;
use crate::se::{Write, SerializerError};
pub struct StringWriter {
buf: Vec<u8>
}
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, FromUtf8Error> {
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(())
}
}

View File

@ -1,17 +0,0 @@
use crate::se::*;
use super::StringWriter;
pub fn default_base_serializer<W>(w: W) -> BaseSerializer<DefaultConfig, W>
where W: Write
{
BaseSerializer::new(w)
}
pub fn to_string<T>(value: T) -> Result<String, SerializerError>
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())
}

55
sehn/src/utils/writer.rs Normal file
View File

@ -0,0 +1,55 @@
use crate::se::*;
use super::{GenericWriteBuffer, GenericReadBuffer};
pub struct GenericWriter<T>
where T: GenericWriteBuffer
{
buf: T
}
impl<T> From<T> for GenericWriter<T>
where T: GenericWriteBuffer
{
fn from(buf: T) -> Self {
Self { buf }
}
}
impl<T> GenericWriter<T>
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<T> Write for &mut GenericWriter<T>
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)
}
}