···
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")]
32
-
pub fn from_json(json: &'s serde_json::Value) -> Self {
33
-
if let Some(value) = json.as_bool() {
38
+
pub fn from_json(json: &'s serde_json::Value) -> Result<Self, AtDataError> {
39
+
Ok(if let Some(value) = json.as_bool() {
} else if let Some(value) = json.as_i64() {
} else if let Some(value) = json.as_str() {
Self::String(AtprotoStr::new(value))
} else if let Some(value) = json.as_array() {
40
-
Self::Array(Array::from_json(value))
46
+
Self::Array(Array::from_json(value)?)
} 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()))
48
+
Object::from_json(value)?
49
+
} else if json.is_f64() {
50
+
return Err(AtDataError::FloatNotAllowed);
51
-
pub fn from_cbor(cbor: &'s Ipld) -> Self {
56
+
pub fn from_cbor(cbor: &'s Ipld) -> Result<Self, AtDataError> {
Ipld::Null => Data::Null,
Ipld::Bool(bool) => Data::Boolean(*bool),
Ipld::Integer(int) => Data::Integer(*int as i64),
56
-
Ipld::Float(_) => todo!(),
62
+
return Err(AtDataError::FloatNotAllowed);
Ipld::String(string) => Self::String(AtprotoStr::new(string)),
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),
66
+
Ipld::List(iplds) => Self::Array(Array::from_cbor(iplds)?),
67
+
Ipld::Map(btree_map) => Object::from_cbor(btree_map)?,
Ipld::Link(cid) => Self::CidLink(Cid::ipld(*cid)),
···
pub struct Array<'s>(pub Vec<Data<'s>>);
70
-
pub fn from_json(json: &'s Vec<serde_json::Value>) -> Self {
77
+
pub fn from_json(json: &'s Vec<serde_json::Value>) -> Result<Self, AtDataError> {
let mut array = Vec::with_capacity(json.len());
73
-
array.push(Data::from_json(item));
80
+
array.push(Data::from_json(item)?);
77
-
pub fn from_cbor(cbor: &'s Vec<Ipld>) -> Self {
84
+
pub fn from_cbor(cbor: &'s Vec<Ipld>) -> Result<Self, AtDataError> {
let mut array = Vec::with_capacity(cbor.len());
80
-
array.push(Data::from_cbor(item));
87
+
array.push(Data::from_cbor(item)?);
···
pub struct Object<'s>(pub BTreeMap<SmolStr, Data<'s>>);
90
-
pub fn from_json(json: &'s serde_json::Map<String, serde_json::Value>) -> Data<'s> {
98
+
json: &'s serde_json::Map<String, serde_json::Value>,
99
+
) -> Result<Data<'s>, AtDataError> {
if let Some(type_field) = json.get("$type").and_then(|v| v.as_str()) {
if infer_from_type(type_field) == DataModelType::Blob {
if let Some(blob) = json_to_blob(json) {
94
-
return Data::Blob(blob);
103
+
return Ok(Data::Blob(blob));
···
for (key, value) in json {
102
-
map.insert(key.to_smolstr(), Data::from_json(value));
111
+
map.insert(key.to_smolstr(), Data::from_json(value)?);
match string_key_type_guess(key) {
DataModelType::Null if value.is_null() => {
···
if let Some(value) = value.get("$link").and_then(|v| v.as_str()) {
map.insert(key.to_smolstr(), Data::CidLink(Cid::Str(value.into())));
122
-
map.insert(key.to_smolstr(), Object::from_json(value));
131
+
map.insert(key.to_smolstr(), Object::from_json(value)?);
125
-
map.insert(key.to_smolstr(), Data::from_json(value));
134
+
map.insert(key.to_smolstr(), Data::from_json(value)?);
DataModelType::Blob if value.is_object() => {
131
-
Object::from_json(value.as_object().unwrap()),
140
+
Object::from_json(value.as_object().unwrap())?,
DataModelType::Array if value.is_array() => {
137
-
Data::Array(Array::from_json(value.as_array().unwrap())),
146
+
Data::Array(Array::from_json(value.as_array().unwrap())?),
DataModelType::Object if value.is_object() => {
143
-
Object::from_json(value.as_object().unwrap()),
152
+
Object::from_json(value.as_object().unwrap())?,
DataModelType::String(string_type) if value.is_string() => {
insert_string(&mut map, key, value.as_str().unwrap(), string_type);
150
-
map.insert(key.to_smolstr(), Data::from_json(value));
159
+
map.insert(key.to_smolstr(), Data::from_json(value)?);
155
-
Data::Object(Object(map))
164
+
Ok(Data::Object(Object(map)))
158
-
pub fn from_cbor(cbor: &'s BTreeMap<String, Ipld>) -> Data<'s> {
167
+
pub fn from_cbor(cbor: &'s BTreeMap<String, Ipld>) -> Result<Data<'s>, AtDataError> {
if let Some(Ipld::String(type_field)) = cbor.get("$type") {
if infer_from_type(type_field) == DataModelType::Blob {
if let Some(blob) = cbor_to_blob(cbor) {
162
-
return Data::Blob(blob);
171
+
return Ok(Data::Blob(blob));
···
for (key, value) in cbor {
170
-
map.insert(key.to_smolstr(), Data::from_cbor(value));
179
+
map.insert(key.to_smolstr(), Data::from_cbor(value)?);
match (string_key_type_guess(key), value) {
(DataModelType::Null, Ipld::Null) => {
···
map.insert(key.to_smolstr(), Data::Bytes(Bytes::copy_from_slice(value)));
(DataModelType::Blob, Ipld::Map(value)) => {
186
-
map.insert(key.to_smolstr(), Object::from_cbor(value));
195
+
map.insert(key.to_smolstr(), Object::from_cbor(value)?);
(DataModelType::Array, Ipld::List(value)) => {
189
-
map.insert(key.to_smolstr(), Data::Array(Array::from_cbor(value)));
198
+
map.insert(key.to_smolstr(), Data::Array(Array::from_cbor(value)?));
(DataModelType::Object, Ipld::Map(value)) => {
192
-
map.insert(key.to_smolstr(), Object::from_cbor(value));
201
+
map.insert(key.to_smolstr(), Object::from_cbor(value)?);
(DataModelType::String(string_type), Ipld::String(value)) => {
insert_string(&mut map, key, value, string_type);
198
-
map.insert(key.to_smolstr(), Data::from_cbor(value));
207
+
map.insert(key.to_smolstr(), Data::from_cbor(value)?);
203
-
Data::Object(Object(map))
212
+
Ok(Data::Object(Object(map)))
···
string_type: LexiconStringType,
221
+
) -> Result<(), AtDataError> {
LexiconStringType::Datetime => {
if let Ok(datetime) = Datetime::from_str(value) {
···
map.insert(key.to_smolstr(), Data::String(parse_string(value)));
/// smarter parsing to avoid trying as many posibilities.