Better errors, no-std, generic writer system
This commit is contained in:
parent
cca35eadde
commit
6ca24956ad
@ -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 = []
|
||||||
|
@ -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
13
sehn/examples/no-std.rs
Normal 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());
|
||||||
|
}
|
@ -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
33
sehn/src/se/base/error.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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)?)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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(())
|
||||||
}
|
}
|
||||||
})*
|
})*
|
||||||
}
|
}
|
||||||
|
@ -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:
|
||||||
|
@ -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> {}
|
|
@ -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);
|
@ -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
120
sehn/src/utils/buffer.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -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())
|
||||||
|
}
|
@ -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(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
55
sehn/src/utils/writer.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user