1use std::collections::BTreeMap;
2
3pub mod export;
4mod json;
5mod sorting;
6use thiserror::Error;
7
8#[derive(Clone, Debug)]
11#[allow(missing_docs)]
12pub enum Value {
13 Null,
14 Int64(i64),
15 Float64(f64),
16 Boolean(bool),
17 String(String),
18 Bytes(Vec<u8>),
19 Array(Vec<Value>),
20 Object(BTreeMap<String, Value>),
21}
22
23impl<T: Into<Value>> From<Option<T>> for Value {
24 fn from(v: Option<T>) -> Value {
25 v.map(|v| v.into()).unwrap_or(Value::Null)
26 }
27}
28
29impl From<i64> for Value {
30 fn from(v: i64) -> Value {
31 Value::Int64(v)
32 }
33}
34
35impl From<f64> for Value {
36 fn from(v: f64) -> Value {
37 Value::Float64(v)
38 }
39}
40
41impl From<bool> for Value {
42 fn from(v: bool) -> Value {
43 Value::Boolean(v)
44 }
45}
46
47impl From<&str> for Value {
48 fn from(v: &str) -> Value {
49 Value::String(v.into())
50 }
51}
52
53impl From<String> for Value {
54 fn from(v: String) -> Value {
55 Value::String(v)
56 }
57}
58
59impl From<Vec<u8>> for Value {
60 fn from(v: Vec<u8>) -> Value {
61 Value::Bytes(v)
62 }
63}
64
65impl From<Vec<Value>> for Value {
66 fn from(v: Vec<Value>) -> Value {
67 Value::Array(v)
68 }
69}
70
71#[cfg(any(test, feature = "testing"))]
72mod proptest {
73 use proptest::prelude::*;
74
75 use super::Value;
76
77 impl Arbitrary for Value {
78 type Parameters = ();
79 type Strategy = proptest::strategy::BoxedStrategy<Self>;
80
81 fn arbitrary_with((): Self::Parameters) -> Self::Strategy {
82 value_strategy(4, 32, 8).boxed()
83 }
84 }
85
86 fn value_strategy(
87 depth: usize,
88 node_target: usize,
89 branching: usize,
90 ) -> impl Strategy<Value = Value> {
91 let leaf = prop_oneof![
93 1 => Just(Value::Null),
94 1 => any::<i64>().prop_map(Value::from),
95 1 => (prop::num::f64::ANY | prop::num::f64::SIGNALING_NAN).prop_map(Value::from),
96 1 => any::<bool>().prop_map(Value::from),
97 1 => any::<String>().prop_map(Value::String),
98 1 => any::<Vec<u8>>().prop_map(Value::Bytes),
99 ];
100 leaf.prop_recursive(
101 depth as u32,
102 node_target as u32,
103 branching as u32,
104 move |inner| {
105 prop_oneof![
106 prop::collection::vec(inner.clone(), 0..branching).prop_map(Value::Array),
111 prop::collection::btree_map(any::<String>(), inner, 0..branching)
112 .prop_map(Value::Object),
113 ]
114 },
115 )
116 }
117}
118
119#[derive(Error, Clone, PartialEq, Eq)]
122#[error("{:}", message)]
123pub struct ConvexError {
124 pub message: String,
126 pub data: Value,
129}
130
131impl std::fmt::Debug for ConvexError {
132 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133 let message = &self.message;
134 write!(f, "{message:#?}")
135 }
136}