Start work on better sehn base
This commit is contained in:
parent
e49e427e5a
commit
a202514b52
@ -1,5 +1,6 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
|
"sehn",
|
||||||
"sehn-serde",
|
"sehn-serde",
|
||||||
"sehn-std"
|
"sehn-std"
|
||||||
]
|
]
|
8
sehn/Cargo.toml
Normal file
8
sehn/Cargo.toml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
[package]
|
||||||
|
name = "sehn"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["James Dyson <theavitex@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
itoa = "0.4"
|
38
sehn/examples/basic.rs
Normal file
38
sehn/examples/basic.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
extern crate sehn;
|
||||||
|
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use sehn::*;
|
||||||
|
|
||||||
|
fn print_and_clear(s: BaseSerializer<DefaultConfig, &mut StringWriter>) {
|
||||||
|
let out = s.into_inner();
|
||||||
|
println!("{}", out.as_str().unwrap());
|
||||||
|
out.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut w = StringWriter::new();
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
let mut s = default_base_serializer(&mut w);
|
||||||
|
let mut obj = BTreeMap::new();
|
||||||
|
|
||||||
|
obj.insert("hello", Tag::new("one", vec![1]));
|
||||||
|
obj.insert("world", Tag::new("two", vec![2]));
|
||||||
|
|
||||||
|
s.serialize_any(obj).unwrap();
|
||||||
|
print_and_clear(s);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
let mut s = default_base_serializer(&mut w);
|
||||||
|
|
||||||
|
let lines = vec![
|
||||||
|
"hello",
|
||||||
|
"world"
|
||||||
|
];
|
||||||
|
|
||||||
|
s.serialize_multiline_text(lines).unwrap();
|
||||||
|
print_and_clear(s);
|
||||||
|
}
|
48
sehn/src/de/base/mod.rs
Normal file
48
sehn/src/de/base/mod.rs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
use super::{
|
||||||
|
Read,
|
||||||
|
Deserializer
|
||||||
|
};
|
||||||
|
|
||||||
|
pub struct BaseDeserializer<R> {
|
||||||
|
src: R,
|
||||||
|
peeked_byte: Option<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, R> BaseDeserializer<R>
|
||||||
|
where R: Read<'de>
|
||||||
|
{
|
||||||
|
pub fn new(src: R) -> Self {
|
||||||
|
Self {
|
||||||
|
src,
|
||||||
|
peeked_byte: None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn peek_byte(&mut self) -> Result<u8, R::Error> {
|
||||||
|
match self.peeked_byte {
|
||||||
|
Some(byte) => Ok(byte),
|
||||||
|
None => {
|
||||||
|
let byte = self.src.read()?;
|
||||||
|
self.peeked_byte = Some(byte);
|
||||||
|
Ok(byte)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_byte(&mut self) -> Result<u8, R::Error> {
|
||||||
|
match self.peeked_byte.take() {
|
||||||
|
Some(byte) => Ok(byte),
|
||||||
|
None => self.src.read()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de, R> Deserializer<'de> for &mut BaseDeserializer<R>
|
||||||
|
where R: Read<'de>
|
||||||
|
{
|
||||||
|
type Error = R::Error;
|
||||||
|
|
||||||
|
// fn deserialize_str(self) -> Result<&'de str, Self::Error> {
|
||||||
|
|
||||||
|
// }
|
||||||
|
}
|
20
sehn/src/de/error.rs
Normal file
20
sehn/src/de/error.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
pub enum DeserializerError {
|
||||||
|
/// A unexpected error (should never get this).
|
||||||
|
Unexpected(&'static str)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for DeserializerError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use DeserializerError::*;
|
||||||
|
match self {
|
||||||
|
Unexpected(ref err) => write!(f, "unexpected error: {}", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Error: fmt::Debug + From<DeserializerError> {}
|
||||||
|
|
||||||
|
impl<T> Error for T where
|
||||||
|
T: fmt::Debug + From<DeserializerError> {}
|
52
sehn/src/de/mod.rs
Normal file
52
sehn/src/de/mod.rs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
mod base;
|
||||||
|
mod error;
|
||||||
|
|
||||||
|
pub use self::base::*;
|
||||||
|
pub use self::error::*;
|
||||||
|
|
||||||
|
pub trait Read<'a> {
|
||||||
|
/// The error that a read can return.
|
||||||
|
type Error: Error;
|
||||||
|
|
||||||
|
/// Read a single byte.
|
||||||
|
fn read(&mut self) -> Result<u8, Self::Error>;
|
||||||
|
|
||||||
|
/// Start mark.
|
||||||
|
fn start_mark(&mut self);
|
||||||
|
|
||||||
|
/// Zero-copy drain from mark.
|
||||||
|
fn drain_mark(&mut self) -> Result<&'a [u8], Self::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Deserialize: Sized {
|
||||||
|
fn deserialize<'de, D>(d: D) -> Result<Self, D::Error>
|
||||||
|
where D: Deserializer<'de>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub trait Unit {
|
||||||
|
// fn from_name_value<T, E>(name: &str, value: T) -> Result<T, E>
|
||||||
|
// where
|
||||||
|
// T: Deserialize,
|
||||||
|
// E: Error;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// pub enum MaybeUnit<'a, T> {
|
||||||
|
// Raw(T),
|
||||||
|
// Wrapped(&'a str, T)
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub trait Deserializer<'de> {
|
||||||
|
type Error: Error;
|
||||||
|
|
||||||
|
//fn deserialize_real_u8(self) -> Result<u8, Self::Error>;
|
||||||
|
//fn deserialize_real_u16(self) -> Result<u16, Self::Error>;
|
||||||
|
//fn deserialize_real_u32(self) -> Result<u32, Self::Error>;
|
||||||
|
//fn deserialize_real_u64(self) -> Result<u64, Self::Error>;
|
||||||
|
//fn deserialize_real_i8(self) -> Result<i8, Self::Error>;
|
||||||
|
|
||||||
|
//fn deserialize_str(self) -> Result<&'de str, Self::Error>;
|
||||||
|
|
||||||
|
//fn deserialize_unit<U>(self) -> Result<U, Self::Error>
|
||||||
|
// where U: Unit;
|
||||||
|
//fn deserialize_maybe_unit(self) -> Result<MaybeUnit, Self::Error>;
|
||||||
|
}
|
24
sehn/src/grammar.rs
Normal file
24
sehn/src/grammar.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
// Braces
|
||||||
|
pub const GRAMMAR_BRACE_OPEN: u8 = b'{';
|
||||||
|
pub const GRAMMAR_BRACE_CLOSE: u8 = b'}';
|
||||||
|
|
||||||
|
// Parentheses
|
||||||
|
pub const GRAMMAR_PAREN_OPEN: u8 = b'(';
|
||||||
|
pub const GRAMMAR_PAREN_CLOSE: u8 = b')';
|
||||||
|
|
||||||
|
// Brackets
|
||||||
|
pub const GRAMMAR_BRKET_OPEN: u8 = b'[';
|
||||||
|
pub const GRAMMAR_BRKET_CLOSE: u8 = b']';
|
||||||
|
|
||||||
|
// Whitespace
|
||||||
|
pub const GRAMMAR_LF: u8 = b'\n';
|
||||||
|
pub const GRAMMAR_CR: u8 = b'\r';
|
||||||
|
pub const GRAMMAR_TAB: u8 = b'\t';
|
||||||
|
pub const GRAMMAR_SPACE: u8 = b' ';
|
||||||
|
|
||||||
|
// Other
|
||||||
|
pub const GRAMMAR_BTICK: u8 = b'`';
|
||||||
|
pub const GRAMMAR_QUOTE: u8 = b'"';
|
||||||
|
pub const GRAMMAR_COMMA: u8 = b',';
|
||||||
|
pub const GRAMMAR_COLON: u8 = b':';
|
||||||
|
pub const GRAMMAR_BSLSH: u8 = b'\\';
|
15
sehn/src/lib.rs
Normal file
15
sehn/src/lib.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
pub mod se;
|
||||||
|
pub mod de;
|
||||||
|
pub mod value;
|
||||||
|
pub mod grammar;
|
||||||
|
pub mod utils;
|
||||||
|
|
||||||
|
// Serialization/Deserialization
|
||||||
|
pub use self::de::*;
|
||||||
|
pub use self::se::*;
|
||||||
|
|
||||||
|
// Supporting values
|
||||||
|
pub use self::value::*;
|
||||||
|
|
||||||
|
// Utilities
|
||||||
|
pub use self::utils::*;
|
192
sehn/src/se/base/mod.rs
Normal file
192
sehn/src/se/base/mod.rs
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
mod real;
|
||||||
|
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
Write,
|
||||||
|
Serialize,
|
||||||
|
Serializer
|
||||||
|
};
|
||||||
|
|
||||||
|
use self::real::{
|
||||||
|
RealSerializer,
|
||||||
|
PrimitiveRealSerializer,
|
||||||
|
FastRealSerializer
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::grammar::*;
|
||||||
|
|
||||||
|
pub trait Config {
|
||||||
|
type RealSerializer: RealSerializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DefaultConfig {}
|
||||||
|
|
||||||
|
impl Config for DefaultConfig {
|
||||||
|
type RealSerializer = FastRealSerializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct BaseSerializer<C: Config, W: Write> {
|
||||||
|
out: W,
|
||||||
|
cfg: PhantomData<C>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C, W> BaseSerializer<C, W>
|
||||||
|
where
|
||||||
|
C: Config,
|
||||||
|
W: Write
|
||||||
|
{
|
||||||
|
pub fn new(out: W) -> Self {
|
||||||
|
Self { out, cfg: PhantomData }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_inner(self) -> W {
|
||||||
|
self.out
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn serialize_real<R>(&mut self, r: R) -> Result<(), W::Error>
|
||||||
|
where
|
||||||
|
C::RealSerializer: PrimitiveRealSerializer<R>
|
||||||
|
{
|
||||||
|
C::RealSerializer::serialize_real::<W>(&mut self.out, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn write_delim(&mut self, delim: u8) -> Result<(), W::Error> {
|
||||||
|
self.out.write(&[delim])
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn write_utf8(&mut self, s: &str) -> Result<(), W::Error> {
|
||||||
|
self.out.write(s.as_bytes())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: Config, W: Write> Serializer for &mut BaseSerializer<C, W> {
|
||||||
|
type Error = W::Error;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_real_u8(self, real: u8) -> Result<(), Self::Error> {
|
||||||
|
self.serialize_real::<u8>(real)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_real_u16(self, real: u16) -> Result<(), Self::Error> {
|
||||||
|
self.serialize_real::<u16>(real)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_real_u32(self, real: u32) -> Result<(), Self::Error> {
|
||||||
|
self.serialize_real::<u32>(real)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_real_u64(self, real: u64) -> Result<(), Self::Error> {
|
||||||
|
self.serialize_real::<u64>(real)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_real_i8(self, real: i8) -> Result<(), Self::Error> {
|
||||||
|
self.serialize_real::<i8>(real)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_real_i16(self, real: i16) -> Result<(), Self::Error> {
|
||||||
|
self.serialize_real::<i16>(real)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_real_i32(self, real: i32) -> Result<(), Self::Error> {
|
||||||
|
self.serialize_real::<i32>(real)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_real_i64(self, real: i64) -> Result<(), Self::Error> {
|
||||||
|
self.serialize_real::<i64>(real)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_real_f32(self, real: f32) -> Result<(), Self::Error> {
|
||||||
|
self.serialize_real::<f32>(real)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_real_f64(self, real: f64) -> Result<(), Self::Error> {
|
||||||
|
self.serialize_real::<f64>(real)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_unit<'a, V>(self, name: &'a str, value: V) -> Result<(), Self::Error>
|
||||||
|
where V: Serialize
|
||||||
|
{
|
||||||
|
self.serialize_atom(name)?;
|
||||||
|
self.write_delim(GRAMMAR_PAREN_OPEN)?;
|
||||||
|
self.serialize_any(value)?;
|
||||||
|
self.write_delim(GRAMMAR_PAREN_CLOSE)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_atom<'a>(self, atom: &'a str) -> Result<(), Self::Error> {
|
||||||
|
self.write_utf8(atom)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_text<'a>(self, text: &'a str) -> Result<(), Self::Error> {
|
||||||
|
self.write_delim(GRAMMAR_QUOTE)?;
|
||||||
|
self.write_utf8(text)?;
|
||||||
|
self.write_delim(GRAMMAR_QUOTE)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_multiline_text<'a, M>(self, lines: M) -> Result<(), Self::Error>
|
||||||
|
where M: IntoIterator<Item = &'a str>
|
||||||
|
{
|
||||||
|
self.write_delim(GRAMMAR_BTICK)?;
|
||||||
|
for line in lines.into_iter() {
|
||||||
|
self.serialize_text(line)?;
|
||||||
|
}
|
||||||
|
self.write_delim(GRAMMAR_BTICK)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_dict<K, V, D>(self, dict: D) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
K: Serialize,
|
||||||
|
V: Serialize,
|
||||||
|
D: IntoIterator<Item = (K, V)>
|
||||||
|
{
|
||||||
|
self.write_delim(GRAMMAR_BRACE_OPEN)?;
|
||||||
|
let mut first = true;
|
||||||
|
for (k, v) in dict.into_iter() {
|
||||||
|
if first {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
self.write_delim(GRAMMAR_COMMA)?;
|
||||||
|
}
|
||||||
|
self.serialize_any(&k)?;
|
||||||
|
self.write_delim(GRAMMAR_COLON)?;
|
||||||
|
self.serialize_any(&v)?;
|
||||||
|
}
|
||||||
|
self.write_delim(GRAMMAR_BRACE_CLOSE)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn serialize_list<T, L>(self, list: L) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
T: Serialize,
|
||||||
|
L: IntoIterator<Item = T>
|
||||||
|
{
|
||||||
|
self.write_delim(GRAMMAR_BRKET_OPEN)?;
|
||||||
|
let mut first = true;
|
||||||
|
for v in list.into_iter() {
|
||||||
|
if first {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
self.write_delim(GRAMMAR_COMMA)?;
|
||||||
|
}
|
||||||
|
self.serialize_any(&v)?;
|
||||||
|
}
|
||||||
|
self.write_delim(GRAMMAR_BRKET_CLOSE)
|
||||||
|
}
|
||||||
|
}
|
54
sehn/src/se/base/real/dec_buf.rs
Normal file
54
sehn/src/se/base/real/dec_buf.rs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
// Should be greater than MAX_SIG_DIGITS = 17
|
||||||
|
const DEC_BUF_SIZE: usize = 32;
|
||||||
|
|
||||||
|
pub struct DecBuf {
|
||||||
|
buf: [u8; DEC_BUF_SIZE],
|
||||||
|
len: usize
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DecBuf {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
buf: unsafe { core::mem::uninitialized() },
|
||||||
|
len: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_bytes(&self) -> &[u8] {
|
||||||
|
&self.buf[0..self.len]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn extend_mut_slice(&mut self, add_len: usize) -> Result<&mut [u8], fmt::Error> {
|
||||||
|
let cur_len = self.len;
|
||||||
|
let new_len = cur_len + add_len;
|
||||||
|
if new_len > self.buf.len() {
|
||||||
|
Err(fmt::Error)
|
||||||
|
} else {
|
||||||
|
self.len = new_len;
|
||||||
|
Ok(&mut self.buf[cur_len..new_len])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Write for DecBuf {
|
||||||
|
#[inline]
|
||||||
|
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||||
|
if s.is_empty() {
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let new_bytes = s.as_bytes();
|
||||||
|
self.extend_mut_slice(new_bytes.len()).map(|b| {
|
||||||
|
b.copy_from_slice(new_bytes);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn write_char(&mut self, c: char) -> fmt::Result {
|
||||||
|
self.extend_mut_slice(c.len_utf8()).map(|b| {
|
||||||
|
c.encode_utf8(b);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
47
sehn/src/se/base/real/fast.rs
Normal file
47
sehn/src/se/base/real/fast.rs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
use core::fmt::Write as FmtWrite;
|
||||||
|
use crate::se::{Write, SerializerError};
|
||||||
|
use super::{
|
||||||
|
dec_buf::DecBuf,
|
||||||
|
RealSerializer,
|
||||||
|
PrimitiveRealSerializer
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! impl_write_real_int_for_fast_serializer {
|
||||||
|
($($prim:ident)*) => {
|
||||||
|
$(impl PrimitiveRealSerializer<$prim> for FastRealSerializer {
|
||||||
|
fn serialize_real<W: Write>(out: &mut W, r: $prim) -> Result<(), W::Error> {
|
||||||
|
let mut buf = itoa::Buffer::new();
|
||||||
|
let real_str = buf.format(r);
|
||||||
|
out.write(real_str.as_bytes())
|
||||||
|
}
|
||||||
|
})*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_write_real_float_for_fast_serializer {
|
||||||
|
($($prim:ident)*) => {
|
||||||
|
$(impl PrimitiveRealSerializer<$prim> for FastRealSerializer {
|
||||||
|
fn serialize_real<W: Write>(out: &mut W, r: $prim) -> Result<(), W::Error> {
|
||||||
|
let mut buf = DecBuf::new();
|
||||||
|
write!(buf, "{}", r).map_err(|_|
|
||||||
|
SerializerError::Unexpected("failed to format real")
|
||||||
|
)?;
|
||||||
|
out.write(buf.as_bytes())
|
||||||
|
}
|
||||||
|
})*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FastRealSerializer;
|
||||||
|
|
||||||
|
impl_write_real_int_for_fast_serializer!(
|
||||||
|
u8 u16 u32 u64
|
||||||
|
i8 i16 i32 i64
|
||||||
|
);
|
||||||
|
|
||||||
|
impl_write_real_float_for_fast_serializer!(
|
||||||
|
f32
|
||||||
|
f64
|
||||||
|
);
|
||||||
|
|
||||||
|
impl RealSerializer for FastRealSerializer {}
|
24
sehn/src/se/base/real/mod.rs
Normal file
24
sehn/src/se/base/real/mod.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
mod fast;
|
||||||
|
mod dec_buf;
|
||||||
|
|
||||||
|
pub use self::fast::*;
|
||||||
|
|
||||||
|
use crate::se::Write;
|
||||||
|
|
||||||
|
pub trait PrimitiveRealSerializer<T> {
|
||||||
|
fn serialize_real<W>(w: &mut W, i: T) -> Result<(), W::Error>
|
||||||
|
where
|
||||||
|
W: Write;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait RealSerializer:
|
||||||
|
PrimitiveRealSerializer<i8> +
|
||||||
|
PrimitiveRealSerializer<i16> +
|
||||||
|
PrimitiveRealSerializer<i32> +
|
||||||
|
PrimitiveRealSerializer<i64> +
|
||||||
|
PrimitiveRealSerializer<u8> +
|
||||||
|
PrimitiveRealSerializer<u16> +
|
||||||
|
PrimitiveRealSerializer<u32> +
|
||||||
|
PrimitiveRealSerializer<u64> +
|
||||||
|
PrimitiveRealSerializer<f32> +
|
||||||
|
PrimitiveRealSerializer<f64> {}
|
20
sehn/src/se/error.rs
Normal file
20
sehn/src/se/error.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
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> {}
|
144
sehn/src/se/impls.rs
Normal file
144
sehn/src/se/impls.rs
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
use std::hash::{Hash, BuildHasher};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
use super::{Serialize, Serializer};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
macro_rules! real_impl {
|
||||||
|
($prim:ty, $func:ident) => {
|
||||||
|
impl Serialize for $prim {
|
||||||
|
fn serialize<S: Serializer>(&self, s: S) -> Result<(), S::Error> {
|
||||||
|
s.$func(*self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
real_impl!(u8, serialize_real_u8);
|
||||||
|
real_impl!(u16, serialize_real_u16);
|
||||||
|
real_impl!(u32, serialize_real_u32);
|
||||||
|
real_impl!(u64, serialize_real_u64);
|
||||||
|
real_impl!(i8, serialize_real_i8);
|
||||||
|
real_impl!(i16, serialize_real_i16);
|
||||||
|
real_impl!(i32, serialize_real_i32);
|
||||||
|
real_impl!(i64, serialize_real_i64);
|
||||||
|
real_impl!(f32, serialize_real_f32);
|
||||||
|
real_impl!(f64, serialize_real_f64);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
impl Serialize for str {
|
||||||
|
fn serialize<S: Serializer>(&self, s: S) -> Result<(), S::Error> {
|
||||||
|
s.serialize_text(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
macro_rules! seq_impl {
|
||||||
|
($ty:ident < T $(: $tbound1:ident $(+ $tbound2:ident)*)* $(, $typaram:ident : $bound:ident)* >) => {
|
||||||
|
impl<T $(, $typaram)*> Serialize for $ty<T $(, $typaram)*>
|
||||||
|
where
|
||||||
|
T: Serialize $(+ $tbound1 $(+ $tbound2)*)*,
|
||||||
|
$($typaram: $bound,)*
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<(), S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_list(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
seq_impl!(Vec<T>);
|
||||||
|
|
||||||
|
// #[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
// seq_impl!(BinaryHeap<T: Ord>);
|
||||||
|
|
||||||
|
// #[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
// seq_impl!(BTreeSet<T: Ord>);
|
||||||
|
|
||||||
|
// #[cfg(feature = "std")]
|
||||||
|
// seq_impl!(HashSet<T: Eq + Hash, H: BuildHasher>);
|
||||||
|
|
||||||
|
// #[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
// seq_impl!(LinkedList<T>);
|
||||||
|
|
||||||
|
// #[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
// seq_impl!(VecDeque<T>);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
impl<T> Serialize for [T]
|
||||||
|
where
|
||||||
|
T: Serialize,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<(), S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_list(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
macro_rules! dict_impl {
|
||||||
|
($ty:ident < K $(: $kbound1:ident $(+ $kbound2:ident)*)*, V $(, $typaram:ident : $bound:ident)* >) => {
|
||||||
|
impl<K, V $(, $typaram)*> Serialize for $ty<K, V $(, $typaram)*>
|
||||||
|
where
|
||||||
|
K: Serialize $(+ $kbound1 $(+ $kbound2)*)*,
|
||||||
|
V: Serialize,
|
||||||
|
$($typaram: $bound,)*
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<(), S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
serializer.serialize_dict(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#[cfg(any(feature = "std", feature = "alloc"))]
|
||||||
|
dict_impl!(BTreeMap<K: Ord, V>);
|
||||||
|
|
||||||
|
//#[cfg(feature = "std")]
|
||||||
|
dict_impl!(HashMap<K: Eq + Hash, V, H: BuildHasher>);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
macro_rules! deref_impl {
|
||||||
|
(
|
||||||
|
$(#[doc = $doc:tt])*
|
||||||
|
<$($desc:tt)+
|
||||||
|
) => {
|
||||||
|
$(#[doc = $doc])*
|
||||||
|
impl <$($desc)+ {
|
||||||
|
#[inline]
|
||||||
|
fn serialize<S>(&self, serializer: S) -> Result<(), S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
(**self).serialize(serializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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"))]
|
||||||
|
deref_impl!(<T: ?Sized> Serialize for Box<T> where T: Serialize);
|
65
sehn/src/se/mod.rs
Normal file
65
sehn/src/se/mod.rs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
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;
|
||||||
|
|
||||||
|
/// The write function used with serialization.
|
||||||
|
fn write(&mut self, buf: &[u8]) -> Result<(), Self::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Serialize {
|
||||||
|
fn serialize<S>(&self, s: S) -> Result<(), S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Serializer: Sized {
|
||||||
|
type Error: Error;
|
||||||
|
|
||||||
|
fn serialize_any<T>(self, any: T) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
T: Serialize
|
||||||
|
{
|
||||||
|
any.serialize(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn serialize_real_u8(self, real: u8) -> Result<(), Self::Error>;
|
||||||
|
fn serialize_real_u16(self, real: u16) -> Result<(), Self::Error>;
|
||||||
|
fn serialize_real_u32(self, real: u32) -> Result<(), Self::Error>;
|
||||||
|
fn serialize_real_u64(self, real: u64) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
|
fn serialize_real_i8(self, real: i8) -> Result<(), Self::Error>;
|
||||||
|
fn serialize_real_i16(self, real: i16) -> Result<(), Self::Error>;
|
||||||
|
fn serialize_real_i32(self, real: i32) -> Result<(), Self::Error>;
|
||||||
|
fn serialize_real_i64(self, real: i64) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
|
fn serialize_real_f32(self, real: f32) -> Result<(), Self::Error>;
|
||||||
|
fn serialize_real_f64(self, real: f64) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
|
fn serialize_atom<'a>(self, atom: &'a str) -> Result<(), Self::Error>;
|
||||||
|
fn serialize_text<'a>(self, text: &'a str) -> Result<(), Self::Error>;
|
||||||
|
|
||||||
|
fn serialize_multiline_text<'a, M>(self, lines: M) -> Result<(), Self::Error>
|
||||||
|
where M: IntoIterator<Item = &'a str>;
|
||||||
|
|
||||||
|
fn serialize_unit<'a, V>(self, name: &'a str, value: V) -> Result<(), Self::Error>
|
||||||
|
where V: Serialize;
|
||||||
|
|
||||||
|
fn serialize_dict<K, V, D>(self, dict: D) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
K: Serialize,
|
||||||
|
V: Serialize,
|
||||||
|
D: IntoIterator<Item = (K, V)>;
|
||||||
|
|
||||||
|
fn serialize_list<V, L>(self, list: L) -> Result<(), Self::Error>
|
||||||
|
where
|
||||||
|
V: Serialize,
|
||||||
|
L: IntoIterator<Item = V>;
|
||||||
|
}
|
5
sehn/src/utils/mod.rs
Normal file
5
sehn/src/utils/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mod to_string;
|
||||||
|
mod string_writer;
|
||||||
|
|
||||||
|
pub use self::to_string::*;
|
||||||
|
pub use self::string_writer::*;
|
37
sehn/src/utils/string_writer.rs
Normal file
37
sehn/src/utils/string_writer.rs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
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(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
|
||||||
|
self.buf.extend_from_slice(bytes);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
17
sehn/src/utils/to_string.rs
Normal file
17
sehn/src/utils/to_string.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
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())
|
||||||
|
}
|
3
sehn/src/value/mod.rs
Normal file
3
sehn/src/value/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mod tag;
|
||||||
|
|
||||||
|
pub use self::tag::*;
|
23
sehn/src/value/tag.rs
Normal file
23
sehn/src/value/tag.rs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
use crate::se::{Serializer, Serialize};
|
||||||
|
|
||||||
|
pub struct Tag<'a, T> {
|
||||||
|
name: &'a str,
|
||||||
|
value: T
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Tag<'a, T> {
|
||||||
|
pub fn new(name: &'a str, value: T) -> Self {
|
||||||
|
Self { name, value }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, T> Serialize for Tag<'a, T>
|
||||||
|
where
|
||||||
|
T: Serialize
|
||||||
|
{
|
||||||
|
fn serialize<S>(&self, s: S) -> Result<(), S::Error>
|
||||||
|
where S: Serializer
|
||||||
|
{
|
||||||
|
s.serialize_unit(self.name, &self.value)
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user