1use std::fmt;
4use std::result;
5
6pub struct SymConfig {}
8
9pub struct ModConfig {
11 pub font_size: f64,
13 pub font_thickness: f64,
15}
16
17pub struct Config {
19 pub name: String,
21 pub s: SymConfig,
23 pub m: ModConfig,
25}
26
27impl Config {
28 pub fn klc() -> Config {
30 Config {
31 name: "KLC 2.0.10".into(),
32 s: SymConfig {},
33 m: ModConfig {
34 font_size: 1.0,
35 font_thickness: 0.15,
36 },
37 }
38 }
39}
40
41pub trait CheckFix {
43 fn check(&self, config: &Config) -> Vec<CheckFixData>;
45
46 fn fix(&mut self, _config: &Config) {}
48}
49
50#[derive(Debug)]
51pub enum CheckFixData {
53 Item(CheckFixItem),
55 More(Vec<CheckFixData>),
57}
58
59impl CheckFixData {
60 pub fn flatter(self) -> Self {
62 match self {
63 CheckFixData::Item(_) => self,
64 CheckFixData::More(v) => if v.len() == 1 {
65 v.into_iter().next().unwrap()
66 } else {
67 CheckFixData::More(v)
68 },
69 }
70 }
71
72 pub fn new<A: fmt::Display, B: Into<String>>(
74 section: i64,
75 rule: i64,
76 item: A,
77 message: B,
78 ) -> Self {
79 let i = CheckFixItem::new(section, rule, item, message.into());
80 CheckFixData::Item(i)
81 }
82
83 pub fn info<A: fmt::Display, B: Into<String>>(
85 section: i64,
86 rule: i64,
87 item: A,
88 message: B,
89 ) -> Self {
90 let i = CheckFixItem::new(section, rule, item, message.into()).info();
91 CheckFixData::Item(i)
92 }
93
94 pub fn dump_on_logger(&self, indent: usize) {
96 match *self {
97 CheckFixData::Item(ref item) => item.dump_on_logger(indent),
98 CheckFixData::More(ref more) => for klcdata in more {
99 let new_indent = match *klcdata {
100 CheckFixData::Item(_) => indent,
101 CheckFixData::More(_) => indent + 1,
102 };
103 klcdata.dump_on_logger(new_indent)
104 },
105 }
106 }
107}
108
109#[derive(Debug)]
110pub struct CheckFixItem {
112 pub section: i64,
114 pub rule: i64,
116 pub item: String,
118 pub message: String,
120 pub info: bool,
122}
123impl CheckFixItem {
124 pub fn new<A: fmt::Display, B: Into<String>>(
126 section: i64,
127 rule: i64,
128 item: A,
129 message: B,
130 ) -> Self {
131 CheckFixItem {
132 section: section,
133 rule: rule,
134 item: format!("{}", item),
135 message: message.into(),
136 info: false,
137 }
138 }
139
140 pub fn info(self) -> CheckFixItem {
142 CheckFixItem { info: true, ..self }
143 }
144
145 pub fn dump_on_logger(&self, indent: usize) {
147 let indent = ::std::iter::repeat(" ")
148 .take(indent * 2)
149 .collect::<String>();
150 if self.info {
151 info!(
152 "{}{}.{} {}:{}",
153 indent,
154 self.section,
155 self.rule,
156 self.item,
157 self.message
158 )
159 } else {
160 warn!(
161 "{}{}.{} {}:{}",
162 indent,
163 self.section,
164 self.rule,
165 self.item,
166 self.message
167 )
168 }
169 }
170}
171
172#[derive(Debug)]
173pub enum KLCSection {
175 General,
177 SymbolLibraryNames,
179 SymbolNames,
181 SymbolRules,
183 FootprintLibraryNames,
185 FootprintNames,
187 FootprintRules,
189 SMDRules,
191 THTRules,
193 FootprintProperties,
195}
196
197impl Into<i64> for KLCSection {
198 fn into(self) -> i64 {
199 match self {
200 KLCSection::General => 1,
201 KLCSection::SymbolLibraryNames => 2,
202 KLCSection::SymbolNames => 3,
203 KLCSection::SymbolRules => 4,
204 KLCSection::FootprintLibraryNames => 5,
205 KLCSection::FootprintNames => 6,
206 KLCSection::FootprintRules => 7,
207 KLCSection::SMDRules => 8,
208 KLCSection::THTRules => 9,
209 KLCSection::FootprintProperties => 10,
210 }
211 }
212}
213
214impl fmt::Display for KLCSection {
215 fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
216 let s = match *self {
217 KLCSection::General => "General Rules",
218 KLCSection::SymbolLibraryNames => "Symbol Library Names",
219 KLCSection::SymbolNames => "Symbol Names",
220 KLCSection::SymbolRules => "General Rules for Symbols",
221 KLCSection::FootprintLibraryNames => "Footprint Library Names",
222 KLCSection::FootprintNames => "Footprint Names",
223 KLCSection::FootprintRules => "General Rules for Footprints",
224 KLCSection::SMDRules => "Rules for SMD Footprints",
225 KLCSection::THTRules => "Rules for Through-hole Footprints",
226 KLCSection::FootprintProperties => "Footprint Properties",
227 };
228 write!(f, "{}", s)
229 }
230}
231
232const ALLOWED_1_7: &'static str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-.";
246
247fn allowed_1_7(s: &str) -> Option<Vec<String>> {
248 let mut v = vec![];
249 for (i, c) in s.chars().enumerate() {
250 if ALLOWED_1_7.chars().find(|&x| x == c).is_none() {
251 v.push(format!("Invalid char '{}' at {} in '{}'", c, i, s))
252 }
253 }
254 if v.is_empty() {
255 None
256 } else {
257 Some(v)
258 }
259}
260
261pub fn allowed_1_7_items(s: &str) -> Vec<CheckFixData> {
263 let mut v = vec![];
264 if let Some(v2) = allowed_1_7(s) {
265 for x in v2 {
266 v.push(CheckFixData::new(1, 7, s, x))
267 }
268 }
269 v
270}
271
272pub fn is_allowed_1_7(s: &str) -> bool {
274 allowed_1_7(s).is_none()
275}
276
277#[cfg(test)]
317mod tests {
318 use super::*;
319 #[test]
320 fn test_allowed_1_7_1() {
321 assert!(allowed_1_7("Hello_world_1.23-4").is_none())
322 }
323
324 #[test]
325 fn test_allowed_1_7_2() {
326 let t = allowed_1_7("Hello world")
327 .unwrap()
328 .into_iter()
329 .next()
330 .unwrap();
331 assert_eq!(t, "Invalid char ' ' at 5 in 'Hello world'")
332 }
333}