1use crate::state::oca::overlay::attribute_framing::{FramingScope, Framings};
2use crate::state::oca::overlay::cardinality::Cardinalitys;
3use crate::state::oca::overlay::character_encoding::CharacterEncodings;
4use crate::state::oca::overlay::conditional::Conditionals;
5use crate::state::oca::overlay::conformance::Conformances;
6use crate::state::oca::overlay::entry::Entries;
7use crate::state::oca::overlay::entry_code::EntryCodes;
8#[cfg(feature = "format_overlay")]
9use crate::state::oca::overlay::format::Formats;
10use crate::state::oca::overlay::information::Information;
11use crate::state::oca::overlay::label::Labels;
12use crate::state::oca::overlay::link::Links;
13use crate::state::oca::overlay::meta::Metas;
14use crate::state::oca::overlay::unit::Units;
15use crate::state::oca::OCABundle;
16use crate::state::{
17 attribute::Attribute, encoding::Encoding, entries::EntriesElement,
18 entry_codes::EntryCodes as EntryCodesValue, oca::OCABox,
19};
20use indexmap::IndexMap;
21use oca_ast_semantics::ast;
22use std::collections::HashMap;
23use std::str::FromStr;
24
25#[derive(Debug)]
26pub struct OCABuild {
27 pub oca_bundle: OCABundle,
28 pub steps: Vec<OCABuildStep>,
29}
30
31#[derive(Debug)]
32pub struct OCABuildStep {
33 pub parent_said: Option<said::SelfAddressingIdentifier>,
34 pub command: ast::Command,
35 pub result: OCABundle,
36}
37
38#[derive(Debug, Clone, serde::Serialize)]
39pub struct FromASTError {
40 pub line_number: usize,
41 pub raw_line: String,
42 pub message: String,
43}
44
45#[derive(thiserror::Error, Debug, Clone, serde::Serialize)]
46#[serde(untagged)]
47pub enum Error {
48 #[error("Error at line {line_number} ({raw_line}): {message}")]
49 FromASTError {
50 #[serde(rename = "ln")]
51 line_number: usize,
52 #[serde(rename = "c")]
53 raw_line: String,
54 #[serde(rename = "e")]
55 message: String,
56 },
57}
58
59pub fn from_ast(
60 from_oca: Option<OCABundle>,
61 oca_ast: &ast::OCAAst,
62) -> Result<OCABuild, Vec<Error>> {
63 let mut errors = vec![];
64 let mut steps = vec![];
65 let mut parent_said: Option<said::SelfAddressingIdentifier> = match &from_oca {
66 Some(oca_bundle) => oca_bundle.said.clone(),
67 None => None,
68 };
69 let mut base: Option<OCABox> = from_oca.clone().map(OCABox::from);
70 let default_command_meta = ast::CommandMeta {
71 line_number: 0,
72 raw_line: "unknown".to_string(),
73 };
74 for (i, command) in oca_ast.commands.iter().enumerate() {
75 let command_index = match &from_oca {
76 Some(_) => i + 1,
77 None => i,
78 };
79 let command_meta = oca_ast
81 .commands_meta
82 .get(&command_index)
83 .unwrap_or(&default_command_meta);
84 match apply_command(base.clone(), command.clone()) {
85 Ok(oca_box) => {
86 let mut oca_box_mut = oca_box.clone();
87 let oca_bundle = oca_box_mut.generate_bundle();
88 steps.push(OCABuildStep {
96 parent_said: parent_said.clone(),
97 command: command.clone(),
98 result: oca_bundle.clone(),
99 });
100 parent_said.clone_from(&oca_bundle.said);
101 base = Some(oca_box);
102 }
104 Err(mut err) => {
105 errors.extend(err.iter_mut().map(|e| Error::FromASTError {
106 line_number: command_meta.line_number,
107 raw_line: command_meta.raw_line.clone(),
108 message: e.clone(),
109 }));
110 }
111 }
112 }
113 if errors.is_empty() {
114 Ok(OCABuild {
115 oca_bundle: base.unwrap().generate_bundle(),
116 steps,
117 })
118 } else {
119 Err(errors)
120 }
121}
122
123pub fn apply_command(base: Option<OCABox>, op: ast::Command) -> Result<OCABox, Vec<String>> {
124 let mut errors = vec![];
125 let mut oca: OCABox = match base {
126 Some(oca) => oca,
127 None => OCABox::new(),
128 };
129
130 match (op.kind, op.object_kind) {
131 (ast::CommandType::From, _) => {
132 errors.push(
133 "Unsupported FROM command, it should be resolved before applying commands"
134 .to_string(),
135 );
136 }
137 (ast::CommandType::Add, ast::ObjectKind::CaptureBase(content)) => {
138 if let Some(ref attributes) = content.attributes {
139 for (attr_name, attr_type) in attributes {
140 let mut attribute = Attribute::new(attr_name.clone());
141 attribute.set_attribute_type(attr_type.clone());
142 oca.add_attribute(attribute);
143 }
144 }
145 if let Some(ref properties) = content.properties {
146 for (prop_name, prop_value) in properties {
148 if prop_name.eq("classification") {
149 if let ast::NestedValue::Value(value) = prop_value {
150 oca.add_classification(value.clone());
151 }
152 }
153 }
154 }
155 }
156 (ast::CommandType::Add, ast::ObjectKind::Overlay(overlay_type, content)) => {
157 match overlay_type {
158 ast::OverlayType::Meta(_) => {
159 if let Some(ref properties) = content.properties {
160 let mut mut_properties = properties.clone();
161 let lang = mut_properties.remove("lang");
162 let mut lang_iso = None;
163 if let Some(ast::NestedValue::Value(lang_str)) = lang {
164 lang_iso = isolang::Language::from_639_1(lang_str.as_str());
165 }
166
167 for (prop_name, prop_value) in mut_properties {
168 if let ast::NestedValue::Value(value) = prop_value {
169 oca.add_meta(lang_iso.unwrap(), prop_name.clone(), value.clone());
170 }
171 }
172 }
173 }
174 ast::OverlayType::Label(_) => {
175 let mut lang_iso = None;
176 if let Some(ref properties) = content.properties {
177 let mut mut_properties = properties.clone();
178 let lang = mut_properties.remove("lang");
179 if let Some(ast::NestedValue::Value(lang_str)) = lang {
180 lang_iso = isolang::Language::from_639_1(lang_str.as_str());
181 }
182 }
183 if let Some(ref attributes) = content.attributes {
184 for (attr_name, attr_type_value) in attributes {
185 let mut attribute = oca
186 .attributes
187 .get(attr_name)
188 .ok_or_else(|| {
189 errors.push(format!("Undefined attribute: {attr_name}"));
190 errors.clone()
191 })?
192 .clone();
193 if let ast::NestedValue::Value(attr_label) = attr_type_value {
194 attribute.set_label(lang_iso.unwrap(), attr_label.clone());
195 }
196 oca.add_attribute(attribute);
197 }
198 }
199 }
200 ast::OverlayType::Information(_) => {
201 let mut lang_iso = None;
202 if let Some(ref properties) = content.properties {
203 let mut mut_properties = properties.clone();
204 let lang = mut_properties.remove("lang");
205 if let Some(ast::NestedValue::Value(lang_str)) = lang {
206 lang_iso = isolang::Language::from_639_1(lang_str.as_str());
207 }
208 }
209 if let Some(ref attributes) = content.attributes {
210 for (attr_name, attr_type_value) in attributes {
211 let mut attribute = oca
212 .attributes
213 .get(attr_name)
214 .ok_or_else(|| {
215 errors.push(format!("Undefined attribute: {attr_name}"));
216 errors.clone()
217 })?
218 .clone();
219 if let ast::NestedValue::Value(attr_info) = attr_type_value {
220 attribute.set_information(lang_iso.unwrap(), attr_info.clone());
221 }
222 oca.add_attribute(attribute);
223 }
224 }
225 }
226 ast::OverlayType::CharacterEncoding(_) => {
227 if let Some(ref attributes) = content.attributes {
228 for (attr_name, attr_type_value) in attributes {
229 let mut attribute = oca
230 .attributes
231 .get(attr_name)
232 .ok_or_else(|| {
233 errors.push(format!("Undefined attribute: {attr_name}"));
234 errors.clone()
235 })?
236 .clone();
237 if let ast::NestedValue::Value(attr_encoding) = attr_type_value {
238 attribute.set_encoding(Encoding::from_str(attr_encoding).map_err(
239 |_| {
240 errors.push(format!("Unknown encoding: {attr_encoding}"));
241 errors.clone()
242 },
243 )?);
244 }
245 oca.add_attribute(attribute);
246 }
247 }
248 }
249 ast::OverlayType::Conformance(_) => {
250 if let Some(ref attributes) = content.attributes {
251 for (attr_name, attr_type_value) in attributes {
252 let mut attribute = oca
253 .attributes
254 .get(attr_name)
255 .ok_or_else(|| {
256 errors.push(format!("Undefined attribute: {attr_name}"));
257 errors.clone()
258 })?
259 .clone();
260
261 if let ast::NestedValue::Value(attr_conformance) = attr_type_value {
262 attribute.set_conformance(attr_conformance.clone());
263 }
264 oca.add_attribute(attribute);
265 }
266 }
267 }
268 ast::OverlayType::Format(_) => {
269 #[cfg(feature = "format_overlay")]
270 {
271 if let Some(ref attributes) = content.attributes {
272 for (attr_name, attr_type_value) in attributes {
273 let mut attribute = oca
274 .attributes
275 .get(attr_name)
276 .ok_or_else(|| {
277 errors.push(format!("Undefined attribute: {attr_name}"));
278 errors.clone()
279 })?
280 .clone();
281 if let ast::NestedValue::Value(attr_format) = attr_type_value {
282 attribute.set_format(attr_format.clone());
283 }
284 oca.add_attribute(attribute);
285 }
286 }
287 }
288 }
289 ast::OverlayType::Unit(_) => {
290 if let Some(ref attributes) = content.attributes {
291 for (attr_name, attr_type_value) in attributes {
292 let mut attribute = oca
293 .attributes
294 .get(attr_name)
295 .ok_or_else(|| {
296 errors.push(format!("Undefined attribute: {attr_name}"));
297 errors.clone()
298 })?
299 .clone();
300 if let ast::NestedValue::Value(attr_unit) = attr_type_value {
301 attribute.set_unit(attr_unit.clone());
302 }
303 oca.add_attribute(attribute);
304 }
305 }
306 }
307 ast::OverlayType::Cardinality(_) => {
308 if let Some(ref attributes) = content.attributes {
309 for (attr_name, attr_type_value) in attributes {
310 let mut attribute = oca
311 .attributes
312 .get(attr_name)
313 .ok_or_else(|| {
314 errors.push(format!("Undefined attribute: {attr_name}"));
315 errors.clone()
316 })?
317 .clone();
318 if let ast::NestedValue::Value(attr_cardinality) = attr_type_value {
319 attribute.set_cardinality(attr_cardinality.clone());
320 }
321 oca.add_attribute(attribute);
322 }
323 }
324 }
325 ast::OverlayType::Conditional(_) => {
326 if let Some(ref attributes) = content.attributes {
327 for (attr_name, attr_type_value) in attributes {
328 let mut attribute = oca
329 .attributes
330 .get(attr_name)
331 .ok_or_else(|| {
332 errors.push(format!("Undefined attribute: {attr_name}"));
333 errors.clone()
334 })?
335 .clone();
336 if let ast::NestedValue::Value(attr_condition) = attr_type_value {
337 attribute.set_condition(attr_condition.clone());
338 }
339 oca.add_attribute(attribute);
340 }
341 }
342 }
343 ast::OverlayType::EntryCode(_) => {
344 if let Some(ref attributes) = content.attributes {
345 for (attr_name, attr_type_value) in attributes {
346 let mut attribute = oca
347 .attributes
348 .get(attr_name)
349 .ok_or_else(|| {
350 errors.push(format!("Undefined attribute: {attr_name}"));
351 errors.clone()
352 })?
353 .clone();
354 match attr_type_value {
355 ast::NestedValue::Value(attr_entry_codes_sai) => {
356 attribute.set_entry_codes(EntryCodesValue::Sai(
357 attr_entry_codes_sai.clone(),
358 ));
359 }
360 ast::NestedValue::Array(attr_entry_codes) => {
361 let mut entry_codes: Vec<String> = vec![];
362 for attr_entry_code in attr_entry_codes {
363 if let ast::NestedValue::Value(entry_code) = attr_entry_code
364 {
365 entry_codes.push(entry_code.clone());
366 }
367 }
368 attribute.set_entry_codes(EntryCodesValue::Array(entry_codes));
369 }
370 ast::NestedValue::Object(attr_grouped_entry_codes) => {
371 let mut grouped_entry_codes = IndexMap::new();
372 for (group, attr_entry_codes) in attr_grouped_entry_codes {
373 if let ast::NestedValue::Array(entry_codes) =
374 attr_entry_codes
375 {
376 let codes: Vec<String> = entry_codes
377 .iter()
378 .filter_map(|entry_code| {
379 if let ast::NestedValue::Value(entry_code) =
380 entry_code
381 {
382 Some(entry_code.clone())
383 } else {
384 None
385 }
386 })
387 .collect();
388 grouped_entry_codes
389 .insert(group.clone(), codes.clone());
390 }
391 }
392 attribute.set_entry_codes(EntryCodesValue::Object(
393 grouped_entry_codes,
394 ));
395 }
396 _ => (),
397 }
398 oca.add_attribute(attribute);
399 }
400 }
401 }
402 ast::OverlayType::Entry(_) => {
403 let mut lang_iso = None;
404 if let Some(ref properties) = content.properties {
405 let mut mut_properties = properties.clone();
406 let lang = mut_properties.remove("lang");
407 if let Some(ast::NestedValue::Value(lang_str)) = lang {
408 lang_iso = isolang::Language::from_639_1(lang_str.as_str());
409 }
410 }
411 if let Some(ref attributes) = content.attributes {
412 for (attr_name, attr_type_value) in attributes {
413 let mut attribute = oca
414 .attributes
415 .get(attr_name)
416 .ok_or_else(|| {
417 errors.push(format!("Undefined attribute: {attr_name}"));
418 errors.clone()
419 })?
420 .clone();
421 match attr_type_value {
422 ast::NestedValue::Value(attr_entries) => {
423 attribute.set_entry(
424 lang_iso.unwrap(),
425 EntriesElement::Sai(attr_entries.clone()),
426 );
427 }
428 ast::NestedValue::Object(attr_entries) => {
429 let mut entries = HashMap::new();
430 for (attr_entry_key, attr_entry_value) in attr_entries {
431 if let ast::NestedValue::Value(entry_value) =
432 attr_entry_value
433 {
434 entries.insert(
435 attr_entry_key.clone(),
436 entry_value.clone(),
437 );
438 }
439 }
440 attribute.set_entry(
441 lang_iso.unwrap(),
442 EntriesElement::Object(entries),
443 );
444 }
445 _ => (),
446 }
447 oca.add_attribute(attribute);
448 }
449 }
450 }
451 ast::OverlayType::Link(_) => {
452 let mut target_bundle = None;
453 if let Some(ref properties) = content.properties {
454 if let Some(ast::NestedValue::Reference(ast::RefValue::Said(target_said))) =
455 properties.get("target")
456 {
457 target_bundle = Some(target_said.to_string());
458 }
459 }
460 if target_bundle.is_none() {
461 errors.push("Undefined target bundle".to_string());
462 }
463
464 if let Some(ref attributes) = content.attributes {
465 for (attr_name, attr_type_value) in attributes {
466 let mut attribute = oca
467 .attributes
468 .get(attr_name)
469 .ok_or_else(|| {
470 errors.push(format!("Undefined attribute: {attr_name}"));
471 errors.clone()
472 })?
473 .clone();
474 if let ast::NestedValue::Value(linked_attr) = attr_type_value {
475 attribute
476 .set_link(target_bundle.clone().unwrap(), linked_attr.clone());
477 }
478 oca.add_attribute(attribute);
479 }
480 }
481 }
482 ast::OverlayType::AttributeFraming(_) => {
483 let mut frame_id = None;
484 let mut frame_meta = HashMap::new();
485 if let Some(ref properties) = content.properties {
486 for prop in properties {
487 if let (prop_name, ast::NestedValue::Value(prop_value)) = prop {
488 if prop_name.eq("id") {
489 frame_id = Some(prop_value.clone());
490 } else {
491 frame_meta
492 .insert(format!("frame_{}", prop_name), prop_value.clone());
493 }
494 }
495 }
496 }
497 if frame_id.is_none() {
498 errors.push("Undefined frame id".to_string());
499 }
500
501 if let Some(ref attributes) = content.attributes {
502 for (attr_name, attr_framing_value) in attributes {
503 let mut attribute = oca
504 .attributes
505 .get(attr_name)
506 .ok_or_else(|| {
507 errors.push(format!("Undefined attribute: {attr_name}"));
508 errors.clone()
509 })?
510 .clone();
511 if let ast::NestedValue::Object(attr_framing) = attr_framing_value {
512 let mut framing = HashMap::new();
513 for (framing_key, framing_value) in attr_framing {
514 if let ast::NestedValue::Object(framing_value) = framing_value {
515 if let Some(ast::NestedValue::Value(predicate_id)) =
516 framing_value.get("predicate_id")
517 {
518 if let Some(ast::NestedValue::Value(
519 framing_justification,
520 )) = framing_value.get("framing_justification")
521 {
522 let framing_scope = FramingScope {
523 predicate_id: predicate_id.to_string(),
524 framing_justification: framing_justification
525 .to_string(),
526 frame_meta: frame_meta.clone(),
527 };
528 framing.insert(framing_key.clone(), framing_scope);
529 }
530 }
531 }
532 }
533 attribute.set_framing(frame_id.clone().unwrap(), framing.clone());
534 }
535 oca.add_attribute(attribute);
536 }
537 }
538 }
539 _ => (),
540 }
541 }
542 (ast::CommandType::Add, ast::ObjectKind::OCABundle(_)) => todo!(),
543 (ast::CommandType::Remove, ast::ObjectKind::CaptureBase(content)) => {
544 if let Some(ref attributes) = content.attributes {
545 for (attr_name, _) in attributes {
546 oca.remove_attribute(attr_name);
547 }
548 }
549 if let Some(ref properties) = content.properties {
550 for (prop_name, _) in properties {
551 if prop_name.eq("classification") {
552 oca.remove_classification()
553 }
554 }
555 }
556 }
557 (ast::CommandType::Remove, ast::ObjectKind::OCABundle(_)) => todo!(),
558 (ast::CommandType::Remove, ast::ObjectKind::Overlay(_, _)) => todo!(),
559 (ast::CommandType::Modify, ast::ObjectKind::CaptureBase(_)) => todo!(),
560 (ast::CommandType::Modify, ast::ObjectKind::OCABundle(_)) => todo!(),
561 (ast::CommandType::Modify, ast::ObjectKind::Overlay(_, _)) => todo!(),
562 }
563
564 if errors.is_empty() {
565 Ok(oca)
566 } else {
567 Err(errors)
568 }
569}
570
571#[cfg(test)]
572mod tests {
573 use super::*;
574 use indexmap::IndexMap;
575 use oca_ast_semantics::ast::{AttributeType, CaptureContent};
576 use said::{derivation::HashFunctionCode, sad::SerializationFormats, version::Encode};
577
578 #[test]
579 fn test_add_step() {
580 let mut commands = vec![];
581
582 let mut attributes = IndexMap::new();
583 attributes.insert(
584 "d".to_string(),
585 ast::NestedAttrType::Value(AttributeType::Text),
586 );
587 attributes.insert(
588 "i".to_string(),
589 ast::NestedAttrType::Value(AttributeType::Text),
590 );
591 attributes.insert(
592 "passed".to_string(),
593 ast::NestedAttrType::Value(AttributeType::Boolean),
594 );
595 commands.push(ast::Command {
596 kind: ast::CommandType::Add,
597 object_kind: ast::ObjectKind::CaptureBase(CaptureContent {
598 attributes: Some(attributes),
599 properties: None,
600 flagged_attributes: None,
601 }),
602 });
603
604 let mut properties = IndexMap::new();
605 properties.insert(
606 "lang".to_string(),
607 ast::NestedValue::Value("en".to_string()),
608 );
609 properties.insert(
610 "name".to_string(),
611 ast::NestedValue::Value("Entrance credential".to_string()),
612 );
613 properties.insert(
614 "description".to_string(),
615 ast::NestedValue::Value("Entrance credential".to_string()),
616 );
617 let overlay_version = "1.1".to_string();
618 commands.push(ast::Command {
619 kind: ast::CommandType::Add,
620 object_kind: ast::ObjectKind::Overlay(
621 ast::OverlayType::Meta(overlay_version.clone()),
622 ast::Content {
623 attributes: None,
624 properties: Some(properties),
625 },
626 ),
627 });
628
629 let mut attributes = IndexMap::new();
630 attributes.insert(
631 "d".to_string(),
632 ast::NestedValue::Value("Schema digest".to_string()),
633 );
634 attributes.insert(
635 "i".to_string(),
636 ast::NestedValue::Value("Credential Issuee".to_string()),
637 );
638 attributes.insert(
639 "passed".to_string(),
640 ast::NestedValue::Value("Passed".to_string()),
641 );
642 let mut properties = IndexMap::new();
643 properties.insert(
644 "lang".to_string(),
645 ast::NestedValue::Value("en".to_string()),
646 );
647 commands.push(ast::Command {
648 kind: ast::CommandType::Add,
649 object_kind: ast::ObjectKind::Overlay(
650 ast::OverlayType::Label(overlay_version.clone()),
651 ast::Content {
652 attributes: Some(attributes),
653 properties: Some(properties),
654 },
655 ),
656 });
657
658 let mut attributes = IndexMap::new();
659 attributes.insert(
660 "d".to_string(),
661 ast::NestedValue::Value("Schema digest".to_string()),
662 );
663 attributes.insert(
664 "i".to_string(),
665 ast::NestedValue::Value("Credential Issuee".to_string()),
666 );
667 attributes.insert(
668 "passed".to_string(),
669 ast::NestedValue::Value("Enables or disables passing".to_string()),
670 );
671 let mut properties = IndexMap::new();
672 properties.insert(
673 "lang".to_string(),
674 ast::NestedValue::Value("en".to_string()),
675 );
676 commands.push(ast::Command {
677 kind: ast::CommandType::Add,
678 object_kind: ast::ObjectKind::Overlay(
679 ast::OverlayType::Information(overlay_version.clone()),
680 ast::Content {
681 attributes: Some(attributes),
682 properties: Some(properties),
683 },
684 ),
685 });
686
687 let mut attributes = IndexMap::new();
688 attributes.insert(
689 "d".to_string(),
690 ast::NestedValue::Value("utf-8".to_string()),
691 );
692 attributes.insert(
693 "i".to_string(),
694 ast::NestedValue::Value("utf-8".to_string()),
695 );
696 attributes.insert(
697 "passed".to_string(),
698 ast::NestedValue::Value("utf-8".to_string()),
699 );
700 commands.push(ast::Command {
701 kind: ast::CommandType::Add,
702 object_kind: ast::ObjectKind::Overlay(
703 ast::OverlayType::CharacterEncoding(overlay_version.clone()),
704 ast::Content {
705 attributes: Some(attributes),
706 properties: None,
707 },
708 ),
709 });
710
711 let mut attributes = IndexMap::new();
712 attributes.insert("d".to_string(), ast::NestedValue::Value("M".to_string()));
713 attributes.insert("i".to_string(), ast::NestedValue::Value("M".to_string()));
714 attributes.insert(
715 "passed".to_string(),
716 ast::NestedValue::Value("M".to_string()),
717 );
718 commands.push(ast::Command {
719 kind: ast::CommandType::Add,
720 object_kind: ast::ObjectKind::Overlay(
721 ast::OverlayType::Conformance(overlay_version.clone()),
722 ast::Content {
723 attributes: Some(attributes),
724 properties: None,
725 },
726 ),
727 });
728
729 let mut base: Option<OCABox> = None;
731 for command in commands {
732 match apply_command(base.clone(), command.clone()) {
733 Ok(oca) => {
734 base = Some(oca);
735 }
736 Err(errors) => {
737 println!("{:?}", errors);
738 }
739 }
740 }
744 }
745
746 #[test]
747 fn build_from_ast() {
748 let mut commands = vec![];
749
750 let mut attributes = IndexMap::new();
751 attributes.insert(
752 "d".to_string(),
753 ast::NestedAttrType::Value(AttributeType::Text),
754 );
755 attributes.insert(
756 "i".to_string(),
757 ast::NestedAttrType::Value(AttributeType::Text),
758 );
759 attributes.insert(
760 "list".to_string(),
761 ast::NestedAttrType::Value(AttributeType::Text),
762 );
763 attributes.insert(
764 "passed".to_string(),
765 ast::NestedAttrType::Value(AttributeType::Boolean),
766 );
767
768 let flagged_attributes = vec!["d".to_string(), "i".to_string()];
769 commands.push(ast::Command {
770 kind: ast::CommandType::Add,
771 object_kind: ast::ObjectKind::CaptureBase(ast::CaptureContent {
772 attributes: Some(attributes),
773 properties: None,
774 flagged_attributes: Some(flagged_attributes.clone()),
775 }),
776 });
777
778 let mut properties = IndexMap::new();
779 properties.insert(
780 "lang".to_string(),
781 ast::NestedValue::Value("en".to_string()),
782 );
783 properties.insert(
784 "name".to_string(),
785 ast::NestedValue::Value("Entrance credential".to_string()),
786 );
787 properties.insert(
788 "description".to_string(),
789 ast::NestedValue::Value("Entrance credential".to_string()),
790 );
791 let overlay_version = "1.1".to_string();
792 commands.push(ast::Command {
793 kind: ast::CommandType::Add,
794 object_kind: ast::ObjectKind::Overlay(
795 ast::OverlayType::Meta(overlay_version.clone()),
796 ast::Content {
797 attributes: None,
798 properties: Some(properties),
799 },
800 ),
801 });
802
803 let mut attributes = IndexMap::new();
804 attributes.insert(
805 "d".to_string(),
806 ast::NestedValue::Value("Schema digest".to_string()),
807 );
808 attributes.insert(
809 "i".to_string(),
810 ast::NestedValue::Value("Credential Issuee".to_string()),
811 );
812 attributes.insert(
813 "passed".to_string(),
814 ast::NestedValue::Value("Passed".to_string()),
815 );
816 let mut properties = IndexMap::new();
817 properties.insert(
818 "lang".to_string(),
819 ast::NestedValue::Value("en".to_string()),
820 );
821 commands.push(ast::Command {
822 kind: ast::CommandType::Add,
823 object_kind: ast::ObjectKind::Overlay(
824 ast::OverlayType::Label(overlay_version.clone()),
825 ast::Content {
826 attributes: Some(attributes),
827 properties: Some(properties),
828 },
829 ),
830 });
831
832 let mut attributes = IndexMap::new();
833 attributes.insert(
834 "d".to_string(),
835 ast::NestedValue::Value("Schema digest".to_string()),
836 );
837 attributes.insert(
838 "i".to_string(),
839 ast::NestedValue::Value("Credential Issuee".to_string()),
840 );
841 attributes.insert(
842 "passed".to_string(),
843 ast::NestedValue::Value("Enables or disables passing".to_string()),
844 );
845 let mut properties = IndexMap::new();
846 properties.insert(
847 "lang".to_string(),
848 ast::NestedValue::Value("en".to_string()),
849 );
850 commands.push(ast::Command {
851 kind: ast::CommandType::Add,
852 object_kind: ast::ObjectKind::Overlay(
853 ast::OverlayType::Information(overlay_version.clone()),
854 ast::Content {
855 attributes: Some(attributes),
856 properties: Some(properties),
857 },
858 ),
859 });
860
861 let mut attributes = IndexMap::new();
862 attributes.insert(
863 "d".to_string(),
864 ast::NestedValue::Value("utf-8".to_string()),
865 );
866 attributes.insert(
867 "i".to_string(),
868 ast::NestedValue::Value("utf-8".to_string()),
869 );
870 attributes.insert(
871 "passed".to_string(),
872 ast::NestedValue::Value("utf-8".to_string()),
873 );
874 commands.push(ast::Command {
875 kind: ast::CommandType::Add,
876 object_kind: ast::ObjectKind::Overlay(
877 ast::OverlayType::CharacterEncoding(overlay_version.clone()),
878 ast::Content {
879 attributes: Some(attributes),
880 properties: None,
881 },
882 ),
883 });
884
885 let mut attributes = IndexMap::new();
886 attributes.insert("d".to_string(), ast::NestedValue::Value("M".to_string()));
887 attributes.insert("i".to_string(), ast::NestedValue::Value("M".to_string()));
888 attributes.insert(
889 "passed".to_string(),
890 ast::NestedValue::Value("M".to_string()),
891 );
892 commands.push(ast::Command {
893 kind: ast::CommandType::Add,
894 object_kind: ast::ObjectKind::Overlay(
895 ast::OverlayType::Conformance(overlay_version.clone()),
896 ast::Content {
897 attributes: Some(attributes),
898 properties: None,
899 },
900 ),
901 });
902
903 let mut attributes = IndexMap::new();
904 let mut grouped_elements = IndexMap::new();
905 grouped_elements.insert(
906 "g1".to_string(),
907 ast::NestedValue::Array(vec![ast::NestedValue::Value("el1".to_string())]),
908 );
909 grouped_elements.insert(
910 "g2".to_string(),
911 ast::NestedValue::Array(vec![
912 ast::NestedValue::Value("el2".to_string()),
913 ast::NestedValue::Value("el3".to_string()),
914 ]),
915 );
916 attributes.insert(
917 "list".to_string(),
918 oca_ast_semantics::ast::NestedValue::Object(grouped_elements),
919 );
920 commands.push(ast::Command {
921 kind: ast::CommandType::Add,
922 object_kind: ast::ObjectKind::Overlay(
923 ast::OverlayType::EntryCode(overlay_version.clone()),
924 ast::Content {
925 attributes: Some(attributes),
926 properties: None,
927 },
928 ),
929 });
930
931 let oca_ast = ast::OCAAst {
932 version: "1.0".to_string(),
933 commands,
934 commands_meta: IndexMap::new(),
935 meta: HashMap::new(),
936 };
937
938 let build_result = from_ast(None, &oca_ast);
939 match build_result {
940 Ok(oca_build) => {
941 let code = HashFunctionCode::Blake3_256;
942 let format = SerializationFormats::JSON;
943 let oca_bundle_encoded = oca_build.oca_bundle.encode(&code, &format).unwrap();
944 let oca_bundle_json = String::from_utf8(oca_bundle_encoded).unwrap();
945 println!("{}", oca_bundle_json);
946 }
947 Err(e) => {
948 println!("{:?}", e);
949 }
950 }
951 }
952}