value_trait/
lib.rs

1//! A crate providing generalised value traits for working with
2//! `JSONesque` values.
3#![warn(unused_extern_crates)]
4#![cfg_attr(feature = "portable", feature(portable_simd))]
5#![deny(
6    clippy::all,
7    clippy::unwrap_used,
8    clippy::unnecessary_unwrap,
9    clippy::pedantic,
10    missing_docs
11)]
12// We might want to revisit inline_always
13#![allow(clippy::module_name_repetitions)]
14
15#[cfg(all(feature = "128bit", feature = "c-abi"))]
16compile_error!(
17    "Combining the features `128bit` and `c-abi` is impossible because i128's \
18    ABI is unstable (see \
19    https://github.com/rust-lang/unsafe-code-guidelines/issues/119). Please \
20    use only one of them in order to compile this crate. If you don't know \
21    where this error is coming from, it's possible that you depend on \
22    value-trait twice indirectly, once with the `c-abi` feature, and once with \
23    the `128bit` feature, and that they have been merged by Cargo."
24);
25
26#[cfg(all(feature = "c-abi", feature = "ordered-float"))]
27compile_error!(
28    "Combining the features `c-abi` and `ordered-float` is impossible because ordered_float::OrderedFloat does not implement `StableAbi`"
29);
30
31use std::borrow::Cow;
32use std::fmt;
33
34mod array;
35/// Traits for serializing JSON
36pub mod generator;
37mod impls;
38mod node;
39mod object;
40mod option;
41/// Prelude for traits
42pub mod prelude;
43
44/// Traits that provide basic interactions, they do have no auto-implementations
45pub mod base;
46
47/// Traits that have derived implementations relying on `base` traitsa
48pub mod derived;
49
50pub use node::StaticNode;
51
52#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53/// An access error for `ValueType`
54pub enum AccessError {
55    /// An access attempt to a Value was made under the
56    /// assumption that it is an Object - the Value however
57    /// wasn't.
58    NotAnObject,
59    /// An access attempt to a Value was made under the
60    /// assumption that it is an Array - the Value however
61    /// wasn't.
62    NotAnArray,
63}
64
65impl fmt::Display for AccessError {
66    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67        match self {
68            Self::NotAnArray => write!(f, "The value is not an array"),
69            Self::NotAnObject => write!(f, "The value is not an object"),
70        }
71    }
72}
73impl std::error::Error for AccessError {}
74
75/// Extended types that have no native representation in JSON
76#[derive(Debug, Clone, Copy, PartialEq, Eq)]
77pub enum ExtendedValueType {
78    /// A 32 bit signed integer value
79    I32,
80    /// A 16 bit signed integer value
81    I16,
82    /// A 8 bit signed integer value
83    I8,
84    /// A 32 bit unsigned integer value
85    U32,
86    /// A 16 bit unsigned integer value
87    U16,
88    /// A 8 bit unsigned integer value
89    U8,
90    /// A useize value
91    Usize,
92    /// A 32 bit floating point value
93    F32,
94    /// A single utf-8 character
95    Char,
96    /// Not a value at all
97    None,
98}
99
100impl Default for ExtendedValueType {
101    fn default() -> Self {
102        Self::None
103    }
104}
105
106impl fmt::Display for ExtendedValueType {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        match self {
109            Self::I32 => write!(f, "i32"),
110            Self::I16 => write!(f, "i16"),
111            Self::I8 => write!(f, "i8"),
112            Self::U32 => write!(f, "u32"),
113            Self::U16 => write!(f, "u16"),
114            Self::U8 => write!(f, "u8"),
115            Self::Usize => write!(f, "usize"),
116            Self::F32 => write!(f, "f32"),
117            Self::Char => write!(f, "char"),
118            Self::None => write!(f, "none"),
119        }
120    }
121}
122
123/// Types of JSON values
124#[derive(Copy, Clone, Debug, PartialEq, Eq)]
125pub enum ValueType {
126    /// null
127    Null,
128    /// a boolean
129    Bool,
130    /// a signed integer type
131    I64,
132    /// a 128 bit signed integer
133    I128,
134    /// a unsigned integer type
135    U64,
136    /// a 128 bit unsigned integer
137    U128,
138    /// a float type
139    F64,
140    /// a string type
141    String,
142    /// an array
143    Array,
144    /// an object
145    Object,
146    /// Extended types that do not have a real representation in JSON
147    Extended(ExtendedValueType),
148    #[cfg(feature = "custom-types")]
149    /// a custom type
150    Custom(&'static str),
151}
152impl fmt::Display for ValueType {
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        match self {
155            Self::Null => write!(f, "null"),
156            Self::Bool => write!(f, "bool"),
157            Self::I64 => write!(f, "i64"),
158            Self::I128 => write!(f, "i128"),
159            Self::U64 => write!(f, "u64"),
160            Self::U128 => write!(f, "u128"),
161            Self::F64 => write!(f, "f64"),
162            Self::String => write!(f, "string"),
163            Self::Array => write!(f, "array"),
164            Self::Object => write!(f, "object"),
165            Self::Extended(ty) => write!(f, "{ty}"),
166            #[cfg(feature = "custom-types")]
167            Self::Custom(name) => write!(f, "{name}"),
168        }
169    }
170}
171
172impl Default for ValueType {
173    fn default() -> Self {
174        Self::Null
175    }
176}
177
178#[allow(clippy::trait_duplication_in_bounds)] // This is a bug From<()> is counted as duplicate
179/// Support of builder methods for traits.
180pub trait ValueBuilder<'input>:
181    Default
182    + From<StaticNode>
183    + From<i8>
184    + From<i16>
185    + From<i32>
186    + From<i64>
187    + From<u8>
188    + From<u16>
189    + From<u32>
190    + From<u64>
191    + From<f32>
192    + From<f64>
193    + From<bool>
194    + From<()>
195    + From<String>
196    + From<&'input str>
197    + From<Cow<'input, str>>
198{
199    /// Returns an empty array with a given capacity
200    fn array_with_capacity(capacity: usize) -> Self;
201    /// Returns an empty object with a given capacity
202    fn object_with_capacity(capacity: usize) -> Self;
203    /// Returns an empty array
204    #[must_use]
205    fn array() -> Self {
206        Self::array_with_capacity(0)
207    }
208    /// Returns an empty object
209    #[must_use]
210    fn object() -> Self {
211        Self::object_with_capacity(0)
212    }
213    /// Returns anull value
214    fn null() -> Self;
215}
216
217/// A type error thrown by the `try_*` functions
218#[derive(Clone, Debug, PartialEq, Eq)]
219pub struct TryTypeError {
220    /// The expected value type
221    pub expected: ValueType,
222    /// The actual value type
223    pub got: ValueType,
224}
225
226impl std::fmt::Display for TryTypeError {
227    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
228        write!(f, "Expected type {}, got {}", self.expected, self.got)
229    }
230}
231
232impl std::error::Error for TryTypeError {}
233
234// /// The `Value` exposes common interface for values, this allows using both/// `BorrowedValue` and `OwnedValue` nearly interchangeable
235// pub trait Value:
236//     Sized
237//     + Index<usize>
238//     + PartialEq<i8>
239//     + PartialEq<i16>
240//     + PartialEq<i32>
241//     + PartialEq<i64>
242//     + PartialEq<i128>
243//     + PartialEq<u8>
244//     + PartialEq<u16>
245//     + PartialEq<u32>
246//     + PartialEq<u64>
247//     + PartialEq<u128>
248//     + PartialEq<f32>
249//     + PartialEq<f64>
250//     + PartialEq<String>
251//     + PartialEq<bool>
252//     + PartialEq<()>
253//     + derived::ValueTryAsScalar
254//     + base::ValueAsContainer
255// {
256// }