1use crate::boolean::BooleanExpr;
9use crate::{Group, Value};
10use std::num::ParseFloatError;
11use std::str::FromStr;
12
13impl Group {
14 pub fn get_attribute(&self, name: &str) -> Option<&Vec<Value>> {
16 self.attributes
17 .get(name)
18 .and_then(|attributes| attributes.first())
19 }
20
21 pub fn get_simple_attribute(&self, name: &str) -> Option<&Value> {
24 self.attributes
25 .get(name)
26 .and_then(|attributes| attributes.first())
27 .filter(|values| values.len() == 1) .and_then(|values| values.first())
29 }
30
31 pub fn get_complex_attribute(&self, name: &str) -> Option<&Vec<Value>> {
34 self.attributes
35 .get(name)
36 .and_then(|attributes| attributes.first())
37 .filter(|values| values.len() != 1) }
39
40 fn get_boolean_function(&self, name: &str) -> Option<(BooleanExpr<usize>, Vec<String>)> {
43 self.get_simple_attribute(name).and_then(|attr| match attr {
44 Value::String(s) | Value::QuotedString(s) => {
45 crate::boolean::parse_boolean_function(s.chars().peekable()).ok()
46 }
47 _ => None,
48 })
49 }
50
51 pub fn find_groups_by_name<'a: 'b, 'b>(
53 &'a self,
54 group_name: &'b str,
55 ) -> impl Iterator<Item = &'a Group> + 'b {
56 self.groups.iter().filter(move |g| g.name == group_name)
57 }
58
59 pub fn find_group_by_arg(&self, group_name: &str, arg_name: &str) -> Option<&Group> {
65 self.find_groups_by_name(group_name).find(|g| {
66 !g.arguments.is_empty()
67 && if let Value::String(name) = &g.arguments[0] {
68 name == arg_name
69 } else {
70 false
71 }
72 })
73 }
74
75 pub fn find_cell(&self, cell_name: &str) -> Option<&Group> {
81 assert_eq!(self.name, "library", "Group must be the top-level library.");
82 self.find_group_by_arg("cell", cell_name)
83 }
84
85 pub fn find_pin(&self, pin_name: &str) -> Option<&Group> {
91 assert_eq!(self.name, "cell", "Must be a cell group.");
92 self.find_group_by_arg("pin", pin_name)
93 }
94}
95
96pub fn parse_float_array(s: &str) -> Result<Vec<f64>, ParseFloatError> {
98 let s = s.strip_prefix('"').unwrap_or(s);
100 let s = s.strip_suffix('"').unwrap_or(s);
101
102 let splitted = s.split(',');
103 splitted
104 .map(|s| {
105 let s = s.strip_prefix(|c: char| c.is_whitespace()).unwrap_or(s);
107 let s = s.strip_suffix(|c: char| c.is_whitespace()).unwrap_or(s);
108
109 f64::from_str(s)
111 })
112 .collect()
113}
114
115#[test]
116fn test_parse_float_array() {
117 let s = r#""1.2, 1.3, 1.4""#;
118 let v = parse_float_array(s).unwrap();
119 assert_eq!(v, vec![1.2, 1.3, 1.4])
120}