From 4c12260a07648fd3893fb154627229c3ad5e9c5b Mon Sep 17 00:00:00 2001 From: Evan Hedbor Date: Mon, 26 Aug 2024 19:17:27 +0200 Subject: [PATCH] Create skeleton for streaming API. --- .vscode/settings.json | 3 + src/lib.rs | 1 + src/ser/serializer.rs | 976 +++++++++++++++++++++--------------------- src/stream.rs | 11 + src/stream/event.rs | 141 ++++++ src/stream/read.rs | 108 +++++ src/stream/reader.rs | 57 +++ src/stream/writer.rs | 28 ++ 8 files changed, 837 insertions(+), 488 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 src/stream.rs create mode 100644 src/stream/event.rs create mode 100644 src/stream/read.rs create mode 100644 src/stream/reader.rs create mode 100644 src/stream/writer.rs diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b3d37f2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "rewrap.wrappingColumn": 100 +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 20ba41c..bf4b485 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,6 +122,7 @@ mod de; pub mod error; pub mod ser; +pub mod stream; pub use error::{Error, Result}; pub use ser::{ diff --git a/src/ser/serializer.rs b/src/ser/serializer.rs index f208234..e422319 100644 --- a/src/ser/serializer.rs +++ b/src/ser/serializer.rs @@ -1,488 +1,488 @@ -use super::formatter::{Formatter, PrettyFormatter}; -use crate::{Error, Result}; -use serde::ser::{ - Impossible, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, - SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, -}; -use serde::Serialize; -use std::borrow::Cow; -use std::io::Write; - -/// Serializes Rust types into KeyValues text. -pub struct Serializer { - writer: W, - formatter: F, - elements: Vec>>, -} - -impl Serializer { - /// Creates a new KeyValues serializer using the given `writer` and `formatter`. - pub fn new(writer: W, formatter: F) -> Self { - Self { - writer, - formatter, - elements: Vec::new(), - } - } - - fn begin_seq(&mut self) -> Result<()> { - // Make sure sequences are enclosed in maps - match self.elements.last() { - Some(Some(_)) => Ok(()), - _ => Err(Error::UnrepresentableSequence), - } - } - - fn end_seq(&mut self) -> Result<()> { - Ok(()) - } - - fn begin_map(&mut self) -> Result<()> { - if let Some(key) = Self::current_key(&self.elements) { - self.formatter - .begin_key(&mut self.writer) - .and_then(|_| self.formatter.write_string(&mut self.writer, key)) - .and_then(|_| self.formatter.end_key(&mut self.writer)) - .and_then(|_| self.formatter.begin_value(&mut self.writer)) - .map_err(Error::Io)?; - } - - self.formatter - .begin_object(&mut self.writer) - .map_err(Error::Io) - } - - fn end_map(&mut self) -> Result<()> { - self.formatter - .end_object(&mut self.writer) - .map_err(Error::Io)?; - - if !self.elements.is_empty() { - self.formatter - .end_value(&mut self.writer) - .map_err(Error::Io)?; - } - - Ok(()) - } - - /// Begins a map element (when `key` is `Some`) or sequence element (when `key` is `None). - fn begin_element(&mut self, key: Option>) -> Result<()> { - self.elements.push(key); - Ok(()) - } - - /// Ends the current map or sequence element. - fn end_element(&mut self) -> Result<()> { - self.elements.pop(); - Ok(()) - } - - fn string_value(&mut self, value: &str) -> Result<()> { - if let Some(key) = Self::current_key(&self.elements) { - // We're in a map or sequence. Write a key-value. - self.formatter - .begin_key(&mut self.writer) - .and_then(|_| self.formatter.write_string(&mut self.writer, key)) - .and_then(|_| self.formatter.end_key(&mut self.writer)) - .and_then(|_| self.formatter.begin_value(&mut self.writer)) - .and_then(|_| self.formatter.write_string(&mut self.writer, value)) - .and_then(|_| self.formatter.end_value(&mut self.writer)) - .map_err(Error::Io) - } else { - // We're at the root level. Just write the plain string. - self.formatter - .write_string(&mut self.writer, value) - .map_err(Error::Io) - } - } - - fn current_key<'a>(elements: &'a [Option>]) -> Option<&'a str> { - elements.last().map(|element| match element { - Some(direct_key) => direct_key.as_ref(), - None => elements - .iter() - .nth_back(1) - .expect("found root-level list? (should be impossible)") - .as_ref() - .expect("found nested list? (should be impossible)"), - }) - } -} - -macro_rules! serialize_as_str_impl { - ($ty:ident) => { - paste::paste! { - fn [](self, v: $ty) -> $crate::Result { - self.serialize_str(&v.to_string()) - } - } - }; - ($first:ident, $($rest:ident),+) => { - serialize_as_str_impl!($first); - serialize_as_str_impl!($($rest),+); - } -} - -impl<'a, W: Write, F: Formatter> serde::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; - - fn serialize_bool(self, v: bool) -> Result { - let s = if v { "1" } else { "0" }; - self.serialize_str(s) - } - - serialize_as_str_impl!(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, f32, f64, char); - - fn serialize_str(self, v: &str) -> Result { - self.string_value(v) - } - - fn serialize_bytes(self, _v: &[u8]) -> Result { - Err(Error::UnsupportedType("bytes".to_string())) - } - - fn serialize_none(self) -> Result { - // omit the value entirely, unless we're at root level. - if self.elements.is_empty() { - self.string_value("")?; - } - - Ok(()) - } - - fn serialize_some(self, value: &T) -> Result { - value.serialize(self) - } - - fn serialize_unit(self) -> Result { - self.serialize_none() - } - - fn serialize_unit_struct(self, _name: &'static str) -> Result { - self.serialize_unit() - } - - 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 { - value.serialize(self) - } - - fn serialize_newtype_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - value: &T, - ) -> Result { - self.begin_map()?; - self.begin_element(Some(Cow::Borrowed(variant)))?; - value.serialize(&mut *self)?; - self.end_element()?; - self.end_map()?; - - Ok(()) - } - - fn serialize_seq(self, _len: Option) -> Result { - self.begin_seq()?; - 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 { - self.serialize_seq(Some(len)) - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - _len: usize, - ) -> Result { - self.begin_map()?; - self.begin_element(Some(Cow::Borrowed(variant)))?; - Ok(self) - } - - fn serialize_map(self, _len: Option) -> Result { - self.begin_map()?; - Ok(self) - } - - fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { - self.begin_map()?; - Ok(self) - } - - fn serialize_struct_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - _len: usize, - ) -> Result { - self.begin_map()?; - self.begin_element(Some(Cow::Borrowed(variant)))?; - self.begin_map()?; - Ok(self) - } -} - -struct MapKeySerializer<'a, W, F> { - serializer: &'a mut Serializer, -} - -impl<'a, W: Write, F: Formatter> serde::Serializer for MapKeySerializer<'a, W, F> { - type Ok = (); - type Error = Error; - type SerializeSeq = Impossible; - type SerializeTuple = Impossible; - type SerializeTupleStruct = Impossible; - type SerializeTupleVariant = Impossible; - type SerializeMap = Impossible; - type SerializeStruct = Impossible; - type SerializeStructVariant = Impossible; - - serialize_as_str_impl!(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, f32, f64, char); - - fn serialize_bool(self, v: bool) -> Result { - self.serialize_str(if v { "1" } else { "0" }) - } - - fn serialize_str(self, v: &str) -> Result { - let key = Cow::Owned(String::from(v)); - self.serializer.begin_element(Some(key)) - } - - fn serialize_bytes(self, _v: &[u8]) -> Result { - Err(Error::KeyMustBeAString("bytes".to_string())) - } - - fn serialize_none(self) -> Result { - Err(Error::KeyMustBeAString("none".to_string())) - } - - fn serialize_some(self, _value: &T) -> Result { - Err(Error::KeyMustBeAString("some".to_string())) - } - - fn serialize_unit(self) -> Result { - Err(Error::KeyMustBeAString("unit".to_string())) - } - - fn serialize_unit_struct(self, _name: &'static str) -> Result { - Err(Error::KeyMustBeAString("unit struct".to_string())) - } - - fn serialize_unit_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - ) -> Result { - Err(Error::KeyMustBeAString("unit variant".to_string())) - } - - fn serialize_newtype_struct( - self, - _name: &'static str, - value: &T, - ) -> Result { - value.serialize(self) - } - - fn serialize_newtype_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _value: &T, - ) -> Result { - Err(Error::KeyMustBeAString("newtype variant".to_string())) - } - - fn serialize_seq(self, _len: Option) -> Result { - Err(Error::KeyMustBeAString("sequence".to_string())) - } - - fn serialize_tuple(self, _len: usize) -> Result { - Err(Error::KeyMustBeAString("tuple".to_string())) - } - - fn serialize_tuple_struct( - self, - _name: &'static str, - _len: usize, - ) -> Result { - Err(Error::KeyMustBeAString("tuple struct".to_string())) - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize, - ) -> Result { - Err(Error::KeyMustBeAString("tuple variant".to_string())) - } - - fn serialize_map(self, _len: Option) -> Result { - Err(Error::KeyMustBeAString("map".to_string())) - } - - fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { - Err(Error::KeyMustBeAString("struct".to_string())) - } - - fn serialize_struct_variant( - self, - _name: &'static str, - _variant_index: u32, - _variant: &'static str, - _len: usize, - ) -> Result { - Err(Error::KeyMustBeAString("struct variant".to_string())) - } -} - -impl<'a, W: Write, F: Formatter> SerializeSeq for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result { - self.begin_element(None)?; - value.serialize(&mut **self)?; - self.end_element() - } - - fn end(self) -> Result { - self.end_seq() - } -} - -impl<'a, W: Write, F: Formatter> SerializeTuple for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result { - SerializeSeq::serialize_element(self, value) - } - - fn end(self) -> Result { - SerializeSeq::end(self) - } -} - -impl<'a, W: Write, F: Formatter> SerializeTupleStruct for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result { - SerializeSeq::serialize_element(self, value) - } - - fn end(self) -> Result { - SerializeSeq::end(self) - } -} - -impl<'a, W: Write, F: Formatter> SerializeTupleVariant for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result { - value.serialize(&mut **self) - } - - fn end(self) -> Result { - self.end_element()?; - self.end_map() - } -} - -impl<'a, W: Write, F: Formatter> SerializeMap for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_key(&mut self, key: &T) -> Result { - let ser = MapKeySerializer { serializer: self }; - key.serialize(ser) - } - - fn serialize_value(&mut self, value: &T) -> Result { - value.serialize(&mut **self)?; - self.end_element() - } - - fn end(self) -> Result { - self.end_map() - } -} - -impl<'a, W: Write, F: Formatter> SerializeStruct for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result { - self.begin_element(Some(Cow::Borrowed(key)))?; - value.serialize(&mut **self)?; - self.end_element() - } - - fn end(self) -> Result { - self.end_map() - } -} - -impl<'a, W: Write, F: Formatter> SerializeStructVariant for &'a mut Serializer { - type Ok = (); - type Error = Error; - - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result { - SerializeStruct::serialize_field(self, key, value) - } - - fn end(self) -> Result { - self.end_map()?; - self.end_element()?; - self.end_map() - } -} +use super::formatter::{Formatter, PrettyFormatter}; +use crate::{Error, Result}; +use serde::ser::{ + Impossible, SerializeMap, SerializeSeq, SerializeStruct, SerializeStructVariant, + SerializeTuple, SerializeTupleStruct, SerializeTupleVariant, +}; +use serde::Serialize; +use std::borrow::Cow; +use std::io::Write; + +/// A high-level serializer for converting Rust types into KeyValues text. +pub struct Serializer { + writer: W, + formatter: F, + elements: Vec>>, +} + +impl Serializer { + /// Creates a new KeyValues serializer using the given `writer` and `formatter`. + pub fn new(writer: W, formatter: F) -> Self { + Self { + writer, + formatter, + elements: Vec::new(), + } + } + + fn begin_seq(&mut self) -> Result<()> { + // Make sure sequences are enclosed in maps + match self.elements.last() { + Some(Some(_)) => Ok(()), + _ => Err(Error::UnrepresentableSequence), + } + } + + fn end_seq(&mut self) -> Result<()> { + Ok(()) + } + + fn begin_map(&mut self) -> Result<()> { + if let Some(key) = Self::current_key(&self.elements) { + self.formatter + .begin_key(&mut self.writer) + .and_then(|_| self.formatter.write_string(&mut self.writer, key)) + .and_then(|_| self.formatter.end_key(&mut self.writer)) + .and_then(|_| self.formatter.begin_value(&mut self.writer)) + .map_err(Error::Io)?; + } + + self.formatter + .begin_object(&mut self.writer) + .map_err(Error::Io) + } + + fn end_map(&mut self) -> Result<()> { + self.formatter + .end_object(&mut self.writer) + .map_err(Error::Io)?; + + if !self.elements.is_empty() { + self.formatter + .end_value(&mut self.writer) + .map_err(Error::Io)?; + } + + Ok(()) + } + + /// Begins a map element (when `key` is `Some`) or sequence element (when `key` is `None). + fn begin_element(&mut self, key: Option>) -> Result<()> { + self.elements.push(key); + Ok(()) + } + + /// Ends the current map or sequence element. + fn end_element(&mut self) -> Result<()> { + self.elements.pop(); + Ok(()) + } + + fn string_value(&mut self, value: &str) -> Result<()> { + if let Some(key) = Self::current_key(&self.elements) { + // We're in a map or sequence. Write a key-value. + self.formatter + .begin_key(&mut self.writer) + .and_then(|_| self.formatter.write_string(&mut self.writer, key)) + .and_then(|_| self.formatter.end_key(&mut self.writer)) + .and_then(|_| self.formatter.begin_value(&mut self.writer)) + .and_then(|_| self.formatter.write_string(&mut self.writer, value)) + .and_then(|_| self.formatter.end_value(&mut self.writer)) + .map_err(Error::Io) + } else { + // We're at the root level. Just write the plain string. + self.formatter + .write_string(&mut self.writer, value) + .map_err(Error::Io) + } + } + + fn current_key<'a>(elements: &'a [Option>]) -> Option<&'a str> { + elements.last().map(|element| match element { + Some(direct_key) => direct_key.as_ref(), + None => elements + .iter() + .nth_back(1) + .expect("found root-level list? (should be impossible)") + .as_ref() + .expect("found nested list? (should be impossible)"), + }) + } +} + +macro_rules! serialize_as_str_impl { + ($ty:ident) => { + paste::paste! { + fn [](self, v: $ty) -> $crate::Result { + self.serialize_str(&v.to_string()) + } + } + }; + ($first:ident, $($rest:ident),+) => { + serialize_as_str_impl!($first); + serialize_as_str_impl!($($rest),+); + } +} + +impl<'a, W: Write, F: Formatter> serde::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; + + fn serialize_bool(self, v: bool) -> Result { + let s = if v { "1" } else { "0" }; + self.serialize_str(s) + } + + serialize_as_str_impl!(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, f32, f64, char); + + fn serialize_str(self, v: &str) -> Result { + self.string_value(v) + } + + fn serialize_bytes(self, _v: &[u8]) -> Result { + Err(Error::UnsupportedType("bytes".to_string())) + } + + fn serialize_none(self) -> Result { + // omit the value entirely, unless we're at root level. + if self.elements.is_empty() { + self.string_value("")?; + } + + Ok(()) + } + + fn serialize_some(self, value: &T) -> Result { + value.serialize(self) + } + + fn serialize_unit(self) -> Result { + self.serialize_none() + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + self.serialize_unit() + } + + 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 { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result { + self.begin_map()?; + self.begin_element(Some(Cow::Borrowed(variant)))?; + value.serialize(&mut *self)?; + self.end_element()?; + self.end_map()?; + + Ok(()) + } + + fn serialize_seq(self, _len: Option) -> Result { + self.begin_seq()?; + 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 { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + self.begin_map()?; + self.begin_element(Some(Cow::Borrowed(variant)))?; + Ok(self) + } + + fn serialize_map(self, _len: Option) -> Result { + self.begin_map()?; + Ok(self) + } + + fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { + self.begin_map()?; + Ok(self) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + _len: usize, + ) -> Result { + self.begin_map()?; + self.begin_element(Some(Cow::Borrowed(variant)))?; + self.begin_map()?; + Ok(self) + } +} + +struct MapKeySerializer<'a, W, F> { + serializer: &'a mut Serializer, +} + +impl<'a, W: Write, F: Formatter> serde::Serializer for MapKeySerializer<'a, W, F> { + type Ok = (); + type Error = Error; + type SerializeSeq = Impossible; + type SerializeTuple = Impossible; + type SerializeTupleStruct = Impossible; + type SerializeTupleVariant = Impossible; + type SerializeMap = Impossible; + type SerializeStruct = Impossible; + type SerializeStructVariant = Impossible; + + serialize_as_str_impl!(i8, i16, i32, i64, i128, u8, u16, u32, u64, u128, f32, f64, char); + + fn serialize_bool(self, v: bool) -> Result { + self.serialize_str(if v { "1" } else { "0" }) + } + + fn serialize_str(self, v: &str) -> Result { + let key = Cow::Owned(String::from(v)); + self.serializer.begin_element(Some(key)) + } + + fn serialize_bytes(self, _v: &[u8]) -> Result { + Err(Error::KeyMustBeAString("bytes".to_string())) + } + + fn serialize_none(self) -> Result { + Err(Error::KeyMustBeAString("none".to_string())) + } + + fn serialize_some(self, _value: &T) -> Result { + Err(Error::KeyMustBeAString("some".to_string())) + } + + fn serialize_unit(self) -> Result { + Err(Error::KeyMustBeAString("unit".to_string())) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Err(Error::KeyMustBeAString("unit struct".to_string())) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result { + Err(Error::KeyMustBeAString("unit variant".to_string())) + } + + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result { + value.serialize(self) + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result { + Err(Error::KeyMustBeAString("newtype variant".to_string())) + } + + fn serialize_seq(self, _len: Option) -> Result { + Err(Error::KeyMustBeAString("sequence".to_string())) + } + + fn serialize_tuple(self, _len: usize) -> Result { + Err(Error::KeyMustBeAString("tuple".to_string())) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + Err(Error::KeyMustBeAString("tuple struct".to_string())) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(Error::KeyMustBeAString("tuple variant".to_string())) + } + + fn serialize_map(self, _len: Option) -> Result { + Err(Error::KeyMustBeAString("map".to_string())) + } + + fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { + Err(Error::KeyMustBeAString("struct".to_string())) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result { + Err(Error::KeyMustBeAString("struct variant".to_string())) + } +} + +impl<'a, W: Write, F: Formatter> SerializeSeq for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result { + self.begin_element(None)?; + value.serialize(&mut **self)?; + self.end_element() + } + + fn end(self) -> Result { + self.end_seq() + } +} + +impl<'a, W: Write, F: Formatter> SerializeTuple for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result { + SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + SerializeSeq::end(self) + } +} + +impl<'a, W: Write, F: Formatter> SerializeTupleStruct for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result { + SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result { + SerializeSeq::end(self) + } +} + +impl<'a, W: Write, F: Formatter> SerializeTupleVariant for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result { + value.serialize(&mut **self) + } + + fn end(self) -> Result { + self.end_element()?; + self.end_map() + } +} + +impl<'a, W: Write, F: Formatter> SerializeMap for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_key(&mut self, key: &T) -> Result { + let ser = MapKeySerializer { serializer: self }; + key.serialize(ser) + } + + fn serialize_value(&mut self, value: &T) -> Result { + value.serialize(&mut **self)?; + self.end_element() + } + + fn end(self) -> Result { + self.end_map() + } +} + +impl<'a, W: Write, F: Formatter> SerializeStruct for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result { + self.begin_element(Some(Cow::Borrowed(key)))?; + value.serialize(&mut **self)?; + self.end_element() + } + + fn end(self) -> Result { + self.end_map() + } +} + +impl<'a, W: Write, F: Formatter> SerializeStructVariant for &'a mut Serializer { + type Ok = (); + type Error = Error; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result { + SerializeStruct::serialize_field(self, key, value) + } + + fn end(self) -> Result { + self.end_map()?; + self.end_element()?; + self.end_map() + } +} diff --git a/src/stream.rs b/src/stream.rs new file mode 100644 index 0000000..946ddb8 --- /dev/null +++ b/src/stream.rs @@ -0,0 +1,11 @@ +//! A low-level streaming API for KeyValues. + +pub mod event; +#[doc(hidden)] +pub mod read; +pub mod reader; +pub mod writer; + +pub use event::{Event, QuoteStyle, Scalar, Tag}; +pub use reader::Reader; +pub use writer::Writer; diff --git a/src/stream/event.rs b/src/stream/event.rs new file mode 100644 index 0000000..fcf59eb --- /dev/null +++ b/src/stream/event.rs @@ -0,0 +1,141 @@ +//! Contains representations for the events that may occur while reading or writing KeyValues. The +//! same struct ([`Event`]) is used to represent both read events and write events. + +use std::borrow::Cow; + +/// Represents all possible events that may occur while reading or writing KeyValues. +#[derive(Clone, Debug, PartialEq)] +pub enum Event<'a> { + /// The start of a document. + /// + /// Note: there is no actual token corresponding to the beginning of a document. + StartDocument, + + /// The end of a document (end of file). + /// + /// Note: there is no actual token corresponding to the end of a document, other than the lack of further input. + EndDocument, + + /// The start of an object (`{`). + StartObject, + + /// The end of an object (`}`). + EndObject, + + /// A string. This event is used for both keys and values. For more information, see the [`Scalar`] struct. + Scalar(Scalar<'a>), +} + +/// A string. This is used for both keys and values. +#[derive(Clone, Debug, PartialEq)] +pub struct Scalar<'a> { + tag: Option>, + value: Cow<'a, str>, + quote_style: QuoteStyle, +} + +/// A conditional tag, which may be present in a [`Scalar`] key. +#[derive(Clone, Debug, PartialEq)] +pub struct Tag<'a> { + value: Cow<'a, str>, + quote_style: QuoteStyle, +} + +/// Specifies how strings are quoted. +#[derive(Copy, Clone, Debug, PartialEq)] +pub enum QuoteStyle { + /// Use double quotes. + DoubleQuoted, + + /// Do not use quotes. + Unquoted, + + /// Let the serializer decide if the string should be [quoted][QuoteStyle::DoubleQuoted] or + /// [unquoted][QuoteStyle::Unquoted]. This variant is unused in deserialization. + /// + /// # Rules + /// + /// The following rules are used for determining if a string will be quoted or not: + /// + /// 1. If quotes are required, use quotes. This happens if the string contains whitespace or + /// a control character (`{`, `}`, or `"`), or begins with `[` and is not a tag. + /// 2. If the string is a tag, don't use quotes. + /// 3. If the string starts with `#` (like a `#base` or `#include` directive), don't use quotes. + /// 4. Otherwise, use double quotes. + Unspecified, +} + +impl<'a> Scalar<'a> { + /// Creates a new scalar. + /// + /// # Errors + /// + /// If the scalar requires quotes but the `quote_style` is [`QuoteStyle::Unquoted`], `None` will + /// be returned. For a scalar, quotes are required if the `value` contains whitespace or a + /// control character (`{`, `}`, or `"`), or begins with `[`. + pub fn new(tag: Option>, value: Cow<'a, str>, quote_style: QuoteStyle) -> Option { + if quote_style == QuoteStyle::Unquoted + && (requires_quotes(&value) || value.starts_with('[')) + { + None + } else { + Some(Self { + tag, + value, + quote_style, + }) + } + } + + /// Returns the scalar's tag. This only makes sense for keys; values completely ignore this field. + pub fn tag(&self) -> Option<&Tag<'a>> { + self.tag.as_ref() + } + + /// Returns the scalar's value. + pub fn value(&self) -> &str { + &self.value + } + + /// Returns the scalar's quote style. + pub fn quote_style(&self) -> QuoteStyle { + self.quote_style + } +} + +impl<'a> Tag<'a> { + /// Creates a new tag. Tags values must begin with `[`, end with `]`, and be at least three + /// characters long. + /// + /// # Errors + /// + /// If the `value` is formatted incorrectly (as described above), `None` will be returned. + /// + /// If the tag requires quotes but the `quote_style` is [`QuoteStyle::Unquoted`], `None` will be + /// returned. For a tag, quotes are required if the `value` contains whitespace or a control + /// character (`{`, `}`, or `"`). + pub fn new(value: Cow<'a, str>, quote_style: QuoteStyle) -> Option { + if !value.starts_with('[') || !value.ends_with(']') || value.len() < 3 { + None + } else if quote_style == QuoteStyle::Unquoted && requires_quotes(&value) { + None + } else { + Some(Tag { value, quote_style }) + } + } + + /// Returns the tag's value. This includes the enclosing square brackets. + pub fn value(&self) -> &str { + &self.value + } + + /// Returns the tag's quote style. + pub fn quote_style(&self) -> QuoteStyle { + self.quote_style + } +} + +fn requires_quotes(value: &str) -> bool { + value.is_empty() + || value.contains(|c: char| c == '{' || c == '}' || c == '"' || c.is_whitespace()) +} diff --git a/src/stream/read.rs b/src/stream/read.rs new file mode 100644 index 0000000..1cde193 --- /dev/null +++ b/src/stream/read.rs @@ -0,0 +1,108 @@ +use crate::Result; +use std::borrow::Cow; +use std::io; + +mod sealed { + /// This trait is used to prevent other crates from implementing the [`Read`] trait. + pub(super) trait Sealed {} +} + +/// Crate-private trait to abstract around the different kinds of readers used by the +/// [`Reader`][super::reader::Reader] struct. +/// +/// The idea for this trait comes from [`serde_json`]. +/// +/// [`serde_json`]: https://docs.rs/serde_json/latest/serde_json/de/trait.Read.html +#[allow(private_bounds)] +pub trait Read<'a>: sealed::Sealed { + fn peek_char(&mut self, i: usize) -> Result>; + + fn next_char(&mut self) -> Result>; + + fn parse_str(&mut self) -> Result>>; +} + +#[derive(Debug)] +pub(super) struct IoReader { + bytes: io::Bytes, + peeked: Vec, +} + +impl IoReader { + pub fn new(reader: R) -> Self { + Self { + bytes: reader.bytes(), + peeked: vec![] + } + } +} + +impl sealed::Sealed for IoReader {} + +impl<'a, R: io::Read> Read<'a> for IoReader { + fn peek_char(&mut self, i: usize) -> Result> { + todo!() + } + + fn next_char(&mut self) -> Result> { + todo!() + } + + fn parse_str(&mut self) -> Result>> { + todo!() + } +} + +#[derive(Debug, Clone)] +pub(super) struct SliceReader<'a> { + slice: &'a [u8], +} + +impl<'a> SliceReader<'a> { + pub fn new(slice: &'a [u8]) -> Self { + Self { slice } + } +} + +impl<'a> sealed::Sealed for SliceReader<'a> {} + +impl<'a> Read<'a> for SliceReader<'a> { + fn peek_char(&mut self, i: usize) -> Result> { + todo!() + } + + fn next_char(&mut self) -> Result> { + todo!() + } + + fn parse_str(&mut self) -> Result>> { + todo!() + } +} + +#[derive(Debug, Clone)] +pub(super) struct StrReader<'a> { + str: &'a str, +} + +impl<'a> StrReader<'a> { + pub fn new(str: &'a str) -> Self { + Self { str } + } +} + +impl<'a> sealed::Sealed for StrReader<'a> {} + +impl<'a> Read<'a> for StrReader<'a> { + fn peek_char(&mut self, i: usize) -> Result> { + todo!() + } + + fn next_char(&mut self) -> Result> { + todo!() + } + + fn parse_str(&mut self) -> Result>> { + todo!() + } +} diff --git a/src/stream/reader.rs b/src/stream/reader.rs new file mode 100644 index 0000000..948fac8 --- /dev/null +++ b/src/stream/reader.rs @@ -0,0 +1,57 @@ +use super::event::Event; +use super::read; +use crate::Result; +use std::io; + +/// A low-level streaming reader that parses text into [`Event`]s representing the KeyValues format. +#[derive(Clone, Debug)] +pub struct Reader { + inner: R, + first: bool, +} + +impl Reader { + fn new(inner: R) -> Self { + Self { inner, first: true } + } +} + +impl Reader> { + /// Creates a KeyValues reader from an [`io::Read`]. + /// + /// This may be less efficient than creating a `Reader` from a [`&[u8]`][Self::from_slice()] or + /// [`&str`][Self::from_str()], as those implementations do not need to buffer input. + pub fn from_reader(reader: R) -> Self { + Self::new(read::IoReader::new(reader)) + } +} + +impl<'a> Reader> { + /// Creates a KeyValues reader from a `&[u8]`. + /// + /// If the input is known to be UTF-8, use [`Reader::from_str()`] instead to prevent redundant + /// UTF-8 validation. + pub fn from_slice(slice: &'a [u8]) -> Self { + Self::new(read::SliceReader::new(slice)) + } +} + +impl<'a> Reader> { + /// Creates a KeyValues reader from a `&str`. + pub fn from_str(str: &'a str) -> Self { + Self::new(read::StrReader::new(str)) + } +} + +impl<'a, R: read::Read<'a>> Reader { + /// Reads the next event from the input. + /// + /// # Errors + /// + /// This function returns an error if an `io::Error` occurs or the input contains invalid + /// syntax. Note that this function does not check semantics (is this a valid document?), only + /// syntax (is this one of the possible KeyValues [`Event`]s?). + pub fn read(&mut self) -> Result> { + todo!() + } +} diff --git a/src/stream/writer.rs b/src/stream/writer.rs new file mode 100644 index 0000000..4181367 --- /dev/null +++ b/src/stream/writer.rs @@ -0,0 +1,28 @@ +use super::event::Event; +use crate::Result; +use std::io; + +/// A low-level streaming writer that generates text from a sequence of [`Event`]s representing the +/// KeyValues format. +pub struct Writer { + writer: W, +} + +impl Writer { + /// Creates a KeyValues writer from an [`io::Write`]. + pub fn new(writer: W) -> Self { + Self { writer } + } +} + +impl Writer { + /// Writes the `event` to the output. + /// + /// # Errors + /// + /// This function returns an error if an `io::Error` occurs. Note that this function does not + /// check semantics (is this a valid document?). + pub fn write(event: Event<'_>) -> Result<()> { + todo!() + } +}