oca_rs/facade/
bundle.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
use std::io::Read;

use oca_bundle_semantics::state::oca::OCABundle as StructuralBundle;
use said::derivation::HashFunctionCode;
use said::{sad::SerializationFormats, sad::SAD};
use said::version::SerializationInfo;
use serde::{Deserialize, Serialize};

pub type GenericError = Box<dyn std::error::Error + Sync + Send>;

pub fn load_oca(source: &mut dyn Read) -> Result<Bundle, GenericError> {
    let oca: Bundle = serde_json::from_reader(source)?;
    Ok(oca)
}

#[derive(Debug)]
pub enum BundleElement {
    Structural(StructuralBundle),
    Transformation(transformation_file::state::Transformation),
}

#[derive(SAD, Serialize, Debug, Deserialize, Clone)]
#[version(protocol = "B", major = 1, minor = 0)]
pub struct Bundle {
    #[said]
    #[serde(rename = "d")]
    pub said: Option<said::SelfAddressingIdentifier>,
    #[serde(rename = "m")]
    pub structural: Option<StructuralBundle>,
    #[serde(rename = "t")]
    pub transformations: Vec<transformation_file::state::Transformation>,
}

impl Bundle {
    pub fn new() -> Self {
        Self {
            said: None,
            structural: None,
            transformations: vec![],
        }
    }

    pub fn add(&mut self, element: BundleElement) {
        match element {
            BundleElement::Structural(structural) => self.add_structural(structural),
            BundleElement::Transformation(transformation) => self.add_transformation(transformation),
        }
    }

    fn add_structural(&mut self, structural: StructuralBundle) {
        self.structural = Some(structural);
    }

    fn add_transformation(&mut self, transformation: transformation_file::state::Transformation) {
        self.transformations.push(transformation);
    }

    pub fn fill_said(&mut self) {
        let code = HashFunctionCode::Blake3_256;
        let format = SerializationFormats::JSON;
        self.compute_digest(&code, &format);
    }

    pub fn encode(&self) -> Result<String, serde_json::Error> {
        let code = HashFunctionCode::Blake3_256;
        let format = SerializationFormats::JSON;

        let structural = self.structural.as_ref().unwrap();
        let structural_str = String::from_utf8(structural.encode(&code, &format).unwrap()).unwrap();

        let mut transformations_str = String::new();
        let mut transformations_iter = self.transformations.iter().peekable();
        while let Some(transformation) = transformations_iter.next() {
            let s = String::from_utf8(transformation.encode(&code, &format).unwrap()).unwrap();
            let transformation_str = match transformations_iter.peek() {
                Some(_) => format!("{},", s),
                None => s,
            };
            transformations_str.push_str(&transformation_str);
        };

        let result = format!(
            r#"{{"d":"","m":{},"t":[{}]}}"#,
            structural_str,
            transformations_str
        );

        let protocol_version = said::ProtocolVersion::new("OCAB", 0, 0).unwrap();
        let versioned_result = said::make_me_sad(&result, code, protocol_version).unwrap();

        Ok(versioned_result)
    }
}

impl Default for Bundle {
    fn default() -> Self {
        Self::new()
    }
}