use crate::std_shapes::shapes::ShapeKind;
use crate::std_shapes::shapes::*;
pub fn print_record(rec: &RecordDef, indent: usize) {
match rec {
RecordDef::Text(label, port) => {
println!("\"{}\"", label);
if let Option::Some(port) = port {
println!("\"{}\"", port);
}
}
RecordDef::Array(arr) => {
print!("{}", " ".repeat(indent));
println!("[");
for elem in arr {
print_record(elem, indent + 1);
}
print!("{}", " ".repeat(indent));
println!("]");
}
}
}
struct RecordParser {
input: Vec<char>,
pos: usize,
}
struct RecordParserFrame {
label: String,
arr: Vec<RecordDef>,
}
impl RecordParserFrame {
pub fn new() -> Self {
Self {
label: String::new(),
arr: Vec::new(),
}
}
fn split_label_to_text_and_port(str: &str) -> (String, Option<String>) {
let str = str.trim();
if str.starts_with('<') {
if let Option::Some(idx) = str.find('>') {
let port = &str[1..idx];
return (
str[idx + 1..].trim().to_string(),
Option::Some(port.to_string()),
);
}
}
(str.to_string(), Option::None)
}
pub fn finalize_label(&mut self) {
if !self.label.trim().is_empty() {
let ret = Self::split_label_to_text_and_port(&self.label);
let text = RecordDef::Text(ret.0, ret.1);
self.arr.push(text);
self.label.clear();
}
}
pub fn finalize_record(&mut self) -> RecordDef {
self.finalize_label();
match self.arr.len() {
0 => RecordDef::Text(String::from(""), Option::None),
_ => RecordDef::Array(self.arr.clone()),
}
}
}
impl RecordParser {
pub fn new(input: &str) -> Self {
Self {
input: input.chars().collect(),
pos: 0,
}
}
pub fn parse(&mut self) -> RecordDef {
let mut frame = RecordParserFrame::new();
loop {
let ch = self.input[self.pos];
match ch {
'{' => {
self.pos += 1;
frame.finalize_label();
let ret = self.parse();
frame.arr.push(ret);
}
'|' => {
self.pos += 1;
frame.finalize_label();
}
'}' => {
self.pos += 1;
frame.finalize_label();
return frame.finalize_record();
}
_ => {
self.pos += 1;
frame.label.push(ch);
}
}
if self.pos == self.input.len() {
return frame.finalize_record();
}
}
}
}
pub fn parse_record_string(label: &str) -> RecordDef {
RecordParser::new(label).parse()
}
pub fn record_builder(label: &str) -> ShapeKind {
let res = parse_record_string(label);
ShapeKind::Record(res)
}