diff --git a/Cargo.toml b/Cargo.toml index 67aa90b..89d0b93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace] members = [ - "sehn", + "sehn-serde", "sehn-std" ] \ No newline at end of file diff --git a/sehn/Cargo.toml b/sehn/Cargo.toml deleted file mode 100644 index 97f4705..0000000 --- a/sehn/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "sehn" -version = "0.1.0" -authors = ["avitex "] -edition = "2018" - -[dependencies] -itoa = "0.4" -dtoa = "0.4" -serde = "1.0" -serde_derive = "1.0" -error-chain = "0.12" \ No newline at end of file diff --git a/sehn/examples/basic.rs b/sehn/examples/basic.rs deleted file mode 100644 index 09ad88a..0000000 --- a/sehn/examples/basic.rs +++ /dev/null @@ -1,19 +0,0 @@ -use serde_derive::Serialize; - -#[derive(Serialize)] -pub struct UserType(T); - -#[derive(Serialize)] -pub struct Test<'a> { - foo: &'a str, - bar: UserType<&'a str> -} - -fn main() { - let val = Test { - foo: "hello", - bar: UserType("world") - }; - - println!("{}", sehn::to_string(&val).unwrap()); -} diff --git a/sehn/src/de/error.rs b/sehn/src/de/error.rs deleted file mode 100644 index 10b67b9..0000000 --- a/sehn/src/de/error.rs +++ /dev/null @@ -1,32 +0,0 @@ -use error_chain::{ - error_chain, - error_chain_processing, - impl_error_chain_processed, - impl_error_chain_kind, - impl_extract_backtrace -}; - -error_chain! { - errors { - Eof { - description("unexpected end of input") - } - NestingLimit { - description("nesting limit reached") - } - Unexpected(c: char) { - description("unexpected character") - display("unexpected character: '{}'", c) - } - Message(t: String) { - description(t) - display("internal error: '{}'", t) - } - } -} - -impl serde::de::Error for Error { - fn custom(msg: T) -> Self { - ErrorKind::Message(msg.to_string()).into() - } -} \ No newline at end of file diff --git a/sehn/src/de/mod.rs b/sehn/src/de/mod.rs deleted file mode 100644 index 637f3a9..0000000 --- a/sehn/src/de/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod error; - -pub use self::error::*; \ No newline at end of file diff --git a/sehn/src/error.rs b/sehn/src/error.rs deleted file mode 100644 index f36b151..0000000 --- a/sehn/src/error.rs +++ /dev/null @@ -1,14 +0,0 @@ -use error_chain::{ - error_chain, - error_chain_processing, - impl_error_chain_processed, - impl_error_chain_kind, - impl_extract_backtrace -}; - -error_chain! { - links { - Serialization(crate::ser::Error, crate::ser::ErrorKind); - Deserialization(crate::de::Error, crate::de::ErrorKind); - } -} \ No newline at end of file diff --git a/sehn/src/lib.rs b/sehn/src/lib.rs deleted file mode 100644 index e68e54e..0000000 --- a/sehn/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -mod error; - -pub mod de; -pub mod ser; -pub mod syntax; -pub mod value; - -//pub use self::de::{from_str, Deserializer}; -pub use self::ser::{to_string, Serializer}; -pub use self::error::{Error, ErrorKind, Result}; - -mod private { - pub trait Sealed {} -} \ No newline at end of file diff --git a/sehn/src/ser/config.rs b/sehn/src/ser/config.rs deleted file mode 100644 index a3473f0..0000000 --- a/sehn/src/ser/config.rs +++ /dev/null @@ -1,33 +0,0 @@ -use super::{Format, StandardFormat}; - -pub trait Config { - type Format: Format; - - /// `struct $name { ..., ... }` - const TAG_STRUCTS: bool = false; - /// `struct $name ( ... )` - const TAG_NEWTYPE_STRUCTS: bool = false; - /// `struct $name ( ..., ... )` - const TAG_TUPLE_STRUCTS: bool = false; - /// `enum { $name ( ..., ... ) }` - const TAG_TUPLE_VARIANTS: bool = false; - /// `enum { $name { ..., ... } }` - const TAG_STRUCT_VARIANTS: bool = false; - /// `struct $name` - const UNIT_STRUCT_TO_KIND: bool = false; - /// The initial size of the stack used for - /// checking if a value was tagged or not - /// as it ascends nesting. - const INITIAL_TAG_STACK_SIZE: usize = 265; - /// Disable string escaping (DANGEROUS!) - const DISABLE_STRING_ESCAPING: bool = false; -} - -pub struct DefaultConfig; - -impl Config for DefaultConfig { - type Format = StandardFormat; - - const UNIT_STRUCT_TO_KIND: bool = true; - const TAG_NEWTYPE_STRUCTS: bool = true; -} \ No newline at end of file diff --git a/sehn/src/ser/error.rs b/sehn/src/ser/error.rs deleted file mode 100644 index c0b4354..0000000 --- a/sehn/src/ser/error.rs +++ /dev/null @@ -1,25 +0,0 @@ -use error_chain::{ - error_chain, - error_chain_processing, - impl_error_chain_processed, - impl_error_chain_kind, - impl_extract_backtrace -}; - -error_chain! { - foreign_links { - Io(::std::io::Error); - } - errors { - Message(t: String) { - description(t) - display("internal error: '{}'", t) - } - } -} - -impl serde::ser::Error for Error { - fn custom(msg: T) -> Self { - ErrorKind::Message(msg.to_string()).into() - } -} \ No newline at end of file diff --git a/sehn/src/ser/format/deterministic.rs b/sehn/src/ser/format/deterministic.rs deleted file mode 100644 index cd4168c..0000000 --- a/sehn/src/ser/format/deterministic.rs +++ /dev/null @@ -1,12 +0,0 @@ -use super::{Format, RealFormat, WriteReal}; - -pub struct DeterministicRealFormat; - -impl RealFormat for DeterministicRealFormat {} - -pub struct DeterministicFormat; - -impl Format for DeterministicFormat { - type Engine = (); - type RealFormat = DeterministicRealFormat; -} \ No newline at end of file diff --git a/sehn/src/ser/format/fast_real.rs b/sehn/src/ser/format/fast_real.rs deleted file mode 100644 index bbbd581..0000000 --- a/sehn/src/ser/format/fast_real.rs +++ /dev/null @@ -1,30 +0,0 @@ -use std::io::Write; -use crate::ser::error::Result; -use super::{RealFormat, WriteReal}; - -macro_rules! impl_write_real_for_fast_format { - ($($prim:ident with $xtoa:ident),*) => { - $(impl WriteReal<$prim> for FastRealFormat { - fn write_real(w: &mut W, r: $prim) -> Result<()> { - $xtoa::write(w, r).map(|_| ()).map_err(|e| e.into()) - } - })* - } -} - -pub struct FastRealFormat; - -impl_write_real_for_fast_format!( - i8 with itoa, - i16 with itoa, - i32 with itoa, - i64 with itoa, - u8 with itoa, - u16 with itoa, - u32 with itoa, - u64 with itoa, - f32 with dtoa, - f64 with dtoa -); - -impl RealFormat for FastRealFormat {} \ No newline at end of file diff --git a/sehn/src/ser/format/mod.rs b/sehn/src/ser/format/mod.rs deleted file mode 100644 index 595e3d5..0000000 --- a/sehn/src/ser/format/mod.rs +++ /dev/null @@ -1,40 +0,0 @@ -mod fast_real; -mod pretty; -mod standard; -//mod deterministic; - -use super::{Write, Result}; - -pub use self::fast_real::*; -pub use self::pretty::*; -pub use self::standard::*; -//pub use self::deterministic::*; - -pub trait WriteReal { - fn write_real(w: &mut W, i: T) -> Result<()>; -} - -pub trait RealFormat: - WriteReal + WriteReal + - WriteReal + WriteReal + - WriteReal + WriteReal + - WriteReal + WriteReal + - WriteReal + WriteReal {} - -pub trait FormatEngine: Default { - fn mark_delim(&mut self, _d: u8) {} -} - -impl FormatEngine for () {} - -pub trait Format { - type Engine: FormatEngine; - type RealFormat: RealFormat; - - #[inline] - fn write(_e: &mut Self::Engine, w: &mut Write, bytes: &[u8]) -> Result<()> { - // Passthrough - w.write(bytes)?; - Ok(()) - } -} \ No newline at end of file diff --git a/sehn/src/ser/format/pretty.rs b/sehn/src/ser/format/pretty.rs deleted file mode 100644 index ca44cb6..0000000 --- a/sehn/src/ser/format/pretty.rs +++ /dev/null @@ -1,117 +0,0 @@ -use std::io::Write; -use std::marker::PhantomData; - -use crate::syntax::*; - -use crate::ser::error::Result; -use super::{Format, FormatEngine, FastRealFormat}; - -pub type DefaultPrettyFormat = PrettyFormat; - -pub trait IndentStyle { - const LEVEL: &'static [u8]; -} - -pub struct OneTab; -pub struct TwoSpaces; -pub struct FourSpaces; - -impl IndentStyle for OneTab { - const LEVEL: &'static [u8] = &[ - WHITESPACE_TAB_CHAR - ]; -} - -impl IndentStyle for TwoSpaces { - const LEVEL: &'static [u8] = &[ - WHITESPACE_SPACE_CHAR, - WHITESPACE_SPACE_CHAR - ]; -} - -impl IndentStyle for FourSpaces { - const LEVEL: &'static [u8] = &[ - WHITESPACE_SPACE_CHAR, - WHITESPACE_SPACE_CHAR, - WHITESPACE_SPACE_CHAR, - WHITESPACE_SPACE_CHAR - ]; -} - -pub struct PrettyFormat { - indent_style: PhantomData -} - -impl PrettyFormat { - fn style_before_write(e: &mut PrettyFormatEngine, w: &mut Write) -> Result<()> { - match e.delim { - DICT_END_CHAR | LIST_END_CHAR => { - e.level -= 1; - Self::write_newline(w)?; - Self::write_indentation(e, w)?; - }, - _ => () - } - Ok(()) - } - - fn style_after_write(e: &mut PrettyFormatEngine, w: &mut Write) -> Result<()> { - match e.delim { - DICT_START_CHAR | LIST_START_CHAR => { - e.level += 1; - Self::write_newline(w)?; - Self::write_indentation(e, w)?; - }, - DICT_KV_SEPARATOR_CHAR => { - Self::write_space(w)?; - }, - COMMA_CHAR => { - Self::write_newline(w)?; - Self::write_indentation(e, w)?; - }, - _ => () - } - e.delim = 0; - Ok(()) - } - - fn write_space(w: &mut Write) -> Result<()> { - w.write(&[WHITESPACE_SPACE_CHAR])?; - Ok(()) - } - - fn write_newline(w: &mut Write) -> Result<()> { - w.write(&[NEWLINE_LF_CHAR])?; - Ok(()) - } - - fn write_indentation(e: &mut PrettyFormatEngine, w: &mut Write) -> Result<()> { - for _ in 0..e.level { - w.write(I::LEVEL)?; - } - Ok(()) - } -} - -#[derive(Default)] -pub struct PrettyFormatEngine { - level: usize, - delim: u8 -} - -impl FormatEngine for PrettyFormatEngine { - fn mark_delim(&mut self, delim: u8) { - self.delim = delim; - } -} - -impl Format for PrettyFormat { - type Engine = PrettyFormatEngine; - type RealFormat = FastRealFormat; - - fn write(e: &mut PrettyFormatEngine, w: &mut Write, bytes: &[u8]) -> Result<()> { - Self::style_before_write(e, w)?; - w.write(bytes)?; - Self::style_after_write(e, w) - } -} \ No newline at end of file diff --git a/sehn/src/ser/format/standard.rs b/sehn/src/ser/format/standard.rs deleted file mode 100644 index 2f55d75..0000000 --- a/sehn/src/ser/format/standard.rs +++ /dev/null @@ -1,8 +0,0 @@ -use super::{Format, FastRealFormat}; - -pub struct StandardFormat; - -impl Format for StandardFormat { - type Engine = (); - type RealFormat = FastRealFormat; -} \ No newline at end of file diff --git a/sehn/src/ser/macros.rs b/sehn/src/ser/macros.rs deleted file mode 100644 index c2f01aa..0000000 --- a/sehn/src/ser/macros.rs +++ /dev/null @@ -1,35 +0,0 @@ -macro_rules! impl_ser_real { - ($f:ident, $t:ident) => { - fn $f(self, v: $t) -> Result<()> { - self.write_real::<$t>(v) - } - } -} - -macro_rules! tag_start { - ($s:expr, $opt_enabled:expr, $name:expr) => { - if $opt_enabled { - if $name.is_empty() { - $s.tag_stack.push(false); - } else { - $s.write_bytes($name.as_bytes())?; - $s.write_delim(syntax::TAG_START_CHAR)?; - $s.tag_stack.push(true); - } - } - } -} - -macro_rules! tag_end { - ($s:expr, $opt_enabled:expr) => { - if $opt_enabled { - if $s.tag_stack.pop().expect("stack tag value") { - $s.write_delim(syntax::TAG_END_CHAR) - } else { - Ok(()) - } - } else { - Ok(()) - } - } -} \ No newline at end of file diff --git a/sehn/src/ser/mod.rs b/sehn/src/ser/mod.rs deleted file mode 100644 index 62d5901..0000000 --- a/sehn/src/ser/mod.rs +++ /dev/null @@ -1,491 +0,0 @@ -mod error; -mod string_writer; -mod format; -mod config; -#[macro_use] -mod macros; - -use std::io::Write; -use std::marker::PhantomData; -use serde::ser::{self, Serialize}; -use crate::syntax; - -pub use self::format::*; -pub use self::config::*; -pub use self::string_writer::StringWriter; -pub use self::error::{Error, ErrorKind, Result}; - -pub struct Serializer { - out: W, - tag_stack: Vec, - first_element: bool, - config: PhantomData, - format_engine: ::Engine -} - -impl Serializer { - #[inline] - fn set_first_element(&mut self) { - self.first_element = true; - } - - #[inline] - fn check_not_first_element(&mut self) -> bool { - if self.first_element { - self.first_element = false; - false - } else { - true - } - } - - #[inline] - fn write_delim(&mut self, delim: u8) -> Result<()> { - self.format_engine.mark_delim(delim); - self.write_bytes(&[delim]) - } - - #[inline] - fn write_bytes(&mut self, bytes: &[u8]) -> Result<()> { - ::write::(&mut self.format_engine, &mut self.out, bytes) - } - - #[inline] - fn write_real(&mut self, r: R) -> Result<()> where ::RealFormat: WriteReal { - ::RealFormat::write_real::(&mut self.out, r) - } -} - -pub fn to_string_with_config(value: &T) -> Result -where - T: Serialize, - C: Config -{ - let mut serializer = Serializer { - out: StringWriter::new(), - config: PhantomData::, - tag_stack: Vec::with_capacity(C::INITIAL_TAG_STACK_SIZE), - first_element: false, - format_engine: Default::default() - }; - value.serialize(&mut serializer)?; - Ok(serializer.out.to_string().expect("valid utf8")) -} - -pub fn to_string(value: &T) -> Result -where - T: Serialize, -{ - to_string_with_config::(value) -} - -impl<'a, W: Write, C: Config> ser::Serializer for &'a mut Serializer { - type Ok = (); - type Error = Error; - - type SerializeSeq = Self; - type SerializeTuple = Self; - type SerializeTupleStruct = Self; - type SerializeTupleVariant = Self; - type SerializeMap = Self; - type SerializeStruct = Self; - type SerializeStructVariant = Self; - - impl_ser_real!(serialize_i8, i8); - impl_ser_real!(serialize_i16, i16); - impl_ser_real!(serialize_i32, i32); - impl_ser_real!(serialize_i64, i64); - impl_ser_real!(serialize_u8, u8); - impl_ser_real!(serialize_u16, u16); - impl_ser_real!(serialize_u32, u32); - impl_ser_real!(serialize_u64, u64); - impl_ser_real!(serialize_f32, f32); - impl_ser_real!(serialize_f64, f64); - - fn serialize_char(self, v: char) -> Result<()> { - let mut char_bytes: [u8; 4] = unsafe { std::mem::uninitialized() }; - let char_str = v.encode_utf8(&mut char_bytes[..]); - self.serialize_str(&char_str) - } - - fn serialize_str(self, v: &str) -> Result<()> { - self.write_delim(syntax::TEXT_CHAR)?; - if C::DISABLE_STRING_ESCAPING { - self.write_bytes(v.as_bytes())?; - } else { - // TODO: Escape characters - self.write_bytes(v.as_bytes())?; - } - self.write_delim(syntax::TEXT_CHAR) - } - - fn serialize_bool(self, v: bool) -> Result<()> { - self.write_bytes( - if v { - syntax::BOOLEAN_TRUE_KEYWORD - } else { - syntax::BOOLEAN_FALSE_KEYWORD - } - ) - } - - fn serialize_bytes(self, v: &[u8]) -> Result<()> { - use serde::ser::SerializeSeq; - let mut seq = self.serialize_seq(Some(v.len()))?; - for byte in v { - seq.serialize_element(byte)?; - } - seq.end() - } - - fn serialize_some(self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - value.serialize(self) - } - - fn serialize_none(self) -> Result<()> { - self.serialize_unit() - } - - fn serialize_unit(self) -> Result<()> { - self.write_bytes(b"none") - } - - fn serialize_unit_struct(self, name: &'static str) -> Result<()> { - if C::UNIT_STRUCT_TO_KIND { - self.write_bytes(name.as_bytes()) - } else { - Ok(()) - } - } - - fn serialize_unit_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - ) -> Result<()> { - self.serialize_str(variant) - } - - fn serialize_newtype_struct( - self, - name: &'static str, - value: &T, - ) -> Result<()> - where - T: ?Sized + Serialize, - { - tag_start!(self, C::TAG_NEWTYPE_STRUCTS, name); - value.serialize(&mut *self)?; - tag_end!(self, C::TAG_NEWTYPE_STRUCTS) - } - - fn serialize_newtype_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - value: &T, - ) -> Result<()> - where - T: ?Sized + Serialize, - { - self.write_delim(syntax::DICT_START_CHAR)?; - variant.serialize(&mut *self)?; - self.write_delim(syntax::DICT_KV_SEPARATOR_CHAR)?; - value.serialize(&mut *self)?; - self.write_delim(syntax::DICT_END_CHAR) - } - - fn serialize_seq(self, _len: Option) -> Result { - self.write_delim(syntax::LIST_START_CHAR)?; - self.set_first_element(); - Ok(self) - } - - fn serialize_tuple(self, len: usize) -> Result { - self.serialize_seq(Some(len)) - } - - fn serialize_tuple_struct( - self, - name: &'static str, - len: usize, - ) -> Result { - tag_start!(self, C::TAG_TUPLE_STRUCTS, name); - self.serialize_seq(Some(len)) - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - _len: usize, - ) -> Result { - tag_start!(self, C::TAG_TUPLE_VARIANTS, variant); - self.write_delim(syntax::DICT_START_CHAR)?; - variant.serialize(&mut *self)?; - self.write_delim(syntax::DICT_KV_SEPARATOR_CHAR)?; - self.write_delim(syntax::LIST_START_CHAR)?; - self.set_first_element(); - Ok(self) - } - - fn serialize_map(self, _len: Option) -> Result { - self.write_delim(syntax::DICT_START_CHAR)?; - self.set_first_element(); - Ok(self) - } - - fn serialize_struct( - self, - name: &'static str, - len: usize, - ) -> Result { - tag_start!(self, C::TAG_STRUCTS, name); - self.serialize_map(Some(len))?; - self.set_first_element(); - Ok(self) - } - - fn serialize_struct_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - _len: usize, - ) -> Result { - tag_start!(self, C::TAG_STRUCT_VARIANTS, variant); - self.write_delim(syntax::DICT_START_CHAR)?; - variant.serialize(&mut *self)?; - self.write_delim(syntax::DICT_KV_SEPARATOR_CHAR)?; - self.write_delim(syntax::DICT_START_CHAR)?; - self.set_first_element(); - Ok(self) - } -} - -impl<'a, W: Write, C: Config> ser::SerializeSeq for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if self.check_not_first_element() { - self.write_delim(syntax::LIST_SEPARATOR_CHAR)?; - } - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.write_delim(syntax::LIST_END_CHAR) - } -} - -impl<'a, W: Write, C: Config> ser::SerializeTuple for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if self.check_not_first_element() { - self.write_delim(syntax::LIST_SEPARATOR_CHAR)?; - } - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.write_delim(syntax::LIST_END_CHAR) - } -} - -impl<'a, W: Write, C: Config> ser::SerializeTupleStruct for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if self.check_not_first_element() { - self.write_delim(syntax::LIST_SEPARATOR_CHAR)?; - } - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.write_delim(syntax::LIST_END_CHAR)?; - tag_end!(self, C::TAG_TUPLE_STRUCTS) - } -} - -impl<'a, W: Write, C: Config> ser::SerializeTupleVariant for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if self.check_not_first_element() { - self.write_delim(syntax::LIST_SEPARATOR_CHAR)?; - } - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.write_delim(syntax::LIST_END_CHAR)?; - self.write_delim(syntax::DICT_END_CHAR)?; - tag_end!(self, C::TAG_TUPLE_VARIANTS) - } -} - - -impl<'a, W: Write, C: Config> ser::SerializeMap for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_key(&mut self, key: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if self.check_not_first_element() { - self.write_delim(syntax::DICT_PAIR_SEPARATOR_CHAR)?; - } - key.serialize(&mut **self) - } - - fn serialize_value(&mut self, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - self.write_delim(syntax::DICT_KV_SEPARATOR_CHAR)?; - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.write_delim(syntax::DICT_END_CHAR) - } -} - -impl<'a, W: Write, C: Config> ser::SerializeStruct for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if self.check_not_first_element() { - self.write_delim(syntax::DICT_PAIR_SEPARATOR_CHAR)?; - } - key.serialize(&mut **self)?; - self.write_delim(syntax::DICT_KV_SEPARATOR_CHAR)?; - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.write_delim(syntax::DICT_END_CHAR)?; - tag_end!(self, C::TAG_STRUCTS) - } -} - -impl<'a, W: Write, C: Config> ser::SerializeStructVariant for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> - where - T: ?Sized + Serialize, - { - if self.check_not_first_element() { - self.write_delim(syntax::DICT_PAIR_SEPARATOR_CHAR)?; - } - key.serialize(&mut **self)?; - self.write_delim(syntax::DICT_KV_SEPARATOR_CHAR)?; - value.serialize(&mut **self) - } - - fn end(self) -> Result<()> { - self.write_delim(syntax::DICT_END_CHAR)?; - self.write_delim(syntax::DICT_END_CHAR)?; - tag_end!(self, C::TAG_STRUCT_VARIANTS) - } -} - -//////////////////////////////////////////////////////////////////////////////// - -#[test] -fn test_struct() { - #[derive(Serialize)] - struct Test { - int: u32, - seq: Vec<&'static str>, - } - - let test = Test { - int: 1, - seq: vec!["a", "b"], - }; - let expected = r#"{"int":1,"seq":["a","b"]}"#; - assert_eq!(to_string(&test).unwrap(), expected); -} - -#[test] -fn test_enum() { - #[derive(Serialize)] - enum E { - Unit, - Newtype(u32), - Tuple(u32, u32), - Struct { a: u32 }, - } - - let u = E::Unit; - let expected = r#""Unit""#; - assert_eq!(to_string(&u).unwrap(), expected); - - let n = E::Newtype(1); - let expected = r#"{"Newtype":1}"#; - assert_eq!(to_string(&n).unwrap(), expected); - - let t = E::Tuple(1, 2); - let expected = r#"{"Tuple":[1,2]}"#; - assert_eq!(to_string(&t).unwrap(), expected); - - let s = E::Struct { a: 1 }; - let expected = r#"{"Struct":{"a":1}}"#; - assert_eq!(to_string(&s).unwrap(), expected); -} - -#[test] -fn test_simple() { - #[derive(Serialize)] - #[serde(rename = "Test/Unit")] - struct TestUnitStruct; - - #[derive(Serialize)] - #[serde(rename = "Test/NewtypeStruct")] - struct TestNewtypeStruct(i8); - - #[derive(Serialize)] - #[serde(rename = "")] - struct TestTransparentUnitStruct; - - #[derive(Serialize)] - #[serde(transparent)] - struct TestTransparentNewtypeStruct(i8); - - assert_eq!(to_string(&TestUnitStruct).unwrap(), "Test/Unit"); - assert_eq!(to_string(&TestNewtypeStruct(1)).unwrap(), "Test/NewtypeStruct(1)"); - assert_eq!(to_string(&TestTransparentUnitStruct).unwrap(), ""); - assert_eq!(to_string(&TestTransparentNewtypeStruct(1)).unwrap(), "1"); -} \ No newline at end of file diff --git a/sehn/src/ser/string_writer.rs b/sehn/src/ser/string_writer.rs deleted file mode 100644 index c5a1e69..0000000 --- a/sehn/src/ser/string_writer.rs +++ /dev/null @@ -1,29 +0,0 @@ -use std::io; -use std::string::FromUtf8Error; - -pub struct StringWriter { - buf: Vec -} - -impl StringWriter { - pub fn new() -> Self { - Self { - buf: Vec::new() - } - } - - pub fn to_string(self) -> Result { - String::from_utf8(self.buf) - } -} - -impl io::Write for StringWriter { - fn write(&mut self, bytes: &[u8]) -> io::Result { - self.buf.extend_from_slice(bytes); - Ok(bytes.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Ok(()) - } -} \ No newline at end of file diff --git a/sehn/src/syntax/mod.rs b/sehn/src/syntax/mod.rs deleted file mode 100644 index 463e9e2..0000000 --- a/sehn/src/syntax/mod.rs +++ /dev/null @@ -1,115 +0,0 @@ -use std::fmt::{self, Display}; - -// Shared -pub const COMMA_CHAR: u8 = b','; - -// Newline -pub const NEWLINE_LF_CHAR: u8 = b'\n'; -pub const NEWLINE_CR_CHAR: u8 = b'\r'; - -// Whitespace -pub const WHITESPACE_TAB_CHAR: u8 = b'\t'; -pub const WHITESPACE_SPACE_CHAR: u8 = b' '; - -// Real -pub const REAL_ZERO_CHAR: u8 = b'0'; -pub const REAL_NEG_CHAR: u8 = b'-'; -pub const REAL_SIGEXP_SEPARATOR_CHAR: u8 = b'e'; - -// Text -pub const TEXT_CHAR: u8 = b'"'; -pub const MULTI_TEXT_CHAR: u8 = b'`'; - -// Kind -pub const KIND_NS_SEPARATOR_CHAR: u8 = b'/'; - -// Tag -pub const TAG_START_CHAR: u8 = b'('; -pub const TAG_END_CHAR: u8 = b')'; - -// Dict -pub const DICT_START_CHAR: u8 = b'{'; -pub const DICT_END_CHAR: u8 = b'}'; -pub const DICT_KV_SEPARATOR_CHAR: u8 = b':'; -pub const DICT_PAIR_SEPARATOR_CHAR: u8 = COMMA_CHAR; - -// List -pub const LIST_START_CHAR: u8 = b'['; -pub const LIST_END_CHAR: u8 = b']'; -pub const LIST_SEPARATOR_CHAR: u8 = COMMA_CHAR; - -// Comment -pub const COMMENT_CHAR: u8 = b'#'; - -// Boolean -pub const BOOLEAN_TRUE_KEYWORD: &[u8] = b"true"; -pub const BOOLEAN_FALSE_KEYWORD: &[u8] = b"false"; - -#[derive(Clone, Debug, PartialEq)] -pub enum Token { - // Non-value types - Newline, - Whitespace, - Comment, - AlphaLower, - AlphaUpper, - // Kinds - KindNsSep, - // Real - RealMinus, - RealZero, - RealNumeric, - RealSigExpSep, - // Text - TextStart, - TextEnd, - MultiTextStart, - MultiTextEnd, - // Structures - TagStart, - TagEnd, - DictStart, - DictEnd, - DictKvSep, - DictPairSep, - ListStart, - ListEnd, - ListSep -} - - -impl Token { - pub fn description(&self) -> &'static str { - match self { - Token::Newline => "newline ''", - Token::Whitespace => "whitespace ''", - Token::Comment => "comment '#'", - Token::AlphaLower => "alpha-lower ''", - Token::AlphaUpper => "alpha-upper ''", - Token::KindNsSep => "kind ns separator '/'", - Token::RealMinus => "minus '-'", - Token::RealZero => "zero '0'", - Token::RealNumeric => "number '<0-9>'", - Token::RealSigExpSep => "sig-exp separator 'e'", - Token::TextStart => "text '\"'", - Token::TextEnd => "text end '\"'", - Token::MultiTextStart => "multi text '`'", - Token::MultiTextEnd => "multi text end '`'", - Token::TagStart => "tag '('", - Token::TagEnd => "tag end ')'", - Token::DictStart => "dict '{'", - Token::DictEnd => "dict end '}'", - Token::DictKvSep => "dict kv separator ':'", - Token::DictPairSep => "dict pair separator ','", - Token::ListStart => "list '['", - Token::ListEnd => "list end ']'", - Token::ListSep => "list separator ','", - } - } -} - -impl Display for Token { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - write!(fmt, "{}", self.description()) - } -} diff --git a/sehn/src/syntax/parser.rs b/sehn/src/syntax/parser.rs deleted file mode 100644 index 583dece..0000000 --- a/sehn/src/syntax/parser.rs +++ /dev/null @@ -1,156 +0,0 @@ -pub struct Mark { - i: usize -} - -pub trait Read<'a> { - // Per char reading. - fn next_char(&mut self) -> Result; - fn peek_char(&mut self) -> Result; - - // Sectioning off data. - fn mark(&self) -> Mark; - /// Returns reference to the section. - fn from_mark(&mut self, m: Mark) -> &'a str; - - /// Attempt to enter a new level of nesting. - fn enter_nest(&mut self) -> Result<()>; - /// Leave a nest. - fn leave_nest(&mut self); - - /// Called when the parser passes a line. - fn passed_line(&mut self); -} - -//pub trait Visitor {} - -pub struct Parser<'a, R: Read + 'a> { - r: &'a mut R -} - -impl<'a, R: Read> Parser<'a, R> { - fn parse_value(&mut self) -> Result<()> { - loop { - match self.r.next() { - Some(c) => match c { - COMMENT_CHAR => if !self.skip_to_next_line() { - return Ok(()) - }, - // Whitespace - LF_CHAR => self.r.mark_line(), - CR_CHAR => { - self.skip_char(LF_CHAR); - self.r.mark_line(); - }, - SPACE_CHAR | TAB_CHAR => { - self.skip_one(); - }, - // Values - DICT_START_CHAR => return self.parse_dict(), - LIST_START_CHAR => return self.parse_list(), - TEXT_DELIM_CHAR => return self.parse_text(), - MULTI_TEXT_DELIM_CHAR => return self.parse_multi_text(), - REAL_NEG_CHAR => return self.parse_real_negative(), - REAL_ZERO_CHAR => return self.parse_real_positive_decimal(), - '1'...'9' => return self.parse_real_positive_int(), - 'a'...'z' => return self.parse_initial_lowercase(c), - 'A'...'Z' => return self.parse_initial_uppercase(c), - // Unexpected - c => return Some(ParseError::Unexpected(c)) - }, - None => return Ok(()) - } - } - } - - #[inline] - fn skip_one(&mut self) -> bool { - match self.r.next() { - Some(_) => true, - None => false - } - } - - #[inline] - fn skip_char(&mut self, c: char) -> bool { - match self.r.peek() { - Some(peeked_c) if c == peeked_c => self.skip_one(), - Some(_) => true, - _ => false - } - } - - #[inline] - fn skip_to_next_line(&mut self) -> bool { - loop { - match self.r.next() { - Some(LF_CHAR) => { - self.r.mark_line(); - return true - }, - Some(CR_CHAR) => { - if self.skip_char(LF_CHAR) { - self.r.mark_line(); - return true - } else { - return false - } - }, - Some(_) => return true, - None => return false - } - } - } - - #[inline] - fn parse_dict(&mut self) -> Option { - if self.r.enter_ctx() { - None - } else { - Some(ParseError::NestingLimit) - } - } - - #[inline] - fn parse_list(&mut self) -> Option { - if self.r.enter_ctx() { - None - } else { - Some(ParseError::NestingLimit) - } - } - - #[inline] - fn parse_text(&mut self) -> Option { - None - } - - #[inline] - fn parse_multi_text(&mut self) -> Option { - None - } - - #[inline] - fn parse_real_negative(&mut self) -> Option { - None - } - - #[inline] - fn parse_real_positive_int(&mut self) -> Option { - None - } - - #[inline] - fn parse_real_positive_decimal(&mut self) -> Option { - None - } - - #[inline] - fn parse_initial_lowercase(&mut self, c: char) -> Option { - None - } - - #[inline] - fn parse_initial_uppercase(&mut self, c: char) -> Option { - None - } -} \ No newline at end of file diff --git a/sehn/src/value/mod.rs b/sehn/src/value/mod.rs deleted file mode 100644 index e69de29..0000000 diff --git a/sehn/src/value/real/mod.rs b/sehn/src/value/real/mod.rs deleted file mode 100644 index 251f42c..0000000 --- a/sehn/src/value/real/mod.rs +++ /dev/null @@ -1,24 +0,0 @@ -//mod sig_exp; -//mod str_int; - -// //pub use self::sig_exp::*; -// pub use self::str_int::*; - -// pub type PrimaryInt = i64; -// pub type PrimaryNat = u64; - -// #[derive(Debug, PartialEq)] -// pub enum ToPrimitiveError { -// Overflow, -// Underflow -//} - - -// pub enum Real { -// /// Zero to the natural primitive max. -// Nat(PrimitiveNatValue), -// /// Negative to the integer primitive min. -// Int(PrimitiveIntValue), -// /// SigExp -// SigExp(SigExp) -// } \ No newline at end of file diff --git a/sehn/src/value/real/sig_exp.rs b/sehn/src/value/real/sig_exp.rs deleted file mode 100644 index 8b50b20..0000000 --- a/sehn/src/value/real/sig_exp.rs +++ /dev/null @@ -1,125 +0,0 @@ -use super::{ - StrInt, - StringInt, - PrimitiveInt, - PrimitiveIntValue -}; - -pub struct StrSigExp<'a> { - sig: StrInt<'a>, - exp: StrInt<'a> -} - -impl<'a> StrSigExp<'a> { - #[inline] - pub fn from_parts(sig: StrInt<'a>, exp: StrInt<'a>) -> Self { - Self { - sig, - exp - } - } -} - -impl<'a> From> for SigExp { - fn from(raw: StrSigExp<'a>) -> SigExp { - let raw_exp_digits = raw.exp.digits(); - - if raw_exp_digits.len() <= I16_MAX_DIGITS { - raw_exp_digits - } - - - if let PrimitiveInt(sig) = PrimitiveInt::from_str_int(raw.sig) { - let raw_exp_digits = raw.exp.digits(); - - if raw_exp_digits.len() <= I16_MAX_DIGITS { - raw_exp_digits - } - - if let PrimitiveInt(exp) = PrimitiveInt::from_str_int() { - SigExp::Fit { - sig, - exp - } - } else { - SigExp::Fat { - sig: raw.sig.to_string_int(), - exp: raw.sig.to_string_int() - } - } - } else { - SigExp::Massive { - sig: raw.sig.to_string_int(), - exp: raw.sig.to_string_int() - } - } - } -} - -#[derive(Debug, PartialEq)] -pub enum SigExp { - /// When both `sig` AND `exp` can be - /// represented by fast primitive - /// types without loss of precision. - Fit { - sig: PrimitiveIntValue, - exp: i16 - }, - /// When `sig` can NOT be represented - /// by a fast primitive type - /// without loss of precision. - Fat { - sig: StringInt, - exp: i16 - }, - /// When both `sig` OR `exp` can NOT be - /// represented by fast primitive types - /// without loss of precision. - // #[feature(massive_sig_exp)] - Massive { - sig: StringInt, - exp: StringInt - } -} - -impl SigExp { - // pub fn is_fit(&self) -> f64 { - - // } - // pub fn map_approx_f64(&self) -> f64 { - // match self { - // SigExp::Fit { sig, exp } => { - - // } - // } - // } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_str_sig_exp_to_sig_exp_fit() { - let sig_str_int = StrInt::new("+1").unwrap(); - let exp_str_int = StrInt::new("+1").unwrap(); - let sig_exp = SigExp::from(StrSigExp::from_parts(sig_str_int, exp_str_int)); - assert_eq!(sig_exp, SigExp::Fit{sig: 1, exp: 1}); - } - - #[test] - fn test_str_sig_exp_to_sig_exp_fat() { - let sig_str_int = StrInt::new("+10000000000000000000").unwrap(); - let exp_str_int = StrInt::new("+1").unwrap(); - let sig_exp = SigExp::from(StrSigExp::from_parts(sig_str_int, exp_str_int)); - assert_eq!(sig_exp, SigExp::Fat{sig: sig_str_int.to_string_int(), exp: 1}); - } - - #[test] - fn test_str_sig_exp_to_sig_exp_massive() { - let sig_str_int = StrInt::new("+10000000000000000000").unwrap(); - let exp_str_int = StrInt::new("+10000000000000000000").unwrap(); - let sig_exp = SigExp::from(StrSigExp::from_parts(sig_str_int, exp_str_int)); - assert_eq!(sig_exp, SigExp::Massive{sig: sig_str_int.to_string_int(), exp: exp_str_int.to_string_int()}); - } -} \ No newline at end of file diff --git a/sehn/src/value/real/str_int.rs b/sehn/src/value/real/str_int.rs deleted file mode 100644 index a9e836f..0000000 --- a/sehn/src/value/real/str_int.rs +++ /dev/null @@ -1,295 +0,0 @@ -use super::ToPrimitiveError; - -const EMPTY_STR: &str = ""; -const ZERO_STR: &str = "0"; -const RADIX_10: u8 = 10; - -macro_rules! max_digits ( - ($x:ident) => (($x::max_value() as f64).log10().floor() as usize + 1) -); - -macro_rules! unchecked_str_to_primitive { - ($n:ident) => { - for &c in digits { - let x = match (c as char).to_digit(RADIX_10) { - Some(x) => x, - None => panic!("invalid char") - }; - result = match result.checked_mul(RADIX_10) { - Some(result) => result, - None => return Err(PIE { kind: Overflow }), - }; - result = match result.checked_add(x) { - Some(result) => result, - None => return Err(PIE { kind: Overflow }), - }; - } - } -} - -macro_rules! impl_str_int_to_primitive_int { - ($n:ident, $p:ident) => { - pub fn $n(self: &Self) -> Result<$p, ToPrimitiveError> { - if self.is_zero() { - return Ok(0) - } - if self.digits().len() <= max_digits!($p) { - for digit. - if let Ok(v) = $p::from_str_radix(self.digits(), 10) { - return Ok(v * self.signum() as $p) - } - } - if self.is_positive() { - Err(ToPrimitiveError::Overflow) - } else { - Err(ToPrimitiveError::Underflow) - } - } - } -} - -macro_rules! impl_str_int_to_primitive_nat { - ($n:ident, $p:ident) => { - pub fn $n(self: &Self) -> Result<$p, ToPrimitiveError> { - if self.is_zero() { - return Ok(0) - } - if self.digits().len() <= max_digits!($p) { - if let Ok(v) = $p::from_str_radix(self.digits(), 10) { - return Ok(v) - } - } - Err(ToPrimitiveError::Overflow) - } - } -} - -#[derive(Debug)] -pub enum StrIntParseError { - InvalidChar, - NonZeroEmpty, - ZeroWithTrailing -} - -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct StrInt<'a> { - signum: i8, - digits: &'a str -} - -impl<'a> StrInt<'a> { - pub fn new(str_int: &'a str) -> Result { - match str_int.chars().next() { - Some('0') => Self::from_parts(0, &str_int[1..]), - Some('-') => Self::from_parts(-1, &str_int[1..]), - Some('+') => Self::from_parts(1, &str_int[1..]), - _ => Self::from_parts(1, str_int) - } - } - - pub fn new_zero() -> Self { - Self { - signum: 0, - digits: EMPTY_STR - } - } - - pub fn from_parts(signum: i8, digits: &'a str) -> Result { - if signum == 0 { - if digits.len() > 0 { - return Err(StrIntParseError::ZeroWithTrailing) - } - } else { - if digits.len() == 0 { - return Err(StrIntParseError::NonZeroEmpty) - } - let maybe_invalid_char = digits.chars().find(|c| match c { - '0'...'9' => false, - _ => true - }); - if let Some(_) = maybe_invalid_char { - return Err(StrIntParseError::InvalidChar) - } - } - Ok(Self { - signum, - digits - }) - } - - #[inline] - pub unsafe fn from_parts_unchecked(signum: i8, digits: &'a str) -> Self { - Self { - signum, - digits - } - } - - #[inline] - pub fn to_string_int(&self) -> StringInt { - StringInt { - signum: self.signum, - digits: self.digits.to_string() - } - } - - #[inline] - pub fn is_positive(&self) -> bool { - self.signum > -1 - } - - #[inline] - pub fn is_negative(&self) -> bool { - self.signum == -1 - } - - #[inline] - pub fn is_zero(&self) -> bool { - self.signum == 0 - } - - #[inline] - pub fn digits(&self) -> &str { - if self.is_zero() { - ZERO_STR - } else { - self.digits - } - } - - #[inline] - pub fn signum(&self) -> i8 { - self.signum - } - - impl_str_int_to_primitive_int!(to_i8, i8); - impl_str_int_to_primitive_int!(to_i16, i16); - impl_str_int_to_primitive_int!(to_i32, i32); - impl_str_int_to_primitive_int!(to_i64, i64); - - impl_str_int_to_primitive_nat!(to_u8, u8); - impl_str_int_to_primitive_nat!(to_u16, u16); - impl_str_int_to_primitive_nat!(to_u32, u32); - impl_str_int_to_primitive_nat!(to_u64, u64); -} - -#[derive(Debug, Clone, PartialEq)] -pub struct StringInt { - signum: i8, - digits: String -} - -impl StringInt { - #[inline] - pub fn is_positive(&self) -> bool { - self.signum > -1 - } - - #[inline] - pub fn is_negative(&self) -> bool { - self.signum == -1 - } - - #[inline] - pub fn is_zero(&self) -> bool { - self.signum == 0 - } - - #[inline] - pub fn digits(&self) -> &str { - if self.is_zero() { - ZERO_STR - } else { - self.digits.as_str() - } - } - - pub fn to_str_int(&self) -> StrInt { - StrInt { - signum: self.signum, - digits: self.digits.as_str() - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - const GOOD_INT_STR_CASES: [(&str, StrInt<'static>); 6] = [ - ("0", StrInt {signum: 0, digits: ""}), - ("1", StrInt {signum: 1, digits: "1"}), - ("-1", StrInt {signum: -1, digits: "1"}), - ("123", StrInt {signum: 1, digits: "123"}), - ("+123", StrInt {signum: 1, digits: "123"}), - ("-123", StrInt {signum: -1, digits: "123"}) - ]; - - const BAD_INT_STR_CASES: [&str; 5] = [ - "01", - "0a", - "--", - "++", - "00" - ]; - - #[test] - fn test_good_str_int_cases() { - for (input, expected) in GOOD_INT_STR_CASES.iter() { - if let Ok(output) = StrInt::new(input) { - assert_eq!(output, *expected); - } else { - panic!("input {:?}", input); - } - } - } - - #[test] - fn test_bad_str_int_cases() { - for input in BAD_INT_STR_CASES.iter() { - assert!(StrInt::new(input).is_err()); - } - } - - #[test] - fn test_str_int_to_int_primitives() { - // Pos - assert_eq!(StrInt::new("+128").unwrap().to_i8(), Ok(i8::max_value())); - assert_eq!(StrInt::new("+32767").unwrap().to_i16(), Ok(i16::max_value())); - assert_eq!(StrInt::new("+2147483647").unwrap().to_i32(), Ok(i32::max_value())); - assert_eq!(StrInt::new("+9223372036854775807").unwrap().to_i64(), Ok(i64::max_value())); - // Neg - assert_eq!(StrInt::new("-127").unwrap().to_i8(), Ok(i8::min_value())); - assert_eq!(StrInt::new("-32767").unwrap().to_i16(), Ok(i16::min_value())); - assert_eq!(StrInt::new("-2147483647").unwrap().to_i32(), Ok(i32::min_value())); - assert_eq!(StrInt::new("-9223372036854775807").unwrap().to_i64(), Ok(i64::min_value())); - } - - #[test] - fn test_str_int_to_nat_primitives() { - assert_eq!(StrInt::new("+255").unwrap().to_u8(), Ok(u8::max_value())); - assert_eq!(StrInt::new("+65535").unwrap().to_u16(), Ok(u16::max_value())); - assert_eq!(StrInt::new("+4294967295").unwrap().to_u32(), Ok(u32::max_value())); - assert_eq!(StrInt::new("+18446744073709551615").unwrap().to_u64(), Ok(u64::max_value())); - assert_eq!(StrInt::new("-255").unwrap().to_u8(), Ok(u8::max_value())); - assert_eq!(StrInt::new("-65535").unwrap().to_u16(), Ok(u16::max_value())); - assert_eq!(StrInt::new("-4294967295").unwrap().to_u32(), Ok(u32::max_value())); - assert_eq!(StrInt::new("-18446744073709551615").unwrap().to_u64(), Ok(u64::max_value())); - } - - #[test] - fn test_int_parse_overflow_underflow() { - let definite_overflow = "+256"; - let definite_underflow = "-256"; - assert_eq!(StrInt::new(definite_overflow).unwrap().to_i8(), Err(ToPrimitiveError::Overflow)); - assert_eq!(StrInt::new(definite_underflow).unwrap().to_i8(), Err(ToPrimitiveError::Underflow)); - } - - #[test] - fn test_nat_parse_overflow() { - let definite_overflow_1 = "+256"; - let definite_overflow_2 = "-256"; - assert_eq!(StrInt::new(definite_overflow_1).unwrap().to_u8(), Err(ToPrimitiveError::Overflow)); - assert_eq!(StrInt::new(definite_overflow_2).unwrap().to_u8(), Err(ToPrimitiveError::Overflow)); - } -} \ No newline at end of file diff --git a/sehn/src/value/text.rs b/sehn/src/value/text.rs deleted file mode 100644 index 02a7d12..0000000 --- a/sehn/src/value/text.rs +++ /dev/null @@ -1,3 +0,0 @@ -pub struct Multiline { - lines: Vec -} \ No newline at end of file