use core::cmp::Ordering;
use core::fmt::{self, Write};
use core::marker::PhantomData;
use core::str;
use crate::alloc::{AllocError, Box, GlobalAllocator, String, Vec};
use crate::de::{AsDecoder, Decode, Decoder, Visitor};
use crate::de::{
EntryDecoder, MapDecoder, SequenceDecoder, SizeHint, UnsizedVisitor, VariantDecoder,
};
use crate::en::{Encode, Encoder};
use crate::en::{MapEncoder, SequenceEncoder, VariantEncoder};
use crate::{Allocator, Context, Options};
use super::de::ValueDecoder;
use super::type_hint::{NumberHint, TypeHint};
pub struct Value<A>
where
A: Allocator,
{
pub(super) kind: ValueKind<A>,
}
macro_rules! number {
($ty:ty, $variant:ident, $constructor:ident, $test:ident, $example:expr) => {
#[doc = concat!(" Construct a `", stringify!($ty), "` value.")]
#[doc = concat!(" let value = Value::<Global>::", stringify!($constructor), "(", $example, ");")]
#[doc = concat!(" assert!(value.", stringify!($test), "());")]
pub const fn $constructor(value: $ty) -> Self {
Self::new(ValueKind::Number(Number::$variant(value)))
}
#[doc = concat!(" Check if the value is a `", stringify!($ty), "`.")]
#[doc = concat!(" let value = Value::<Global>::", stringify!($constructor), "(", $example, ");")]
#[doc = concat!(" assert!(value.", stringify!($test), "());")]
pub fn $test(&self) -> bool {
matches!(self.kind, ValueKind::Number(Number::$variant(_)))
}
}
}
impl<A> Value<A>
where
A: Allocator,
{
#[inline]
pub(crate) const fn new(kind: ValueKind<A>) -> Self {
Self { kind }
}
pub const fn empty() -> Self {
Self::new(ValueKind::Empty)
}
pub fn is_empty(&self) -> bool {
matches!(self.kind, ValueKind::Empty)
}
pub const fn bool(value: bool) -> Self {
Self::new(ValueKind::Bool(value))
}
pub fn is_bool(&self) -> bool {
matches!(self.kind, ValueKind::Bool(_))
}
pub const fn char(value: char) -> Self {
Self::new(ValueKind::Char(value))
}
pub fn is_char(&self) -> bool {
matches!(self.kind, ValueKind::Char(_))
}
number!(u8, U8, u8, is_u8, "42");
number!(u16, U16, u16, is_u16, "42");
number!(u32, U32, u32, is_u32, "42");
number!(u64, U64, u64, is_u64, "42");
number!(u128, U128, u128, is_u128, "42");
number!(i8, I8, i8, is_i8, "42");
number!(i16, I16, i16, is_i16, "42");
number!(i32, I32, i32, is_i32, "42");
number!(i64, I64, i64, is_i64, "42");
number!(i128, I128, i128, is_i128, "42");
number!(usize, Usize, usize, is_usize, "42");
number!(isize, Isize, isize, is_isize, "42");
number!(f32, F32, f32, is_f32, "3.14");
number!(f64, F64, f64, is_f64, "3.14");
pub fn new_map_in(
iter: impl IntoIterator<Item = (Value<A>, Value<A>)>,
alloc: A,
) -> Result<Self, AllocError> {
let mut entries = Vec::new_in(alloc);
let iter = iter.into_iter();
let (low, _) = iter.size_hint();
entries.reserve(low)?;
for (key, value) in iter {
entries.push((key, value))?;
}
Ok(Self::new(ValueKind::Map(entries)))
}
#[inline]
pub fn into_decoder<const OPT: Options, C, M>(self, cx: C) -> IntoValueDecoder<OPT, C, A, M>
where
C: Context,
{
IntoValueDecoder::new(cx, self)
}
#[inline]
pub fn as_decoder<const OPT: Options, C, M>(&self, cx: C) -> AsValueDecoder<'_, OPT, C, A, M>
where
C: Context,
{
AsValueDecoder::new(cx, self)
}
#[inline]
pub(crate) fn decoder<const OPT: Options, C, M>(&self, cx: C) -> ValueDecoder<'_, OPT, C, A, M>
where
C: Context,
{
ValueDecoder::new(cx, self)
}
pub(crate) fn type_hint(&self) -> TypeHint {
match &self.kind {
ValueKind::Empty => TypeHint::Empty,
ValueKind::Bool(..) => TypeHint::Bool,
ValueKind::Char(..) => TypeHint::Char,
ValueKind::Number(number) => TypeHint::Number(number.type_hint()),
ValueKind::Bytes(bytes) => TypeHint::Bytes(SizeHint::exact(bytes.len())),
ValueKind::String(string) => TypeHint::String(SizeHint::exact(string.len())),
ValueKind::Sequence(sequence) => TypeHint::Sequence(SizeHint::exact(sequence.len())),
ValueKind::Map(map) => TypeHint::Map(SizeHint::exact(map.len())),
ValueKind::Variant(..) => TypeHint::Variant,
ValueKind::Option(..) => TypeHint::Option,
}
}
}
impl<A> fmt::Debug for Value<A>
where
A: Allocator,
{
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match &self.kind {
ValueKind::Empty => write!(f, "()"),
ValueKind::Bool(value) => value.fmt(f),
ValueKind::Char(value) => value.fmt(f),
ValueKind::Number(value) => value.fmt(f),
ValueKind::Bytes(value) => BStr::new(value).fmt(f),
ValueKind::String(value) => value.fmt(f),
ValueKind::Sequence(value) => value.fmt(f),
ValueKind::Map(items) => {
let mut map = f.debug_map();
for (key, value) in items.iter() {
map.entry(key, value);
}
map.finish()
}
ValueKind::Variant(value) => {
let (variant, data) = &**value;
f.debug_struct("Variant")
.field("variant", variant)
.field("data", data)
.finish()
}
ValueKind::Option(value) => match value {
Some(v) => f.debug_tuple("Some").field(v).finish(),
None => f.debug_tuple("None").finish(),
},
}
}
}
impl<A> PartialEq for Value<A>
where
A: Allocator,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
match (&self.kind, &other.kind) {
(ValueKind::Empty, ValueKind::Empty) => true,
(ValueKind::Bool(lhs), ValueKind::Bool(rhs)) => lhs == rhs,
(ValueKind::Char(lhs), ValueKind::Char(rhs)) => lhs == rhs,
(ValueKind::Number(lhs), ValueKind::Number(rhs)) => lhs == rhs,
(ValueKind::Bytes(lhs), ValueKind::Bytes(rhs)) => lhs == rhs,
(ValueKind::String(lhs), ValueKind::String(rhs)) => lhs == rhs,
(ValueKind::Sequence(lhs), ValueKind::Sequence(rhs)) => lhs == rhs,
(ValueKind::Map(lhs), ValueKind::Map(rhs)) => lhs == rhs,
(ValueKind::Variant(lhs), ValueKind::Variant(rhs)) => lhs == rhs,
(ValueKind::Option(lhs), ValueKind::Option(rhs)) => lhs == rhs,
_ => false,
}
}
}
impl<A> PartialOrd for Value<A>
where
A: Allocator,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match (&self.kind, &other.kind) {
(ValueKind::Empty, ValueKind::Empty) => Some(Ordering::Equal),
(ValueKind::Bool(lhs), ValueKind::Bool(rhs)) => lhs.partial_cmp(rhs),
(ValueKind::Char(lhs), ValueKind::Char(rhs)) => lhs.partial_cmp(rhs),
(ValueKind::Number(lhs), ValueKind::Number(rhs)) => lhs.partial_cmp(rhs),
(ValueKind::Bytes(lhs), ValueKind::Bytes(rhs)) => lhs.partial_cmp(rhs),
(ValueKind::String(lhs), ValueKind::String(rhs)) => lhs.partial_cmp(rhs),
(ValueKind::Sequence(lhs), ValueKind::Sequence(rhs)) => lhs.partial_cmp(rhs),
(ValueKind::Map(lhs), ValueKind::Map(rhs)) => lhs.partial_cmp(rhs),
(ValueKind::Variant(lhs), ValueKind::Variant(rhs)) => lhs.partial_cmp(rhs),
(ValueKind::Option(lhs), ValueKind::Option(rhs)) => lhs.partial_cmp(rhs),
_ => None,
}
}
}
pub(crate) enum ValueKind<A>
where
A: Allocator,
{
Empty,
Bool(bool),
Char(char),
Number(Number),
Bytes(Vec<u8, A>),
String(String<A>),
Sequence(Vec<Value<A>, A>),
Map(Vec<(Value<A>, Value<A>), A>),
Variant(Box<(Value<A>, Value<A>), A>),
Option(Option<Box<Value<A>, A>>),
}
impl<A> Clone for ValueKind<A>
where
A: GlobalAllocator,
{
#[inline]
fn clone(&self) -> Self {
match self {
ValueKind::Empty => ValueKind::Empty,
ValueKind::Bool(b) => ValueKind::Bool(*b),
ValueKind::Char(c) => ValueKind::Char(*c),
ValueKind::Number(n) => ValueKind::Number(*n),
ValueKind::Bytes(b) => ValueKind::Bytes(b.clone()),
ValueKind::String(s) => ValueKind::String(s.clone()),
ValueKind::Sequence(s) => ValueKind::Sequence(s.clone()),
ValueKind::Map(m) => ValueKind::Map(m.clone()),
ValueKind::Variant(v) => ValueKind::Variant(v.clone()),
ValueKind::Option(o) => ValueKind::Option(o.clone()),
}
}
}
#[derive(Clone, Copy, PartialEq, PartialOrd)]
#[non_exhaustive]
pub(crate) enum Number {
U8(u8),
U16(u16),
U32(u32),
U64(u64),
U128(u128),
I8(i8),
I16(i16),
I32(i32),
I64(i64),
I128(i128),
Usize(usize),
Isize(isize),
F32(f32),
F64(f64),
}
impl fmt::Debug for Number {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Number::U8(n) => n.fmt(f),
Number::U16(n) => n.fmt(f),
Number::U32(n) => n.fmt(f),
Number::U64(n) => n.fmt(f),
Number::U128(n) => n.fmt(f),
Number::I8(n) => n.fmt(f),
Number::I16(n) => n.fmt(f),
Number::I32(n) => n.fmt(f),
Number::I64(n) => n.fmt(f),
Number::I128(n) => n.fmt(f),
Number::Usize(n) => n.fmt(f),
Number::Isize(n) => n.fmt(f),
Number::F32(n) => n.fmt(f),
Number::F64(n) => n.fmt(f),
}
}
}
impl<M> Encode<M> for Number {
type Encode = Self;
const IS_BITWISE_ENCODE: bool = false;
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
match self {
Number::U8(n) => encoder.encode_u8(*n),
Number::U16(n) => encoder.encode_u16(*n),
Number::U32(n) => encoder.encode_u32(*n),
Number::U64(n) => encoder.encode_u64(*n),
Number::U128(n) => encoder.encode_u128(*n),
Number::I8(n) => encoder.encode_i8(*n),
Number::I16(n) => encoder.encode_i16(*n),
Number::I32(n) => encoder.encode_i32(*n),
Number::I64(n) => encoder.encode_i64(*n),
Number::I128(n) => encoder.encode_i128(*n),
Number::Usize(n) => encoder.encode_usize(*n),
Number::Isize(n) => encoder.encode_isize(*n),
Number::F32(n) => encoder.encode_f32(*n),
Number::F64(n) => encoder.encode_f64(*n),
}
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl Number {
pub(crate) fn type_hint(&self) -> NumberHint {
match self {
Number::U8(_) => NumberHint::U8,
Number::U16(_) => NumberHint::U16,
Number::U32(_) => NumberHint::U32,
Number::U64(_) => NumberHint::U64,
Number::U128(_) => NumberHint::U128,
Number::I8(_) => NumberHint::I8,
Number::I16(_) => NumberHint::I16,
Number::I32(_) => NumberHint::I32,
Number::I64(_) => NumberHint::I64,
Number::I128(_) => NumberHint::I128,
Number::Usize(_) => NumberHint::Usize,
Number::Isize(_) => NumberHint::Isize,
Number::F32(_) => NumberHint::F32,
Number::F64(_) => NumberHint::F64,
}
}
}
struct AnyVisitor;
#[crate::trait_defaults(crate)]
impl<'de, C> Visitor<'de, C> for AnyVisitor
where
C: Context,
{
type Ok = Value<C::Allocator>;
type String = StringVisitor;
type Bytes = BytesVisitor;
#[inline]
fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "value that can be decoded into dynamic container")
}
#[inline]
fn visit_empty(self, _: C) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Empty))
}
#[inline]
fn visit_bool(self, _: C, value: bool) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Bool(value)))
}
#[inline]
fn visit_char(self, _: C, value: char) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Char(value)))
}
#[inline]
fn visit_u8(self, _: C, value: u8) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::U8(value))))
}
#[inline]
fn visit_u16(self, _: C, value: u16) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::U16(value))))
}
#[inline]
fn visit_u32(self, _: C, value: u32) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::U32(value))))
}
#[inline]
fn visit_u64(self, _: C, value: u64) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::U64(value))))
}
#[inline]
fn visit_u128(self, _: C, value: u128) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::U128(value))))
}
#[inline]
fn visit_i8(self, _: C, value: i8) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::I8(value))))
}
#[inline]
fn visit_i16(self, _: C, value: i16) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::I16(value))))
}
#[inline]
fn visit_i32(self, _: C, value: i32) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::I32(value))))
}
#[inline]
fn visit_i64(self, _: C, value: i64) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::I64(value))))
}
#[inline]
fn visit_i128(self, _: C, value: i128) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::I128(value))))
}
#[inline]
fn visit_usize(self, _: C, value: usize) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::Usize(value))))
}
#[inline]
fn visit_isize(self, _: C, value: isize) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::Isize(value))))
}
#[inline]
fn visit_f32(self, _: C, value: f32) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::F32(value))))
}
#[inline]
fn visit_f64(self, _: C, value: f64) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Number(Number::F64(value))))
}
#[inline]
fn visit_none(self, _: C) -> Result<Self::Ok, Self::Error> {
Ok(Value::new(ValueKind::Option(None)))
}
#[inline]
fn visit_some<D>(self, decoder: D) -> Result<Self::Ok, Self::Error>
where
D: Decoder<'de, Cx = C, Error = C::Error, Allocator = C::Allocator>,
{
let cx = decoder.cx();
let value = decoder.decode::<Value<C::Allocator>>()?;
let value = Box::new_in(value, cx.alloc()).map_err(cx.map())?;
Ok(Value::new(ValueKind::Option(Some(value))))
}
#[inline]
fn visit_sequence<D>(self, seq: &mut D) -> Result<Self::Ok, Self::Error>
where
D: ?Sized + SequenceDecoder<'de, Cx = C, Error = Self::Error, Allocator = Self::Allocator>,
{
let cx = seq.cx();
let mut out =
Vec::with_capacity_in(seq.size_hint().or_default(), cx.alloc()).map_err(cx.map())?;
while let Some(item) = seq.try_next()? {
out.push(item).map_err(cx.map())?;
}
Ok(Value::new(ValueKind::Sequence(out)))
}
#[inline]
fn visit_map<D>(self, map: &mut D) -> Result<Self::Ok, D::Error>
where
D: ?Sized + MapDecoder<'de, Cx = C, Error = Self::Error, Allocator = Self::Allocator>,
{
let cx = map.cx();
let mut out =
Vec::with_capacity_in(map.size_hint().or_default(), cx.alloc()).map_err(cx.map())?;
while let Some(mut entry) = map.decode_entry()? {
let first = entry.decode_key()?.decode()?;
let second = entry.decode_value()?.decode()?;
out.push((first, second)).map_err(cx.map())?;
}
Ok(Value::new(ValueKind::Map(out)))
}
#[inline]
fn visit_bytes(self, _: C, _: SizeHint) -> Result<Self::Bytes, Self::Error> {
Ok(BytesVisitor)
}
#[inline]
fn visit_string(self, _: C, _: SizeHint) -> Result<Self::String, Self::Error> {
Ok(StringVisitor)
}
#[inline]
fn visit_variant<D>(self, variant: &mut D) -> Result<Self::Ok, Self::Error>
where
D: ?Sized + VariantDecoder<'de, Cx = C, Error = Self::Error, Allocator = Self::Allocator>,
{
let first = variant.decode_tag()?.decode()?;
let second = variant.decode_value()?.decode()?;
let value =
Box::new_in((first, second), variant.cx().alloc()).map_err(variant.cx().map())?;
Ok(Value::new(ValueKind::Variant(value)))
}
}
impl<'de, M, A> Decode<'de, M, A> for Value<A>
where
A: Allocator,
{
const IS_BITWISE_DECODE: bool = false;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M, Allocator = A>,
{
decoder.decode_any(AnyVisitor)
}
}
struct BytesVisitor;
#[crate::trait_defaults(crate)]
impl<C> UnsizedVisitor<'_, C, [u8]> for BytesVisitor
where
C: Context,
{
type Ok = Value<C::Allocator>;
#[inline]
fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "bytes")
}
#[inline]
fn visit_ref(self, cx: C, b: &[u8]) -> Result<Self::Ok, Self::Error> {
let mut bytes = Vec::with_capacity_in(b.len(), cx.alloc()).map_err(cx.map())?;
bytes.extend_from_slice(b).map_err(cx.map())?;
Ok(Value::new(ValueKind::Bytes(bytes)))
}
}
struct StringVisitor;
#[crate::trait_defaults(crate)]
impl<C> UnsizedVisitor<'_, C, str> for StringVisitor
where
C: Context,
{
type Ok = Value<C::Allocator>;
#[inline]
fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "bytes")
}
#[inline]
fn visit_ref(self, cx: C, s: &str) -> Result<Self::Ok, Self::Error> {
let mut string = String::new_in(cx.alloc());
string.push_str(s).map_err(cx.map())?;
Ok(Value::new(ValueKind::String(string)))
}
}
impl<M, C> Encode<M> for Value<C>
where
C: Allocator,
{
type Encode = Self;
const IS_BITWISE_ENCODE: bool = false;
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
match &self.kind {
ValueKind::Empty => encoder.encode_empty(),
ValueKind::Bool(b) => encoder.encode_bool(*b),
ValueKind::Char(c) => encoder.encode_char(*c),
ValueKind::Number(n) => encoder.encode(n),
ValueKind::Bytes(bytes) => encoder.encode_bytes(bytes),
ValueKind::String(string) => encoder.encode_string(string),
ValueKind::Sequence(values) => encoder.encode_sequence_fn(values.len(), |sequence| {
for value in values.iter() {
sequence.encode_next()?.encode(value)?;
}
Ok(())
}),
ValueKind::Map(values) => {
let hint = values.len();
encoder.encode_map_fn(hint, |map| {
for (first, second) in values.iter() {
map.insert_entry(first, second)?;
}
Ok(())
})
}
ValueKind::Variant(variant) => {
let (tag, variant) = &**variant;
let encoder = encoder.encode_variant()?;
encoder.insert_variant(tag, variant)
}
ValueKind::Option(option) => match option {
Some(value) => encoder.encode_some()?.encode(&**value),
None => encoder.encode_none(),
},
}
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
pub struct IntoValueDecoder<const OPT: Options, C, A, M>
where
C: Context,
A: Allocator,
M: 'static,
{
cx: C,
value: Value<A>,
_marker: PhantomData<M>,
}
impl<const OPT: Options, C, A, M> IntoValueDecoder<OPT, C, A, M>
where
C: Context,
A: Allocator,
M: 'static,
{
#[inline]
pub fn new(cx: C, value: Value<A>) -> Self {
Self {
cx,
value,
_marker: PhantomData,
}
}
}
impl<const OPT: Options, C, A, M> AsDecoder for IntoValueDecoder<OPT, C, A, M>
where
C: Context,
A: Allocator,
M: 'static,
{
type Cx = C;
type Error = C::Error;
type Allocator = C::Allocator;
type Mode = M;
type Decoder<'this>
= ValueDecoder<'this, OPT, C, A, M>
where
Self: 'this;
#[inline]
fn as_decoder(&self) -> Result<Self::Decoder<'_>, Self::Error> {
Ok(self.value.decoder(self.cx))
}
}
pub struct AsValueDecoder<'de, const OPT: Options, C, A, M>
where
C: Context,
A: Allocator,
M: 'static,
{
cx: C,
value: &'de Value<A>,
_marker: PhantomData<M>,
}
impl<'de, const OPT: Options, C, A, M> AsValueDecoder<'de, OPT, C, A, M>
where
C: Context,
A: Allocator,
M: 'static,
{
#[inline]
pub fn new(cx: C, value: &'de Value<A>) -> Self {
Self {
cx,
value,
_marker: PhantomData,
}
}
}
impl<const OPT: Options, C, A, M> AsDecoder for AsValueDecoder<'_, OPT, C, A, M>
where
C: Context,
A: Allocator,
M: 'static,
{
type Cx = C;
type Error = C::Error;
type Allocator = C::Allocator;
type Mode = M;
type Decoder<'this>
= ValueDecoder<'this, OPT, C, A, M>
where
Self: 'this;
#[inline]
fn as_decoder(&self) -> Result<Self::Decoder<'_>, Self::Error> {
Ok(self.value.decoder(self.cx))
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
impl<A> TryFrom<&str> for Value<A>
where
A: GlobalAllocator,
{
type Error = AllocError;
#[inline]
fn try_from(value: &str) -> Result<Self, Self::Error> {
let mut string = String::new_in(A::new());
string.push_str(value)?;
Ok(Value::new(ValueKind::String(string)))
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
impl<A> From<rust_alloc::string::String> for Value<A>
where
A: GlobalAllocator,
{
#[inline]
fn from(value: rust_alloc::string::String) -> Self {
Value::new(ValueKind::String(String::from(value)))
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
impl<A> From<rust_alloc::vec::Vec<Value<A>>> for Value<A>
where
A: GlobalAllocator,
{
#[inline]
fn from(value: rust_alloc::vec::Vec<Value<A>>) -> Self {
Value::new(ValueKind::Sequence(Vec::from(value)))
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
impl<A> TryFrom<&[u8]> for Value<A>
where
A: GlobalAllocator,
{
type Error = AllocError;
#[inline]
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
let mut string = Vec::new_in(A::new());
string.extend_from_slice(value)?;
Ok(Value::new(ValueKind::Bytes(string)))
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
impl<const N: usize, A> TryFrom<&[u8; N]> for Value<A>
where
A: GlobalAllocator,
{
type Error = AllocError;
#[inline]
fn try_from(value: &[u8; N]) -> Result<Self, Self::Error> {
Self::try_from(&value[..])
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
impl<const N: usize, A> TryFrom<[u8; N]> for Value<A>
where
A: GlobalAllocator,
{
type Error = AllocError;
#[inline]
fn try_from(value: [u8; N]) -> Result<Self, Self::Error> {
Self::try_from(&value[..])
}
}
impl<A> From<()> for Value<A>
where
A: Allocator,
{
#[inline]
fn from((): ()) -> Self {
Value::new(ValueKind::Empty)
}
}
impl<A> Clone for Value<A>
where
A: GlobalAllocator,
{
#[inline]
fn clone(&self) -> Self {
Self {
kind: self.kind.clone(),
}
}
}
impl<A> Default for Value<A>
where
A: Allocator,
{
#[inline]
fn default() -> Self {
Self::new(ValueKind::Empty)
}
}
impl<A> From<bool> for Value<A>
where
A: Allocator,
{
#[inline]
fn from(value: bool) -> Self {
Value::new(ValueKind::Bool(value))
}
}
impl<A> From<char> for Value<A>
where
A: Allocator,
{
#[inline]
fn from(value: char) -> Self {
Value::new(ValueKind::Char(value))
}
}
macro_rules! number_from {
($($ty:ty => $variant:ident, $example:expr, $min:expr, $max:expr, $test:ident),* $(,)?) => {
$(
#[doc = concat!(" let value: ", stringify!($ty), " = ", stringify!($example), ";")]
#[doc = concat!(" assert!(value.", stringify!($test), "());")]
#[doc = concat!(" let value: ", stringify!($ty), " = ", stringify!($min), ";")]
#[doc = concat!(" assert!(min.", stringify!($test), "());")]
#[doc = concat!(" let value: ", stringify!($ty), " = ", stringify!($max), ";")]
#[doc = concat!(" assert!(max.", stringify!($test), "());")]
impl<A> From<$ty> for Value<A>
where
A: Allocator,
{
#[inline]
fn from(value: $ty) -> Self {
Value::new(ValueKind::Number(Number::$variant(value)))
}
}
)*
};
}
number_from! {
i8 => I8, 42, i8::MAX, i8::MIN, is_i8,
i16 => I16, 42, i16::MAX, i16::MIN, is_i16,
i32 => I32, 42, i32::MAX, i32::MIN, is_i32,
i64 => I64, 42, i64::MAX, i64::MIN, is_i64,
i128 => I128, 42, i128::MAX, i128::MIN, is_i128,
isize => Isize, 42, isize::MAX, isize::MIN, is_isize,
u8 => U8, 42, u8::MAX, u8::MIN, is_u8,
u16 => U16, 42, u16::MAX, u16::MIN, is_u16,
u32 => U32, 42, u32::MAX, u32::MIN, is_u32,
u64 => U64, 42, u64::MAX, u64::MIN, is_u64,
u128 => U128, 42, u128::MAX, u128::MIN, is_u128,
usize => Usize, 42, usize::MAX, usize::MIN, is_usize,
f32 => F32, 42.42, 0.42, 100000.42, is_f32,
f64 => F64, 42.42, 0.42, 100000.42, is_f64,
}
#[repr(transparent)]
struct BStr([u8]);
impl BStr {
fn new(bytes: &[u8]) -> &Self {
unsafe { &*(bytes as *const [u8] as *const Self) }
}
}
impl fmt::Debug for BStr {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_char('"')?;
for chunk in self.0.utf8_chunks() {
f.write_str(chunk.valid())?;
for b in chunk.invalid() {
write!(f, "\\x{:02x}", b)?;
}
}
f.write_char('"')?;
Ok(())
}
}