1use std::io::Read;
2
3use oca_bundle_semantics::state::oca::OCABundle as StructuralBundle;
4use said::derivation::HashFunctionCode;
5use said::version::SerializationInfo;
6use said::{sad::SerializationFormats, sad::SAD};
7use serde::{Deserialize, Serialize};
8
9pub type GenericError = Box<dyn std::error::Error + Sync + Send>;
10
11pub fn load_oca(source: &mut dyn Read) -> Result<Bundle, GenericError> {
12 let oca: Bundle = serde_json::from_reader(source)?;
13 Ok(oca)
14}
15
16#[derive(Debug)]
17pub enum BundleElement {
18 Structural(StructuralBundle),
19 Transformation(transformation_file::state::Transformation),
20}
21
22#[derive(SAD, Serialize, Debug, Deserialize, Clone)]
23#[version(protocol = "B", major = 1, minor = 0)]
24pub struct Bundle {
25 #[said]
26 #[serde(rename = "d")]
27 pub said: Option<said::SelfAddressingIdentifier>,
28 #[serde(rename = "m")]
29 pub structural: Option<StructuralBundle>,
30 #[serde(rename = "t")]
31 pub transformations: Vec<transformation_file::state::Transformation>,
32}
33
34impl Bundle {
35 pub fn new() -> Self {
36 Self {
37 said: None,
38 structural: None,
39 transformations: vec![],
40 }
41 }
42
43 pub fn add(&mut self, element: BundleElement) {
44 match element {
45 BundleElement::Structural(structural) => self.add_structural(structural),
46 BundleElement::Transformation(transformation) => {
47 self.add_transformation(transformation)
48 }
49 }
50 }
51
52 fn add_structural(&mut self, structural: StructuralBundle) {
53 self.structural = Some(structural);
54 }
55
56 fn add_transformation(&mut self, transformation: transformation_file::state::Transformation) {
57 self.transformations.push(transformation);
58 }
59
60 pub fn fill_said(&mut self) {
61 let code = HashFunctionCode::Blake3_256;
62 let format = SerializationFormats::JSON;
63 self.compute_digest(&code, &format);
64 }
65
66 pub fn encode(&self) -> Result<String, serde_json::Error> {
67 let code = HashFunctionCode::Blake3_256;
68 let format = SerializationFormats::JSON;
69
70 let structural = self.structural.as_ref().unwrap();
71 let structural_str = String::from_utf8(structural.encode(&code, &format).unwrap()).unwrap();
72
73 let mut transformations_str = String::new();
74 let mut transformations_iter = self.transformations.iter().peekable();
75 while let Some(transformation) = transformations_iter.next() {
76 let s = String::from_utf8(transformation.encode(&code, &format).unwrap()).unwrap();
77 let transformation_str = match transformations_iter.peek() {
78 Some(_) => format!("{},", s),
79 None => s,
80 };
81 transformations_str.push_str(&transformation_str);
82 }
83
84 let result = format!(
85 r#"{{"d":"","m":{},"t":[{}]}}"#,
86 structural_str, transformations_str
87 );
88
89 let protocol_version = said::ProtocolVersion::new("OCAB", 0, 0).unwrap();
90 let versioned_result = said::make_me_sad(&result, code, protocol_version).unwrap();
91
92 Ok(versioned_result)
93 }
94}
95
96impl Default for Bundle {
97 fn default() -> Self {
98 Self::new()
99 }
100}