value_trait/
base.rs

1use std::io::{self, Write};
2
3use crate::{TryTypeError, ValueType, array::Array, object::Object};
4
5/// Type information on a value
6pub trait TypedValue {
7    /// Gets the type of the current value
8    #[must_use]
9    fn value_type(&self) -> ValueType;
10}
11
12/// Type checks for custom values on a value
13pub trait TypedCustomValue {
14    #[cfg(feature = "custom-types")]
15    /// returns if a type is a custom type
16    fn is_custom(&self) -> bool {
17        false
18    }
19}
20
21/// Access to scalar value types
22pub trait ValueAsScalar {
23    /// Tries to represent the value as a 'null';
24    #[must_use]
25    fn as_null(&self) -> Option<()>;
26
27    /// Tries to represent the value as a bool
28    #[must_use]
29    fn as_bool(&self) -> Option<bool>;
30
31    /// Tries to represent the value as an i128
32    #[inline]
33    #[must_use]
34    fn as_i128(&self) -> Option<i128> {
35        self.as_i64().map(Into::into)
36    }
37
38    /// Tries to represent the value as an i64
39    #[must_use]
40    fn as_i64(&self) -> Option<i64>;
41
42    /// Tries to represent the value as an i32
43    #[inline]
44    #[must_use]
45    fn as_i32(&self) -> Option<i32> {
46        self.as_i64().and_then(|u| u.try_into().ok())
47    }
48
49    /// Tries to represent the value as an i16
50    #[inline]
51    #[must_use]
52    fn as_i16(&self) -> Option<i16> {
53        self.as_i64().and_then(|u| u.try_into().ok())
54    }
55
56    /// Tries to represent the value as an i8
57    #[inline]
58    #[must_use]
59    fn as_i8(&self) -> Option<i8> {
60        self.as_i64().and_then(|u| u.try_into().ok())
61    }
62
63    /// Tries to represent the value as an u128
64    #[inline]
65    #[must_use]
66    fn as_u128(&self) -> Option<u128> {
67        self.as_u64().map(Into::into)
68    }
69
70    /// Tries to represent the value as an u64
71    #[must_use]
72    fn as_u64(&self) -> Option<u64>;
73
74    /// Tries to represent the value as an usize
75    #[inline]
76    #[must_use]
77    fn as_usize(&self) -> Option<usize> {
78        self.as_u64().and_then(|u| u.try_into().ok())
79    }
80
81    /// Tries to represent the value as an u32
82    #[inline]
83    #[must_use]
84    fn as_u32(&self) -> Option<u32> {
85        self.as_u64().and_then(|u| u.try_into().ok())
86    }
87    /// Tries to represent the value as an u16
88    #[inline]
89    #[must_use]
90    fn as_u16(&self) -> Option<u16> {
91        self.as_u64().and_then(|u| u.try_into().ok())
92    }
93
94    /// Tries to represent the value as an u8
95    #[inline]
96    #[must_use]
97    fn as_u8(&self) -> Option<u8> {
98        self.as_u64().and_then(|u| u.try_into().ok())
99    }
100
101    /// Tries to represent the value as a f64
102    #[must_use]
103    fn as_f64(&self) -> Option<f64>;
104
105    /// Tries to represent the value as a f32
106    #[inline]
107    #[must_use]
108    fn as_f32(&self) -> Option<f32> {
109        self.as_f64().and_then(|u| {
110            if u <= f64::from(f32::MAX) && u >= f64::from(f32::MIN) {
111                // Since we check above
112                #[allow(clippy::cast_possible_truncation)]
113                Some(u as f32)
114            } else {
115                None
116            }
117        })
118    }
119
120    /// Casts the current value to a f64 if possible, this will turn integer
121    /// values into floats.
122    #[must_use]
123    #[inline]
124    #[allow(clippy::cast_precision_loss, clippy::option_if_let_else)]
125    fn cast_f64(&self) -> Option<f64> {
126        if let Some(f) = self.as_f64() {
127            Some(f)
128        } else if let Some(u) = self.as_u128() {
129            Some(u as f64)
130        } else {
131            self.as_i128().map(|i| i as f64)
132        }
133    }
134
135    /// Tries to represent the value as a &str
136    #[must_use]
137    fn as_str(&self) -> Option<&str>;
138
139    /// Tries to represent the value as a Char
140    #[inline]
141    #[must_use]
142    fn as_char(&self) -> Option<char> {
143        self.as_str().and_then(|s| s.chars().next())
144    }
145}
146
147/// Trait to allow accessing data inside a Value
148pub trait ValueAsArray {
149    /// The array structure
150    type Array: Array;
151
152    /// Tries to represent the value as an array and returns a reference to it
153    #[must_use]
154    fn as_array(&self) -> Option<&Self::Array>;
155}
156
157/// Trait to allow Value as an object
158pub trait ValueAsObject {
159    /// The object structure
160    type Object: Object;
161
162    /// Tries to represent the value as an object and returns a reference to it
163    #[must_use]
164    fn as_object(&self) -> Option<&Self::Object>;
165}
166
167/// Mutatability for Array values
168pub trait ValueAsMutArray {
169    /// The type for Arrays
170    type Array;
171    /// Tries to represent the value as an array and returns a mutable reference to it
172    fn as_array_mut(&mut self) -> Option<&mut Self::Array>;
173}
174
175/// `try_as_array_mut` access to array value types
176pub trait ValueTryAsArrayMut {
177    /// The array structure
178    type Array: Array;
179
180    /// Tries to represent the value as an array and returns a mutable reference to it
181    /// # Errors
182    /// if the requested type doesn't match the actual type
183    fn try_as_array_mut(&mut self) -> Result<&mut Self::Array, TryTypeError>;
184}
185
186/// Mutatability for Object values
187pub trait ValueAsMutObject {
188    /// The type for Objects
189    type Object;
190    /// Tries to represent the value as an object and returns a mutable reference to it
191    fn as_object_mut(&mut self) -> Option<&mut Self::Object>;
192}
193/// Mutatability for Object values
194pub trait ValueTryAsMutObject {
195    /// The type for Objects
196    type Object;
197    /// Tries to represent the value as an object and returns a mutable reference to it
198    /// # Errors
199    /// if the requested type doesn't match the actual type
200    fn try_as_object_mut(&mut self) -> Result<&mut Self::Object, TryTypeError>;
201}
202
203/// A trait that specifies how to turn the Value `into` it's sub types
204pub trait ValueIntoString {
205    /// The type for Strings
206    type String;
207
208    /// Tries to turn the value into it's string representation
209    #[must_use]
210    fn into_string(self) -> Option<Self::String>;
211}
212
213/// A trait that specifies how to turn the Value `into` it's sub types
214pub trait ValueIntoArray {
215    /// The type for Arrays
216    type Array;
217
218    /// Tries to turn the value into it's array representation
219    #[must_use]
220    fn into_array(self) -> Option<Self::Array>;
221}
222/// A trait that specifies how to turn the Value `into` it's sub types
223pub trait ValueIntoObject {
224    /// The type for Objects
225    type Object;
226
227    /// Tries to turn the value into it's object representation
228    #[must_use]
229    fn into_object(self) -> Option<Self::Object>;
230}
231
232/// A Value that can be serialized and written
233pub trait Writable {
234    /// Encodes the value into it's JSON representation as a string
235    #[must_use]
236    fn encode(&self) -> String;
237
238    /// Encodes the value into it's JSON representation as a string (pretty printed)
239    #[must_use]
240    fn encode_pp(&self) -> String;
241
242    /// Encodes the value into it's JSON representation into a Writer
243    ///
244    /// # Errors
245    ///
246    /// Will return `Err` if an IO error is encountered
247    fn write<'writer, W>(&self, w: &mut W) -> io::Result<()>
248    where
249        W: 'writer + Write;
250
251    /// Encodes the value into it's JSON representation into a Writer, pretty printed
252    ///
253    /// # Errors
254    ///
255    /// Will return `Err` if an IO error is encountered.
256    fn write_pp<'writer, W>(&self, w: &mut W) -> io::Result<()>
257    where
258        W: 'writer + Write;
259}