| //! The internal `Value` serialization API. | |
| //! | |
| //! This implementation isn't intended to be public. It may need to change | |
| //! for optimizations or to support new external serialization frameworks. | |
| use std::any::TypeId; | |
| use super::{Error, Fill, Slot}; | |
| pub(super) mod cast; | |
| pub(super) mod fmt; | |
| #[cfg(feature = "kv_unstable_sval")] | |
| pub(super) mod sval; | |
| /// A container for a structured value for a specific kind of visitor. | |
| #[derive(Clone, Copy)] | |
| pub(super) enum Inner<'v> { | |
| /// A simple primitive value that can be copied without allocating. | |
| Primitive(Primitive<'v>), | |
| /// A value that can be filled. | |
| Fill(Erased<'v, dyn Fill + 'static>), | |
| /// A debuggable value. | |
| Debug(Erased<'v, dyn fmt::Debug + 'static>), | |
| /// A displayable value. | |
| Display(Erased<'v, dyn fmt::Display + 'static>), | |
| #[cfg(feature = "kv_unstable_sval")] | |
| /// A structured value from `sval`. | |
| Sval(Erased<'v, dyn sval::Value + 'static>), | |
| } | |
| impl<'v> Inner<'v> { | |
| pub(super) fn visit(self, visitor: &mut dyn Visitor<'v>) -> Result<(), Error> { | |
| match self { | |
| Inner::Primitive(value) => value.visit(visitor), | |
| Inner::Fill(value) => value.get().fill(&mut Slot::new(visitor)), | |
| Inner::Debug(value) => visitor.debug(value.get()), | |
| Inner::Display(value) => visitor.display(value.get()), | |
| #[cfg(feature = "kv_unstable_sval")] | |
| Inner::Sval(value) => visitor.sval(value.get()), | |
| } | |
| } | |
| } | |
| /// The internal serialization contract. | |
| pub(super) trait Visitor<'v> { | |
| fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error>; | |
| fn display(&mut self, v: &dyn fmt::Display) -> Result<(), Error> { | |
| self.debug(&format_args!("{}", v)) | |
| } | |
| fn u64(&mut self, v: u64) -> Result<(), Error>; | |
| fn i64(&mut self, v: i64) -> Result<(), Error>; | |
| fn f64(&mut self, v: f64) -> Result<(), Error>; | |
| fn bool(&mut self, v: bool) -> Result<(), Error>; | |
| fn char(&mut self, v: char) -> Result<(), Error>; | |
| fn str(&mut self, v: &str) -> Result<(), Error>; | |
| fn borrowed_str(&mut self, v: &'v str) -> Result<(), Error> { | |
| self.str(v) | |
| } | |
| fn none(&mut self) -> Result<(), Error>; | |
| #[cfg(feature = "kv_unstable_sval")] | |
| fn sval(&mut self, v: &dyn sval::Value) -> Result<(), Error>; | |
| } | |
| /// A captured primitive value. | |
| /// | |
| /// These values are common and cheap to copy around. | |
| #[derive(Clone, Copy)] | |
| pub(super) enum Primitive<'v> { | |
| Signed(i64), | |
| Unsigned(u64), | |
| Float(f64), | |
| Bool(bool), | |
| Char(char), | |
| Str(&'v str), | |
| Fmt(fmt::Arguments<'v>), | |
| None, | |
| } | |
| impl<'v> Primitive<'v> { | |
| fn visit(self, visitor: &mut dyn Visitor<'v>) -> Result<(), Error> { | |
| match self { | |
| Primitive::Signed(value) => visitor.i64(value), | |
| Primitive::Unsigned(value) => visitor.u64(value), | |
| Primitive::Float(value) => visitor.f64(value), | |
| Primitive::Bool(value) => visitor.bool(value), | |
| Primitive::Char(value) => visitor.char(value), | |
| Primitive::Str(value) => visitor.borrowed_str(value), | |
| Primitive::Fmt(value) => visitor.debug(&value), | |
| Primitive::None => visitor.none(), | |
| } | |
| } | |
| } | |
| impl<'v> From<u64> for Primitive<'v> { | |
| fn from(v: u64) -> Self { | |
| Primitive::Unsigned(v) | |
| } | |
| } | |
| impl<'v> From<i64> for Primitive<'v> { | |
| fn from(v: i64) -> Self { | |
| Primitive::Signed(v) | |
| } | |
| } | |
| impl<'v> From<f64> for Primitive<'v> { | |
| fn from(v: f64) -> Self { | |
| Primitive::Float(v) | |
| } | |
| } | |
| impl<'v> From<bool> for Primitive<'v> { | |
| fn from(v: bool) -> Self { | |
| Primitive::Bool(v) | |
| } | |
| } | |
| impl<'v> From<char> for Primitive<'v> { | |
| fn from(v: char) -> Self { | |
| Primitive::Char(v) | |
| } | |
| } | |
| impl<'v> From<&'v str> for Primitive<'v> { | |
| fn from(v: &'v str) -> Self { | |
| Primitive::Str(v) | |
| } | |
| } | |
| impl<'v> From<fmt::Arguments<'v>> for Primitive<'v> { | |
| fn from(v: fmt::Arguments<'v>) -> Self { | |
| Primitive::Fmt(v) | |
| } | |
| } | |
| /// A downcastable dynamic type. | |
| pub(super) struct Erased<'v, T: ?Sized> { | |
| type_id: TypeId, | |
| inner: &'v T, | |
| } | |
| impl<'v, T: ?Sized> Clone for Erased<'v, T> { | |
| fn clone(&self) -> Self { | |
| Erased { | |
| type_id: self.type_id, | |
| inner: self.inner, | |
| } | |
| } | |
| } | |
| impl<'v, T: ?Sized> Copy for Erased<'v, T> {} | |
| impl<'v, T: ?Sized> Erased<'v, T> { | |
| // SAFETY: `U: Unsize<T>` and the underlying value `T` must not change | |
| // We could add a safe variant of this method with the `Unsize` trait | |
| pub(super) unsafe fn new_unchecked<U>(inner: &'v T) -> Self | |
| where | |
| U: 'static, | |
| T: 'static, | |
| { | |
| Erased { | |
| type_id: TypeId::of::<U>(), | |
| inner, | |
| } | |
| } | |
| pub(super) fn get(self) -> &'v T { | |
| self.inner | |
| } | |
| // SAFETY: The underlying type of `T` is `U` | |
| pub(super) unsafe fn downcast_unchecked<U>(self) -> &'v U { | |
| &*(self.inner as *const T as *const U) | |
| } | |
| } |