+49
-39
crates/jacquard-common/src/types/value.rs
+49
-39
crates/jacquard-common/src/types/value.rs
···
28
Blob(Blob<'s>),
29
}
30
31
impl<'s> Data<'s> {
32
-
pub fn from_json(json: &'s serde_json::Value) -> Self {
33
-
if let Some(value) = json.as_bool() {
34
Self::Boolean(value)
35
} else if let Some(value) = json.as_i64() {
36
Self::Integer(value)
37
} else if let Some(value) = json.as_str() {
38
Self::String(AtprotoStr::new(value))
39
} else if let Some(value) = json.as_array() {
40
-
Self::Array(Array::from_json(value))
41
} else if let Some(value) = json.as_object() {
42
-
Object::from_json(value)
43
-
} else if let Some(num) = json.as_number() {
44
-
// deliberately permissive here, just in case.
45
-
Self::String(AtprotoStr::new_owned(num.to_smolstr()))
46
} else {
47
Self::Null
48
-
}
49
}
50
51
-
pub fn from_cbor(cbor: &'s Ipld) -> Self {
52
-
match cbor {
53
Ipld::Null => Data::Null,
54
Ipld::Bool(bool) => Data::Boolean(*bool),
55
Ipld::Integer(int) => Data::Integer(*int as i64),
56
-
Ipld::Float(_) => todo!(),
57
Ipld::String(string) => Self::String(AtprotoStr::new(string)),
58
Ipld::Bytes(items) => Self::Bytes(Bytes::copy_from_slice(items.as_slice())),
59
-
Ipld::List(iplds) => Self::Array(Array::from_cbor(iplds)),
60
-
Ipld::Map(btree_map) => Object::from_cbor(btree_map),
61
Ipld::Link(cid) => Self::CidLink(Cid::ipld(*cid)),
62
-
}
63
}
64
}
65
···
67
pub struct Array<'s>(pub Vec<Data<'s>>);
68
69
impl<'s> Array<'s> {
70
-
pub fn from_json(json: &'s Vec<serde_json::Value>) -> Self {
71
let mut array = Vec::with_capacity(json.len());
72
for item in json {
73
-
array.push(Data::from_json(item));
74
}
75
-
Self(array)
76
}
77
-
pub fn from_cbor(cbor: &'s Vec<Ipld>) -> Self {
78
let mut array = Vec::with_capacity(cbor.len());
79
for item in cbor {
80
-
array.push(Data::from_cbor(item));
81
}
82
-
Self(array)
83
}
84
}
85
···
87
pub struct Object<'s>(pub BTreeMap<SmolStr, Data<'s>>);
88
89
impl<'s> Object<'s> {
90
-
pub fn from_json(json: &'s serde_json::Map<String, serde_json::Value>) -> Data<'s> {
91
if let Some(type_field) = json.get("$type").and_then(|v| v.as_str()) {
92
if infer_from_type(type_field) == DataModelType::Blob {
93
if let Some(blob) = json_to_blob(json) {
94
-
return Data::Blob(blob);
95
}
96
}
97
}
···
99
100
for (key, value) in json {
101
if key == "$type" {
102
-
map.insert(key.to_smolstr(), Data::from_json(value));
103
}
104
match string_key_type_guess(key) {
105
DataModelType::Null if value.is_null() => {
···
119
if let Some(value) = value.get("$link").and_then(|v| v.as_str()) {
120
map.insert(key.to_smolstr(), Data::CidLink(Cid::Str(value.into())));
121
} else {
122
-
map.insert(key.to_smolstr(), Object::from_json(value));
123
}
124
} else {
125
-
map.insert(key.to_smolstr(), Data::from_json(value));
126
}
127
}
128
DataModelType::Blob if value.is_object() => {
129
map.insert(
130
key.to_smolstr(),
131
-
Object::from_json(value.as_object().unwrap()),
132
);
133
}
134
DataModelType::Array if value.is_array() => {
135
map.insert(
136
key.to_smolstr(),
137
-
Data::Array(Array::from_json(value.as_array().unwrap())),
138
);
139
}
140
DataModelType::Object if value.is_object() => {
141
map.insert(
142
key.to_smolstr(),
143
-
Object::from_json(value.as_object().unwrap()),
144
);
145
}
146
DataModelType::String(string_type) if value.is_string() => {
147
insert_string(&mut map, key, value.as_str().unwrap(), string_type);
148
}
149
_ => {
150
-
map.insert(key.to_smolstr(), Data::from_json(value));
151
}
152
}
153
}
154
155
-
Data::Object(Object(map))
156
}
157
158
-
pub fn from_cbor(cbor: &'s BTreeMap<String, Ipld>) -> Data<'s> {
159
if let Some(Ipld::String(type_field)) = cbor.get("$type") {
160
if infer_from_type(type_field) == DataModelType::Blob {
161
if let Some(blob) = cbor_to_blob(cbor) {
162
-
return Data::Blob(blob);
163
}
164
}
165
}
···
167
168
for (key, value) in cbor {
169
if key == "$type" {
170
-
map.insert(key.to_smolstr(), Data::from_cbor(value));
171
}
172
match (string_key_type_guess(key), value) {
173
(DataModelType::Null, Ipld::Null) => {
···
183
map.insert(key.to_smolstr(), Data::Bytes(Bytes::copy_from_slice(value)));
184
}
185
(DataModelType::Blob, Ipld::Map(value)) => {
186
-
map.insert(key.to_smolstr(), Object::from_cbor(value));
187
}
188
(DataModelType::Array, Ipld::List(value)) => {
189
-
map.insert(key.to_smolstr(), Data::Array(Array::from_cbor(value)));
190
}
191
(DataModelType::Object, Ipld::Map(value)) => {
192
-
map.insert(key.to_smolstr(), Object::from_cbor(value));
193
}
194
(DataModelType::String(string_type), Ipld::String(value)) => {
195
insert_string(&mut map, key, value, string_type);
196
}
197
_ => {
198
-
map.insert(key.to_smolstr(), Data::from_cbor(value));
199
}
200
}
201
}
202
203
-
Data::Object(Object(map))
204
}
205
}
206
···
209
key: &'s str,
210
value: &'s str,
211
string_type: LexiconStringType,
212
-
) {
213
match string_type {
214
LexiconStringType::Datetime => {
215
if let Ok(datetime) = Datetime::from_str(value) {
···
334
map.insert(key.to_smolstr(), Data::String(parse_string(value)));
335
}
336
}
337
}
338
339
/// smarter parsing to avoid trying as many posibilities.
···
28
Blob(Blob<'s>),
29
}
30
31
+
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error, miette::Diagnostic)]
32
+
pub enum AtDataError {
33
+
#[error("floating point numbers not allowed in AT protocol data")]
34
+
FloatNotAllowed,
35
+
}
36
+
37
impl<'s> Data<'s> {
38
+
pub fn from_json(json: &'s serde_json::Value) -> Result<Self, AtDataError> {
39
+
Ok(if let Some(value) = json.as_bool() {
40
Self::Boolean(value)
41
} else if let Some(value) = json.as_i64() {
42
Self::Integer(value)
43
} else if let Some(value) = json.as_str() {
44
Self::String(AtprotoStr::new(value))
45
} else if let Some(value) = json.as_array() {
46
+
Self::Array(Array::from_json(value)?)
47
} else if let Some(value) = json.as_object() {
48
+
Object::from_json(value)?
49
+
} else if json.is_f64() {
50
+
return Err(AtDataError::FloatNotAllowed);
51
} else {
52
Self::Null
53
+
})
54
}
55
56
+
pub fn from_cbor(cbor: &'s Ipld) -> Result<Self, AtDataError> {
57
+
Ok(match cbor {
58
Ipld::Null => Data::Null,
59
Ipld::Bool(bool) => Data::Boolean(*bool),
60
Ipld::Integer(int) => Data::Integer(*int as i64),
61
+
Ipld::Float(_) => {
62
+
return Err(AtDataError::FloatNotAllowed);
63
+
}
64
Ipld::String(string) => Self::String(AtprotoStr::new(string)),
65
Ipld::Bytes(items) => Self::Bytes(Bytes::copy_from_slice(items.as_slice())),
66
+
Ipld::List(iplds) => Self::Array(Array::from_cbor(iplds)?),
67
+
Ipld::Map(btree_map) => Object::from_cbor(btree_map)?,
68
Ipld::Link(cid) => Self::CidLink(Cid::ipld(*cid)),
69
+
})
70
}
71
}
72
···
74
pub struct Array<'s>(pub Vec<Data<'s>>);
75
76
impl<'s> Array<'s> {
77
+
pub fn from_json(json: &'s Vec<serde_json::Value>) -> Result<Self, AtDataError> {
78
let mut array = Vec::with_capacity(json.len());
79
for item in json {
80
+
array.push(Data::from_json(item)?);
81
}
82
+
Ok(Self(array))
83
}
84
+
pub fn from_cbor(cbor: &'s Vec<Ipld>) -> Result<Self, AtDataError> {
85
let mut array = Vec::with_capacity(cbor.len());
86
for item in cbor {
87
+
array.push(Data::from_cbor(item)?);
88
}
89
+
Ok(Self(array))
90
}
91
}
92
···
94
pub struct Object<'s>(pub BTreeMap<SmolStr, Data<'s>>);
95
96
impl<'s> Object<'s> {
97
+
pub fn from_json(
98
+
json: &'s serde_json::Map<String, serde_json::Value>,
99
+
) -> Result<Data<'s>, AtDataError> {
100
if let Some(type_field) = json.get("$type").and_then(|v| v.as_str()) {
101
if infer_from_type(type_field) == DataModelType::Blob {
102
if let Some(blob) = json_to_blob(json) {
103
+
return Ok(Data::Blob(blob));
104
}
105
}
106
}
···
108
109
for (key, value) in json {
110
if key == "$type" {
111
+
map.insert(key.to_smolstr(), Data::from_json(value)?);
112
}
113
match string_key_type_guess(key) {
114
DataModelType::Null if value.is_null() => {
···
128
if let Some(value) = value.get("$link").and_then(|v| v.as_str()) {
129
map.insert(key.to_smolstr(), Data::CidLink(Cid::Str(value.into())));
130
} else {
131
+
map.insert(key.to_smolstr(), Object::from_json(value)?);
132
}
133
} else {
134
+
map.insert(key.to_smolstr(), Data::from_json(value)?);
135
}
136
}
137
DataModelType::Blob if value.is_object() => {
138
map.insert(
139
key.to_smolstr(),
140
+
Object::from_json(value.as_object().unwrap())?,
141
);
142
}
143
DataModelType::Array if value.is_array() => {
144
map.insert(
145
key.to_smolstr(),
146
+
Data::Array(Array::from_json(value.as_array().unwrap())?),
147
);
148
}
149
DataModelType::Object if value.is_object() => {
150
map.insert(
151
key.to_smolstr(),
152
+
Object::from_json(value.as_object().unwrap())?,
153
);
154
}
155
DataModelType::String(string_type) if value.is_string() => {
156
insert_string(&mut map, key, value.as_str().unwrap(), string_type);
157
}
158
_ => {
159
+
map.insert(key.to_smolstr(), Data::from_json(value)?);
160
}
161
}
162
}
163
164
+
Ok(Data::Object(Object(map)))
165
}
166
167
+
pub fn from_cbor(cbor: &'s BTreeMap<String, Ipld>) -> Result<Data<'s>, AtDataError> {
168
if let Some(Ipld::String(type_field)) = cbor.get("$type") {
169
if infer_from_type(type_field) == DataModelType::Blob {
170
if let Some(blob) = cbor_to_blob(cbor) {
171
+
return Ok(Data::Blob(blob));
172
}
173
}
174
}
···
176
177
for (key, value) in cbor {
178
if key == "$type" {
179
+
map.insert(key.to_smolstr(), Data::from_cbor(value)?);
180
}
181
match (string_key_type_guess(key), value) {
182
(DataModelType::Null, Ipld::Null) => {
···
192
map.insert(key.to_smolstr(), Data::Bytes(Bytes::copy_from_slice(value)));
193
}
194
(DataModelType::Blob, Ipld::Map(value)) => {
195
+
map.insert(key.to_smolstr(), Object::from_cbor(value)?);
196
}
197
(DataModelType::Array, Ipld::List(value)) => {
198
+
map.insert(key.to_smolstr(), Data::Array(Array::from_cbor(value)?));
199
}
200
(DataModelType::Object, Ipld::Map(value)) => {
201
+
map.insert(key.to_smolstr(), Object::from_cbor(value)?);
202
}
203
(DataModelType::String(string_type), Ipld::String(value)) => {
204
insert_string(&mut map, key, value, string_type);
205
}
206
_ => {
207
+
map.insert(key.to_smolstr(), Data::from_cbor(value)?);
208
}
209
}
210
}
211
212
+
Ok(Data::Object(Object(map)))
213
}
214
}
215
···
218
key: &'s str,
219
value: &'s str,
220
string_type: LexiconStringType,
221
+
) -> Result<(), AtDataError> {
222
match string_type {
223
LexiconStringType::Datetime => {
224
if let Ok(datetime) = Datetime::from_str(value) {
···
343
map.insert(key.to_smolstr(), Data::String(parse_string(value)));
344
}
345
}
346
+
Ok(())
347
}
348
349
/// smarter parsing to avoid trying as many posibilities.