diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:29 +0000 |
commit | 631cd5845e8de329d0e227aaa707d7ea228b8f8f (patch) | |
tree | a1b87c8f8cad01cf18f7c5f57a08f102771ed303 /vendor/basic-toml/src/ser.rs | |
parent | Adding debian version 1.69.0+dfsg1-1. (diff) | |
download | rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.tar.xz rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.zip |
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/basic-toml/src/ser.rs')
-rw-r--r-- | vendor/basic-toml/src/ser.rs | 838 |
1 files changed, 838 insertions, 0 deletions
diff --git a/vendor/basic-toml/src/ser.rs b/vendor/basic-toml/src/ser.rs new file mode 100644 index 000000000..c7a600898 --- /dev/null +++ b/vendor/basic-toml/src/ser.rs @@ -0,0 +1,838 @@ +use serde::ser::{self, Serialize}; +use std::cell::Cell; +use std::error; +use std::fmt::{self, Display, Write}; + +/// Serialize the given data structure as a String of TOML. +/// +/// Serialization can fail if `T`'s implementation of `Serialize` decides to +/// fail, if `T` contains a map with non-string keys, or if `T` attempts to +/// serialize an unsupported datatype such as an enum, tuple, or tuple struct. +pub fn to_string<T: ?Sized>(value: &T) -> Result<String, crate::Error> +where + T: Serialize, +{ + let mut dst = String::with_capacity(128); + value.serialize(&mut Serializer::new(&mut dst))?; + Ok(dst) +} + +#[derive(Debug)] +pub(crate) enum Error { + /// Indicates that a Rust type was requested to be serialized but it was not + /// supported. + /// + /// Currently the TOML format does not support serializing types such as + /// enums, tuples and tuple structs. + UnsupportedType, + + /// The key of all TOML maps must be strings, but serialization was + /// attempted where the key of a map was not a string. + KeyNotString, + + /// All values in a TOML table must be emitted before further tables are + /// emitted. If a value is emitted *after* a table then this error is + /// generated. + ValueAfterTable, + + /// None was attempted to be serialized, but it's not supported. + UnsupportedNone, + + /// A custom error which could be generated when serializing a particular + /// type. + Custom(String), +} + +struct Serializer<'a> { + dst: &'a mut String, + state: State<'a>, +} + +#[derive(Debug, Copy, Clone)] +enum ArrayState { + Started, + StartedAsATable, +} + +#[derive(Debug, Clone)] +enum State<'a> { + Table { + key: &'a str, + parent: &'a State<'a>, + first: &'a Cell<bool>, + table_emitted: &'a Cell<bool>, + }, + Array { + parent: &'a State<'a>, + first: &'a Cell<bool>, + type_: &'a Cell<Option<ArrayState>>, + len: Option<usize>, + }, + End, +} + +struct SerializeSeq<'a, 'b> { + ser: &'b mut Serializer<'a>, + first: Cell<bool>, + type_: Cell<Option<ArrayState>>, + len: Option<usize>, +} + +struct SerializeTable<'a, 'b> { + ser: &'b mut Serializer<'a>, + key: String, + first: Cell<bool>, + table_emitted: Cell<bool>, +} + +impl<'a> Serializer<'a> { + fn new(dst: &'a mut String) -> Serializer<'a> { + Serializer { + dst, + state: State::End, + } + } + + fn display<T: Display>(&mut self, t: T, type_: ArrayState) -> Result<(), Error> { + self.emit_key(type_)?; + write!(self.dst, "{}", t).map_err(ser::Error::custom)?; + if let State::Table { .. } = self.state { + self.dst.push('\n'); + } + Ok(()) + } + + fn emit_key(&mut self, type_: ArrayState) -> Result<(), Error> { + self.array_type(type_); + let state = self.state.clone(); + self._emit_key(&state) + } + + // recursive implementation of `emit_key` above + fn _emit_key(&mut self, state: &State) -> Result<(), Error> { + match *state { + State::End => Ok(()), + State::Array { + parent, + first, + type_, + len, + } => { + assert!(type_.get().is_some()); + if first.get() { + self._emit_key(parent)?; + } + self.emit_array(first, len); + Ok(()) + } + State::Table { + parent, + first, + table_emitted, + key, + } => { + if table_emitted.get() { + return Err(Error::ValueAfterTable); + } + if first.get() { + self.emit_table_header(parent)?; + first.set(false); + } + self.escape_key(key)?; + self.dst.push_str(" = "); + Ok(()) + } + } + } + + fn emit_array(&mut self, first: &Cell<bool>, _len: Option<usize>) { + if first.get() { + self.dst.push('['); + } else { + self.dst.push_str(", "); + } + } + + fn array_type(&mut self, type_: ArrayState) { + let prev = match self.state { + State::Array { type_, .. } => type_, + _ => return, + }; + if prev.get().is_none() { + prev.set(Some(type_)); + } + } + + fn escape_key(&mut self, key: &str) -> Result<(), Error> { + let ok = !key.is_empty() + && key.chars().all(|c| match c { + 'a'..='z' | 'A'..='Z' | '0'..='9' | '-' | '_' => true, + _ => false, + }); + if ok { + write!(self.dst, "{}", key).map_err(ser::Error::custom)?; + } else { + self.emit_str(key)?; + } + Ok(()) + } + + fn emit_str(&mut self, value: &str) -> Result<(), Error> { + self.dst.push('"'); + for ch in value.chars() { + match ch { + '\u{8}' => self.dst.push_str("\\b"), + '\u{9}' => self.dst.push_str("\\t"), + '\u{a}' => self.dst.push_str("\\n"), + '\u{c}' => self.dst.push_str("\\f"), + '\u{d}' => self.dst.push_str("\\r"), + '\u{22}' => self.dst.push_str("\\\""), + '\u{5c}' => self.dst.push_str("\\\\"), + c if c <= '\u{1f}' || c == '\u{7f}' => { + write!(self.dst, "\\u{:04X}", ch as u32).map_err(ser::Error::custom)?; + } + ch => self.dst.push(ch), + } + } + self.dst.push('"'); + Ok(()) + } + + fn emit_table_header(&mut self, state: &State) -> Result<(), Error> { + let array_of_tables = match *state { + State::End => return Ok(()), + State::Array { .. } => true, + State::Table { .. } => false, + }; + + // Unlike [..]s, we can't omit [[..]] ancestors, so be sure to emit + // table headers for them. + let mut p = state; + if let State::Array { first, parent, .. } = *state { + if first.get() { + p = parent; + } + } + while let State::Table { first, parent, .. } = *p { + p = parent; + if !first.get() { + break; + } + if let State::Array { + parent: &State::Table { .. }, + .. + } = *parent + { + self.emit_table_header(parent)?; + break; + } + } + + match *state { + State::Table { first, .. } => { + if !first.get() { + // Newline if we are a table that is not the first table in + // the document. + self.dst.push('\n'); + } + } + State::Array { parent, first, .. } => { + if !first.get() { + // Always newline if we are not the first item in the + // table-array + self.dst.push('\n'); + } else if let State::Table { first, .. } = *parent { + if !first.get() { + // Newline if we are not the first item in the document + self.dst.push('\n'); + } + } + } + State::End => {} + } + self.dst.push('['); + if array_of_tables { + self.dst.push('['); + } + self.emit_key_part(state)?; + if array_of_tables { + self.dst.push(']'); + } + self.dst.push_str("]\n"); + Ok(()) + } + + fn emit_key_part(&mut self, key: &State) -> Result<bool, Error> { + match *key { + State::Array { parent, .. } => self.emit_key_part(parent), + State::End => Ok(true), + State::Table { + key, + parent, + table_emitted, + .. + } => { + table_emitted.set(true); + let first = self.emit_key_part(parent)?; + if !first { + self.dst.push('.'); + } + self.escape_key(key)?; + Ok(false) + } + } + } +} + +macro_rules! serialize_float { + ($this:expr, $v:expr) => {{ + $this.emit_key(ArrayState::Started)?; + match ($v.is_sign_negative(), $v.is_nan(), $v == 0.0) { + (true, true, _) => write!($this.dst, "-nan"), + (false, true, _) => write!($this.dst, "nan"), + (true, false, true) => write!($this.dst, "-0.0"), + (false, false, true) => write!($this.dst, "0.0"), + (_, false, false) => write!($this.dst, "{}", $v).and_then(|_| { + if $v % 1.0 == 0.0 { + write!($this.dst, ".0") + } else { + Ok(()) + } + }), + } + .map_err(ser::Error::custom)?; + + if let State::Table { .. } = $this.state { + $this.dst.push_str("\n"); + } + return Ok(()); + }}; +} + +impl<'a, 'b> ser::Serializer for &'b mut Serializer<'a> { + type Ok = (); + type Error = Error; + type SerializeSeq = SerializeSeq<'a, 'b>; + type SerializeTuple = SerializeSeq<'a, 'b>; + type SerializeTupleStruct = SerializeSeq<'a, 'b>; + type SerializeTupleVariant = ser::Impossible<(), Error>; + type SerializeMap = SerializeTable<'a, 'b>; + type SerializeStruct = SerializeTable<'a, 'b>; + type SerializeStructVariant = ser::Impossible<(), Error>; + + fn serialize_bool(self, v: bool) -> Result<(), Self::Error> { + self.display(v, ArrayState::Started) + } + + fn serialize_i8(self, v: i8) -> Result<(), Self::Error> { + self.display(v, ArrayState::Started) + } + + fn serialize_i16(self, v: i16) -> Result<(), Self::Error> { + self.display(v, ArrayState::Started) + } + + fn serialize_i32(self, v: i32) -> Result<(), Self::Error> { + self.display(v, ArrayState::Started) + } + + fn serialize_i64(self, v: i64) -> Result<(), Self::Error> { + self.display(v, ArrayState::Started) + } + + fn serialize_u8(self, v: u8) -> Result<(), Self::Error> { + self.display(v, ArrayState::Started) + } + + fn serialize_u16(self, v: u16) -> Result<(), Self::Error> { + self.display(v, ArrayState::Started) + } + + fn serialize_u32(self, v: u32) -> Result<(), Self::Error> { + self.display(v, ArrayState::Started) + } + + fn serialize_u64(self, v: u64) -> Result<(), Self::Error> { + self.display(v, ArrayState::Started) + } + + fn serialize_f32(self, v: f32) -> Result<(), Self::Error> { + serialize_float!(self, v) + } + + fn serialize_f64(self, v: f64) -> Result<(), Self::Error> { + serialize_float!(self, v) + } + + fn serialize_char(self, v: char) -> Result<(), Self::Error> { + let mut buf = [0; 4]; + self.serialize_str(v.encode_utf8(&mut buf)) + } + + fn serialize_str(self, value: &str) -> Result<(), Self::Error> { + self.emit_key(ArrayState::Started)?; + self.emit_str(value)?; + if let State::Table { .. } = self.state { + self.dst.push('\n'); + } + Ok(()) + } + + fn serialize_bytes(self, value: &[u8]) -> Result<(), Self::Error> { + value.serialize(self) + } + + fn serialize_none(self) -> Result<(), Self::Error> { + Err(Error::UnsupportedNone) + } + + fn serialize_some<T: ?Sized>(self, value: &T) -> Result<(), Self::Error> + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_unit(self) -> Result<(), Self::Error> { + Err(Error::UnsupportedType) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result<(), Self::Error> { + Err(Error::UnsupportedType) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result<(), Self::Error> { + self.serialize_str(variant) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + _name: &'static str, + value: &T, + ) -> Result<(), Self::Error> + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant<T: ?Sized>( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result<(), Self::Error> + where + T: Serialize, + { + Err(Error::UnsupportedType) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + self.array_type(ArrayState::Started); + Ok(SerializeSeq { + ser: self, + first: Cell::new(true), + type_: Cell::new(None), + len, + }) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + Err(Error::UnsupportedType) + } + + fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + self.array_type(ArrayState::StartedAsATable); + Ok(SerializeTable { + ser: self, + key: String::new(), + first: Cell::new(true), + table_emitted: Cell::new(false), + }) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + self.array_type(ArrayState::StartedAsATable); + Ok(SerializeTable { + ser: self, + key: String::new(), + first: Cell::new(true), + table_emitted: Cell::new(false), + }) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + Err(Error::UnsupportedType) + } +} + +impl<'a, 'b> ser::SerializeSeq for SerializeSeq<'a, 'b> { + type Ok = (); + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + value.serialize(&mut Serializer { + dst: &mut *self.ser.dst, + state: State::Array { + parent: &self.ser.state, + first: &self.first, + type_: &self.type_, + len: self.len, + }, + })?; + self.first.set(false); + Ok(()) + } + + fn end(self) -> Result<(), Error> { + match self.type_.get() { + Some(ArrayState::StartedAsATable) => return Ok(()), + Some(ArrayState::Started) => self.ser.dst.push(']'), + None => { + assert!(self.first.get()); + self.ser.emit_key(ArrayState::Started)?; + self.ser.dst.push_str("[]"); + } + } + if let State::Table { .. } = self.ser.state { + self.ser.dst.push('\n'); + } + Ok(()) + } +} + +impl<'a, 'b> ser::SerializeTuple for SerializeSeq<'a, 'b> { + type Ok = (); + type Error = Error; + + fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result<(), Error> { + ser::SerializeSeq::end(self) + } +} + +impl<'a, 'b> ser::SerializeTupleStruct for SerializeSeq<'a, 'b> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + ser::SerializeSeq::serialize_element(self, value) + } + + fn end(self) -> Result<(), Error> { + ser::SerializeSeq::end(self) + } +} + +impl<'a, 'b> ser::SerializeMap for SerializeTable<'a, 'b> { + type Ok = (); + type Error = Error; + + fn serialize_key<T: ?Sized>(&mut self, input: &T) -> Result<(), Error> + where + T: Serialize, + { + self.key = input.serialize(StringExtractor)?; + Ok(()) + } + + fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<(), Error> + where + T: Serialize, + { + let res = value.serialize(&mut Serializer { + dst: &mut *self.ser.dst, + state: State::Table { + key: &self.key, + parent: &self.ser.state, + first: &self.first, + table_emitted: &self.table_emitted, + }, + }); + match res { + Ok(()) => self.first.set(false), + Err(Error::UnsupportedNone) => {} + Err(e) => return Err(e), + } + Ok(()) + } + + fn end(self) -> Result<(), Error> { + if self.first.get() { + let state = self.ser.state.clone(); + self.ser.emit_table_header(&state)?; + } + Ok(()) + } +} + +impl<'a, 'b> ser::SerializeStruct for SerializeTable<'a, 'b> { + type Ok = (); + type Error = Error; + + fn serialize_field<T: ?Sized>(&mut self, key: &'static str, value: &T) -> Result<(), Error> + where + T: Serialize, + { + let res = value.serialize(&mut Serializer { + dst: &mut *self.ser.dst, + state: State::Table { + key, + parent: &self.ser.state, + first: &self.first, + table_emitted: &self.table_emitted, + }, + }); + match res { + Ok(()) => self.first.set(false), + Err(Error::UnsupportedNone) => {} + Err(e) => return Err(e), + } + Ok(()) + } + + fn end(self) -> Result<(), Error> { + if self.first.get() { + let state = self.ser.state.clone(); + self.ser.emit_table_header(&state)?; + } + Ok(()) + } +} + +struct StringExtractor; + +impl ser::Serializer for StringExtractor { + type Ok = String; + type Error = Error; + type SerializeSeq = ser::Impossible<String, Error>; + type SerializeTuple = ser::Impossible<String, Error>; + type SerializeTupleStruct = ser::Impossible<String, Error>; + type SerializeTupleVariant = ser::Impossible<String, Error>; + type SerializeMap = ser::Impossible<String, Error>; + type SerializeStruct = ser::Impossible<String, Error>; + type SerializeStructVariant = ser::Impossible<String, Error>; + + fn serialize_bool(self, _v: bool) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_i8(self, _v: i8) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_i16(self, _v: i16) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_i32(self, _v: i32) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_i64(self, _v: i64) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_u8(self, _v: u8) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_u16(self, _v: u16) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_u32(self, _v: u32) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_u64(self, _v: u64) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_f32(self, _v: f32) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_f64(self, _v: f64) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_char(self, _v: char) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_str(self, value: &str) -> Result<String, Self::Error> { + Ok(value.to_string()) + } + + fn serialize_bytes(self, _value: &[u8]) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_none(self) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_some<T: ?Sized>(self, _value: &T) -> Result<String, Self::Error> + where + T: Serialize, + { + Err(Error::KeyNotString) + } + + fn serialize_unit(self) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + ) -> Result<String, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_newtype_struct<T: ?Sized>( + self, + _name: &'static str, + value: &T, + ) -> Result<String, Self::Error> + where + T: Serialize, + { + value.serialize(self) + } + + fn serialize_newtype_variant<T: ?Sized>( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _value: &T, + ) -> Result<String, Self::Error> + where + T: Serialize, + { + Err(Error::KeyNotString) + } + + fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_tuple(self, _len: usize) -> Result<Self::SerializeTuple, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleStruct, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeTupleVariant, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result<Self::SerializeStruct, Self::Error> { + Err(Error::KeyNotString) + } + + fn serialize_struct_variant( + self, + _name: &'static str, + _variant_index: u32, + _variant: &'static str, + _len: usize, + ) -> Result<Self::SerializeStructVariant, Self::Error> { + Err(Error::KeyNotString) + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Error::UnsupportedType => "unsupported Rust type".fmt(f), + Error::KeyNotString => "map key was not a string".fmt(f), + Error::ValueAfterTable => "values must be emitted before tables".fmt(f), + Error::UnsupportedNone => "unsupported None value".fmt(f), + Error::Custom(ref s) => s.fmt(f), + } + } +} + +impl error::Error for Error {} + +impl ser::Error for Error { + fn custom<T: Display>(msg: T) -> Error { + Error::Custom(msg.to_string()) + } +} |