···
prelude::{BASE64_STANDARD, BASE64_STANDARD_NO_PAD, BASE64_URL_SAFE, BASE64_URL_SAFE_NO_PAD},
6
+
use ipld_core::ipld::Ipld;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use smol_str::{SmolStr, ToSmolStr};
use std::{collections::BTreeMap, str::FromStr};
···
51
+
pub fn from_cbor(cbor: &'s Ipld) -> Self {
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)),
#[derive(Debug, Clone, PartialEq, Eq)]
···
let mut array = Vec::with_capacity(json.len());
array.push(Data::from_json(item));
77
+
pub fn from_cbor(cbor: &'s Vec<Ipld>) -> Self {
78
+
let mut array = Vec::with_capacity(cbor.len());
80
+
array.push(Data::from_cbor(item));
···
Data::Object(Object(map))
299
-
//pub fn from_cbor(cbor: BTreeMap<String, ipld_core::ipld::Ipld>) -> Self {}
321
+
pub fn from_cbor(cbor: &'s BTreeMap<String, Ipld>) -> Data<'s> {
322
+
if let Some(Ipld::String(type_field)) = cbor.get("$type") {
323
+
if infer_from_type(type_field) == DataModelType::Blob {
324
+
if let Some(blob) = cbor_to_blob(cbor) {
325
+
return Data::Blob(blob);
329
+
let mut map = BTreeMap::new();
331
+
for (key, value) in cbor {
332
+
if key == "$type" {
333
+
continue; // skip, because we've already handled it
335
+
match string_key_type_guess(key) {
336
+
DataModelType::Null => {
337
+
if *value == Ipld::Null {
338
+
map.insert(key.to_smolstr(), Data::Null);
340
+
map.insert(key.to_smolstr(), Data::from_cbor(value));
343
+
DataModelType::Boolean => {
344
+
if let Ipld::Bool(value) = value {
345
+
map.insert(key.to_smolstr(), Data::Boolean(*value));
347
+
map.insert(key.to_smolstr(), Data::from_cbor(value));
350
+
DataModelType::Integer => {
351
+
if let Ipld::Integer(int) = value {
352
+
map.insert(key.to_smolstr(), Data::Integer(*int as i64));
354
+
map.insert(key.to_smolstr(), Data::from_cbor(value));
357
+
DataModelType::Bytes => {
358
+
if let Ipld::Bytes(value) = value {
359
+
map.insert(key.to_smolstr(), Data::Bytes(Bytes::copy_from_slice(value)));
361
+
map.insert(key.to_smolstr(), Data::from_cbor(value));
364
+
DataModelType::Blob => {
365
+
if let Ipld::Map(value) = value {
366
+
map.insert(key.to_smolstr(), Object::from_cbor(value));
368
+
map.insert(key.to_smolstr(), Data::from_cbor(value));
371
+
DataModelType::Array => {
372
+
if let Ipld::List(value) = value {
373
+
map.insert(key.to_smolstr(), Data::Array(Array::from_cbor(value)));
375
+
map.insert(key.to_smolstr(), Data::from_cbor(value));
378
+
DataModelType::Object => {
379
+
if let Ipld::Map(value) = value {
380
+
map.insert(key.to_smolstr(), Object::from_cbor(value));
382
+
map.insert(key.to_smolstr(), Data::from_cbor(value));
385
+
DataModelType::String(string_type) => {
386
+
if let Ipld::String(value) = value {
387
+
match string_type {
388
+
LexiconStringType::Datetime => {
389
+
if let Ok(datetime) = Datetime::from_str(value) {
392
+
Data::String(AtprotoStr::Datetime(datetime)),
397
+
Data::String(AtprotoStr::String(value.into())),
401
+
LexiconStringType::AtUri => {
402
+
if let Ok(value) = AtUri::new(value) {
405
+
Data::String(AtprotoStr::AtUri(value)),
410
+
Data::String(AtprotoStr::String(value.into())),
414
+
LexiconStringType::Did => {
415
+
if let Ok(value) = Did::new(value) {
418
+
Data::String(AtprotoStr::Did(value)),
423
+
Data::String(AtprotoStr::String(value.into())),
427
+
LexiconStringType::Handle => {
428
+
if let Ok(value) = Handle::new(value) {
431
+
Data::String(AtprotoStr::Handle(value)),
436
+
Data::String(AtprotoStr::String(value.into())),
440
+
LexiconStringType::AtIdentifier => {
441
+
if let Ok(value) = AtIdentifier::new(value) {
444
+
Data::String(AtprotoStr::AtIdentifier(value)),
449
+
Data::String(AtprotoStr::String(value.into())),
453
+
LexiconStringType::Nsid => {
454
+
if let Ok(value) = Nsid::new(value) {
457
+
Data::String(AtprotoStr::Nsid(value)),
462
+
Data::String(AtprotoStr::String(value.into())),
466
+
LexiconStringType::Cid => {
467
+
if let Ok(value) = Cid::new(value.as_bytes()) {
470
+
Data::String(AtprotoStr::Cid(value)),
475
+
Data::String(AtprotoStr::String(value.into())),
479
+
LexiconStringType::Language => {
480
+
if let Ok(value) = Language::new(value) {
483
+
Data::String(AtprotoStr::Language(value)),
488
+
Data::String(AtprotoStr::String(value.into())),
492
+
LexiconStringType::Tid => {
493
+
if let Ok(value) = Tid::new(value) {
496
+
Data::String(AtprotoStr::Tid(value)),
501
+
Data::String(AtprotoStr::String(value.into())),
505
+
LexiconStringType::RecordKey => {
506
+
if let Ok(value) = Rkey::new(value) {
509
+
Data::String(AtprotoStr::RecordKey(RecordKey::from(value))),
514
+
Data::String(AtprotoStr::String(value.into())),
518
+
LexiconStringType::Uri(_) => {
519
+
if let Ok(uri) = Uri::new(value) {
522
+
Data::String(AtprotoStr::Uri(uri)),
527
+
Data::String(AtprotoStr::String(value.into())),
531
+
LexiconStringType::String => {
532
+
map.insert(key.to_smolstr(), Data::String(parse_string(value)));
536
+
map.insert(key.to_smolstr(), Data::from_cbor(value));
540
+
map.insert(key.to_smolstr(), Data::from_cbor(value));
545
+
Data::Object(Object(map))
/// smarter parsing to avoid trying as many posibilities.
···
// or Ipld value is at least a string, and then we fall back to Object/Map.
_ => DataModelType::String(LexiconStringType::String),
629
+
pub fn cbor_to_blob<'b>(blob: &'b BTreeMap<String, Ipld>) -> Option<Blob<'b>> {
630
+
let mime_type = blob.get("mimeType").and_then(|o| {
631
+
if let Ipld::String(string) = o {
637
+
if let Some(value) = blob.get("ref") {
638
+
if let Ipld::Map(value) = value {
639
+
if let Some(Ipld::String(value)) = value.get("$link") {
640
+
let size = blob.get("size").and_then(|o| {
641
+
if let Ipld::Integer(i) = o {
647
+
if let (Some(mime_type), Some(size)) = (mime_type, size) {
649
+
r#ref: Cid::str(value),
650
+
mime_type: MimeType::raw(mime_type),
651
+
size: size as usize,
656
+
} else if let Some(Ipld::String(value)) = blob.get("cid") {
657
+
if let Some(mime_type) = mime_type {
659
+
r#ref: Cid::str(value),
660
+
mime_type: MimeType::raw(mime_type),
pub fn json_to_blob<'b>(blob: &'b serde_json::Map<String, serde_json::Value>) -> Option<Blob<'b>> {