gen_analyzer/parse/value/
struct.rs1use std::{collections::BTreeMap, fmt::Display};
2
3use gen_utils::{
4 error::{Error, ParseError},
5 parser::{parse_value, trim},
6};
7use nom::{bytes::complete::take_till1, character::complete::char, multi::many0, IResult};
8
9
10use crate::PropKeyType;
11
12use super::Value;
13
14#[derive(Debug, Clone, PartialEq)]
19pub struct Struct {
20 pub name: Option<String>,
21 pub fields: BTreeMap<String, Value>,
22 pub is_anonymous: bool,
23}
24
25impl Struct {
26 pub fn new(name: &str) -> Self {
27 Struct {
28 name: Some(name.to_string()),
29 fields: BTreeMap::new(),
30 is_anonymous: false,
31 }
32 }
33 pub fn insert(&mut self, key: &str, value: Value) {
34 self.fields.insert(key.to_string(), value);
35 }
36 pub fn get(&self, key: &str) -> Option<&Value> {
37 self.fields.get(key)
38 }
39 pub fn set_name(&mut self, name: &str) {
40 self.name.replace(name.to_string());
41 self.is_anonymous = false;
42 }
43 pub fn parse_style(s: &str) -> Result<Self, Error> {
44 match parse_struct_style(s) {
45 Ok((_, res)) => Ok(res),
46 Err(_) => Err(ParseError::template("parse style struct failed").into()),
47 }
48 }
49 pub fn parse_template(s: &str) -> Result<Self, Error> {
50 Self::parse_style(s)
51 }
52}
53
54impl TryFrom<serde_json::Value> for Struct {
55 type Error = Error;
56
57 fn try_from(value: serde_json::Value) -> Result<Self, Self::Error> {
58 let mut fields = BTreeMap::new();
59 if let serde_json::Value::Object(obj) = value {
60 for (k, v) in obj {
61 fields.insert(k, Value::try_from(v)?);
62 }
63 }
64 Ok(Struct {
65 name: None,
66 fields,
67 is_anonymous: true,
68 })
69 }
70}
71
72impl From<Vec<(&str, &str)>> for Struct {
73 fn from(value: Vec<(&str, &str)>) -> Self {
74 let mut fields = BTreeMap::new();
75 for (k, v) in value {
76 fields.insert(k.to_string(), Value::from(v));
77 }
78 Struct {
79 name: None,
80 fields,
81 is_anonymous: true,
82 }
83 }
84}
85
86impl From<Vec<(&str, (Value, PropKeyType))>> for Struct {
87 fn from(value: Vec<(&str, (Value, PropKeyType))>) -> Self {
88 let mut fields = BTreeMap::new();
89 for (k, (v, _)) in value {
90 fields.insert(k.to_string(), v);
91 }
92 Struct {
93 name: None,
94 fields,
95 is_anonymous: true,
96 }
97 }
98}
99
100impl Display for Struct {
101 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
102 let mut fields = String::new();
103 for (k, v) in &self.fields {
104 fields.push_str(&format!("{}: {}, ", k, v));
105 }
106 if self.is_anonymous {
107 write!(f, "{{{}}}", fields)
108 } else {
109 write!(
110 f,
111 "{} {{{}}}",
112 self.name.as_ref().unwrap_or(&String::new()),
113 fields
114 )
115 }
116 }
117}
118
119fn parse_kv(input: &str) -> IResult<&str, (&str, Value)> {
120 let mut res = Struct {
121 name: None,
122 fields: BTreeMap::new(),
123 is_anonymous: true,
124 };
125
126 let (input, k) = trim(parse_value)(input)?;
127 let (input, _) = trim(char(':'))(input)?;
128
129 if input.trim().starts_with('{') {
130 let (input, _) = char('{')(input)?;
131 let (input, fields) = many0(parse_kv)(input)?;
132 let (input, _) = char('}')(input)?;
133 for (k, v) in fields {
134 res.fields.insert(k.to_string(), v);
135 }
136 return Ok((input, (k, Value::Struct(res))));
137 } else {
138 let (input, v) = trim(take_till1(|c| c == ',' || c == '}'))(input)?;
139 let input = if input.starts_with(',') {
140 let (input, _) = trim(char(','))(input)?;
141 input
142 } else {
143 input
144 };
145 let v = Value::parse_style(v).map_err(|_| {
146 nom::Err::Error(nom::error::Error::new(input, nom::error::ErrorKind::Fail))
147 })?;
148 return Ok((input, (k, v)));
149 }
150}
151fn parse_struct_style(s: &str) -> IResult<&str, Struct> {
153 let mut res = Struct {
155 name: None,
156 fields: BTreeMap::new(),
157 is_anonymous: true,
158 };
159 let (input, _) = char('{')(s.trim())?;
161 let (input, fields) = match trim(char('}'))(input) {
162 Ok((input, _)) => (input, vec![]),
163 Err(_) => {
164 let (input, fields) = many0(parse_kv)(input)?;
165
166 (input, fields)
169 }
170 };
171
172 if !fields.is_empty() {
173 for (k, v) in fields {
174 res.fields.insert(k.to_string(), v);
175 }
176 }
177
178 Ok((input, res))
186}
187