1use crate::std_shapes::shapes::ShapeKind;
7use crate::std_shapes::shapes::*;
8
9pub fn print_record(rec: &RecordDef, indent: usize) {
10 match rec {
11 RecordDef::Text(label, port) => {
12 println!("\"{}\"", label);
13 if let Option::Some(port) = port {
14 println!("\"{}\"", port);
15 }
16 }
17 RecordDef::Array(arr) => {
18 print!("{}", " ".repeat(indent));
19 println!("[");
20 for elem in arr {
21 print_record(elem, indent + 1);
22 }
23 print!("{}", " ".repeat(indent));
24 println!("]");
25 }
26 }
27}
28
29struct RecordParser {
30 input: Vec<char>,
31 pos: usize,
32}
33
34struct RecordParserFrame {
35 label: String,
36 arr: Vec<RecordDef>,
37}
38
39impl RecordParserFrame {
40 pub fn new() -> Self {
41 Self {
42 label: String::new(),
43 arr: Vec::new(),
44 }
45 }
46
47 fn split_label_to_text_and_port(str: &str) -> (String, Option<String>) {
50 let str = str.trim();
51 if str.starts_with('<') {
52 if let Option::Some(idx) = str.find('>') {
53 let port = &str[1..idx];
54 return (
55 str[idx + 1..].trim().to_string(),
56 Option::Some(port.to_string()),
57 );
58 }
59 }
60 (str.to_string(), Option::None)
61 }
62
63 pub fn finalize_label(&mut self) {
64 if !self.label.trim().is_empty() {
65 let ret = Self::split_label_to_text_and_port(&self.label);
66 let text = RecordDef::Text(ret.0, ret.1);
67 self.arr.push(text);
68 self.label.clear();
69 }
70 }
71
72 pub fn finalize_record(&mut self) -> RecordDef {
73 self.finalize_label();
74 match self.arr.len() {
75 0 => RecordDef::Text(String::from(""), Option::None),
76 _ => RecordDef::Array(self.arr.clone()),
77 }
78 }
79}
80impl RecordParser {
81 pub fn new(input: &str) -> Self {
82 Self {
83 input: input.chars().collect(),
84 pos: 0,
85 }
86 }
87
88 pub fn parse(&mut self) -> RecordDef {
89 let mut frame = RecordParserFrame::new();
90 loop {
91 let ch = self.input[self.pos];
93
94 match ch {
95 '{' => {
96 self.pos += 1;
97 frame.finalize_label();
99 let ret = self.parse();
101 frame.arr.push(ret);
102 }
103 '|' => {
104 self.pos += 1;
106 frame.finalize_label();
107 }
108 '}' => {
109 self.pos += 1;
111 frame.finalize_label();
113 return frame.finalize_record();
114 }
115 _ => {
116 self.pos += 1;
117
118 frame.label.push(ch);
120 }
121 }
122 if self.pos == self.input.len() {
124 return frame.finalize_record();
125 }
126 }
127 }
128}
129
130pub fn parse_record_string(label: &str) -> RecordDef {
131 RecordParser::new(label).parse()
132}
133
134pub fn record_builder(label: &str) -> ShapeKind {
136 let res = parse_record_string(label);
137 ShapeKind::Record(res)
138}