oca_rs/facade/
explore.rs

1use crate::data_storage::Namespace;
2use oca_ast_semantics::ast::{BundleContent, CaptureContent, Content, ObjectKind, RefValue};
3use oca_bundle_semantics::state::oca::OCABundle;
4use serde::{ser::SerializeStruct, Serialize};
5use std::collections::HashSet;
6
7use super::Facade;
8
9impl Facade {
10    pub fn explore(&self, said: String) -> Option<Relationship> {
11        let relations_u8_res = self.db.get(Namespace::OCARelations, &said);
12
13        match relations_u8_res {
14            Ok(Some(relations_u8)) => {
15                let relationship: Relationship = relations_u8.into();
16                Some(Relationship {
17                    base_object: OCAObject::new(self, said),
18                    relations: relationship.relations,
19                })
20            }
21            _ => None,
22        }
23    }
24
25    fn insert_oca_objects_metadata(&mut self, oca_bundle: OCABundle) -> Result<(), String> {
26        self.db.insert(
27            Namespace::OCARelations,
28            &format!("{}.metadata", oca_bundle.said.clone().unwrap()),
29            &[ObjectKind::OCABundle(BundleContent {
30                said: oca_ast_semantics::ast::ReferenceAttrType::Reference(RefValue::Name(
31                    "".to_string(),
32                )),
33            })
34            .into()],
35        )?;
36        self.db.insert(
37            Namespace::OCARelations,
38            &format!("{}.metadata", oca_bundle.capture_base.said.clone().unwrap()),
39            &[ObjectKind::CaptureBase(CaptureContent {
40                attributes: None,
41                properties: None,
42                flagged_attributes: None,
43            })
44            .into()],
45        )?;
46        oca_bundle.overlays.iter().for_each(|overlay| {
47            let _ = self.db.insert(
48                Namespace::OCARelations,
49                &format!("{}.metadata", overlay.said().clone().unwrap()),
50                &[ObjectKind::Overlay(
51                    overlay.overlay_type().clone(),
52                    Content {
53                        attributes: None,
54                        properties: None,
55                    },
56                )
57                .into()],
58            );
59        });
60
61        Ok(())
62    }
63
64    pub fn add_relations(&mut self, oca_bundle: OCABundle) -> Result<(), String> {
65        self.insert_oca_objects_metadata(oca_bundle.clone())?;
66
67        let oca_bundle_said = oca_bundle.said.clone().unwrap().to_string();
68        let capture_base_said = oca_bundle.capture_base.said.clone().unwrap().to_string();
69
70        let mut oca_bundle_rel =
71            self.explore(oca_bundle_said.clone())
72                .unwrap_or(Relationship::new(OCAObject::new(
73                    self,
74                    oca_bundle_said.clone(),
75                )));
76        oca_bundle_rel.add_relation(OCAObject::new(self, capture_base_said.clone()));
77
78        let mut capture_base_rel =
79            self.explore(capture_base_said.clone())
80                .unwrap_or(Relationship::new(OCAObject::new(
81                    self,
82                    capture_base_said.clone(),
83                )));
84        capture_base_rel.add_relation(OCAObject::new(self, oca_bundle_said.clone()));
85
86        for overlay in oca_bundle.overlays {
87            let overlay_said = overlay.said().clone().unwrap().to_string();
88
89            oca_bundle_rel.add_relation(OCAObject::new(self, overlay_said.clone()));
90            capture_base_rel.add_relation(OCAObject::new(self, overlay_said.clone()));
91
92            let mut overlay_rel = self
93                .explore(overlay_said.clone())
94                .unwrap_or(Relationship::new(OCAObject::new(
95                    self,
96                    overlay_said.clone(),
97                )));
98
99            overlay_rel.add_relation(OCAObject::new(self, oca_bundle_said.clone()));
100            overlay_rel.add_relation(OCAObject::new(self, capture_base_said.clone()));
101            let overlay_rel_u8: Vec<u8> = overlay_rel.clone().into();
102            self.db.insert(
103                Namespace::OCARelations,
104                &overlay_said.clone(),
105                &overlay_rel_u8,
106            )?;
107        }
108
109        let oca_bundle_rel_u8: Vec<u8> = oca_bundle_rel.clone().into();
110        self.db.insert(
111            Namespace::OCARelations,
112            &oca_bundle_rel.base_object.said,
113            &oca_bundle_rel_u8,
114        )?;
115
116        let capture_base_rel_u8: Vec<u8> = capture_base_rel.clone().into();
117        self.db.insert(
118            Namespace::OCARelations,
119            &capture_base_rel.base_object.said,
120            &capture_base_rel_u8,
121        )?;
122
123        Ok(())
124    }
125
126    fn object_type(&self, said: String) -> ObjectKind {
127        let object_type = self
128            .db
129            .get(Namespace::OCARelations, &format!("{}.metadata", said))
130            .unwrap();
131
132        (*object_type.unwrap().first().unwrap()).into()
133    }
134}
135
136#[derive(Clone)]
137pub struct Relationship {
138    pub base_object: OCAObject,
139    pub relations: HashSet<OCAObject>,
140}
141
142impl Relationship {
143    fn new(base_object: OCAObject) -> Self {
144        Self {
145            base_object,
146            relations: HashSet::new(),
147        }
148    }
149
150    fn add_relation(&mut self, object: OCAObject) {
151        self.relations.insert(object);
152    }
153}
154
155impl From<Relationship> for Vec<u8> {
156    fn from(val: Relationship) -> Self {
157        let mut result: Vec<u8> = Vec::new();
158
159        val.relations.iter().for_each(|object| {
160            result.push(object.object_type.clone().into());
161            result.push(object.said.len().try_into().unwrap());
162            result.extend(object.said.as_bytes());
163        });
164
165        result
166    }
167}
168
169impl From<Vec<u8>> for Relationship {
170    fn from(val: Vec<u8>) -> Self {
171        let mut result = Relationship::new(OCAObject {
172            said: "".to_string(),
173            object_type: ObjectKind::OCABundle(BundleContent {
174                said: oca_ast_semantics::ast::ReferenceAttrType::Reference(RefValue::Name(
175                    "".to_string(),
176                )),
177            }),
178        });
179
180        let mut tmp_val = val.clone();
181        while !tmp_val.is_empty() {
182            let said_len = tmp_val[1];
183            let (o_u8, split_val) = tmp_val.split_at(2 + said_len as usize);
184            result.add_relation(OCAObject::from(o_u8.to_vec()));
185            tmp_val = split_val.to_vec();
186        }
187
188        result
189    }
190}
191
192impl From<Vec<u8>> for OCAObject {
193    fn from(val: Vec<u8>) -> Self {
194        let object_type = val[0];
195        let said_len = val[1];
196        let said = String::from_utf8(val[2..2 + said_len as usize].to_vec()).unwrap();
197        Self {
198            said,
199            object_type: object_type.into(),
200        }
201    }
202}
203
204#[derive(Eq, PartialEq, Hash, Clone, Debug)]
205pub struct OCAObject {
206    pub said: String,
207    pub object_type: ObjectKind,
208}
209
210impl Serialize for OCAObject {
211    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
212    where
213        S: serde::Serializer,
214    {
215        #[derive(Serialize)]
216        struct OverlayMetadata {
217            kind: ObjectKind,
218        }
219
220        let mut state = serializer.serialize_struct("OCAObject", 3)?;
221        state.serialize_field("said", &self.said)?;
222        match &self.object_type {
223            ObjectKind::OCABundle(_) | ObjectKind::CaptureBase(_) => {
224                state.serialize_field("object_type", &self.object_type)?
225            }
226            ObjectKind::Overlay(_, _) => {
227                state.serialize_field("object_type", "Overlay")?;
228                let overlay_metadata = OverlayMetadata {
229                    kind: self.object_type.clone(),
230                };
231                state.serialize_field("metadata", &overlay_metadata)?
232            }
233        }
234        state.end()
235    }
236}
237
238impl OCAObject {
239    fn new(facade: &Facade, said: String) -> Self {
240        Self {
241            said: said.clone(),
242            object_type: facade.object_type(said),
243        }
244    }
245}