Skip to main content

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, Default)]
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    #[default]
98    None,
99}
100
101impl fmt::Display for ExtendedValueType {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        match self {
104            Self::I32 => write!(f, "i32"),
105            Self::I16 => write!(f, "i16"),
106            Self::I8 => write!(f, "i8"),
107            Self::U32 => write!(f, "u32"),
108            Self::U16 => write!(f, "u16"),
109            Self::U8 => write!(f, "u8"),
110            Self::Usize => write!(f, "usize"),
111            Self::F32 => write!(f, "f32"),
112            Self::Char => write!(f, "char"),
113            Self::None => write!(f, "none"),
114        }
115    }
116}
117
118/// Types of JSON values
119#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
120pub enum ValueType {
121    /// null
122    #[default]
123    Null,
124    /// a boolean
125    Bool,
126    /// a signed integer type
127    I64,
128    /// a 128 bit signed integer
129    I128,
130    /// a unsigned integer type
131    U64,
132    /// a 128 bit unsigned integer
133    U128,
134    /// a float type
135    F64,
136    /// a string type
137    String,
138    /// an array
139    Array,
140    /// an object
141    Object,
142    /// Extended types that do not have a real representation in JSON
143    Extended(ExtendedValueType),
144    #[cfg(feature = "custom-types")]
145    /// a custom type
146    Custom(&'static str),
147}
148impl fmt::Display for ValueType {
149    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150        match self {
151            Self::Null => write!(f, "null"),
152            Self::Bool => write!(f, "bool"),
153            Self::I64 => write!(f, "i64"),
154            Self::I128 => write!(f, "i128"),
155            Self::U64 => write!(f, "u64"),
156            Self::U128 => write!(f, "u128"),
157            Self::F64 => write!(f, "f64"),
158            Self::String => write!(f, "string"),
159            Self::Array => write!(f, "array"),
160            Self::Object => write!(f, "object"),
161            Self::Extended(ty) => write!(f, "{ty}"),
162            #[cfg(feature = "custom-types")]
163            Self::Custom(name) => write!(f, "{name}"),
164        }
165    }
166}
167
168#[allow(clippy::trait_duplication_in_bounds)] // This is a bug From<()> is counted as duplicate
169/// Support of builder methods for traits.
170pub trait ValueBuilder<'input>:
171    Default
172    + From<StaticNode>
173    + From<i8>
174    + From<i16>
175    + From<i32>
176    + From<i64>
177    + From<u8>
178    + From<u16>
179    + From<u32>
180    + From<u64>
181    + From<f32>
182    + From<f64>
183    + From<bool>
184    + From<()>
185    + From<String>
186    + From<&'input str>
187    + From<Cow<'input, str>>
188{
189    /// Returns an empty array with a given capacity
190    fn array_with_capacity(capacity: usize) -> Self;
191    /// Returns an empty object with a given capacity
192    fn object_with_capacity(capacity: usize) -> Self;
193    /// Returns an empty array
194    #[must_use]
195    fn array() -> Self {
196        Self::array_with_capacity(0)
197    }
198    /// Returns an empty object
199    #[must_use]
200    fn object() -> Self {
201        Self::object_with_capacity(0)
202    }
203    /// Returns anull value
204    fn null() -> Self;
205}
206
207/// A type error thrown by the `try_*` functions
208#[derive(Clone, Debug, PartialEq, Eq)]
209pub struct TryTypeError {
210    /// The expected value type
211    pub expected: ValueType,
212    /// The actual value type
213    pub got: ValueType,
214}
215
216impl std::fmt::Display for TryTypeError {
217    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
218        write!(f, "Expected type {}, got {}", self.expected, self.got)
219    }
220}
221
222impl std::error::Error for TryTypeError {}
223
224// /// The `Value` exposes common interface for values, this allows using both/// `BorrowedValue` and `OwnedValue` nearly interchangeable
225// pub trait Value:
226//     Sized
227//     + Index<usize>
228//     + PartialEq<i8>
229//     + PartialEq<i16>
230//     + PartialEq<i32>
231//     + PartialEq<i64>
232//     + PartialEq<i128>
233//     + PartialEq<u8>
234//     + PartialEq<u16>
235//     + PartialEq<u32>
236//     + PartialEq<u64>
237//     + PartialEq<u128>
238//     + PartialEq<f32>
239//     + PartialEq<f64>
240//     + PartialEq<String>
241//     + PartialEq<bool>
242//     + PartialEq<()>
243//     + derived::ValueTryAsScalar
244//     + base::ValueAsContainer
245// {
246// }