idf_parser/
notes.rs

1use crate::primitives::{quote_string, ws};
2use crate::{parse_section, ws_separated};
3use nom::IResult;
4use nom::Parser;
5use nom::bytes::complete::tag;
6use nom::multi::many1;
7use nom::number::complete::float;
8use nom::sequence::delimited;
9
10/// A board or panel file note.
11/// http://www.aertia.com/docs/priware/IDF_V30_Spec.pdf#page=26
12///
13/// This section contains notes for the design that can be displayed in the receiving system, to allow
14/// the electrical and mechanical designers to communicate additional information about the design
15/// entities beyond that conveyed by the entities themselves. Notes are not intended to be used for
16/// rigorous translations of text such as for transferring manufacturing drawings. The association of a
17/// note to its subject is inferred by its location.
18#[derive(Debug, PartialEq, Clone, Default, PartialOrd)]
19pub struct Note {
20    pub x: f32,
21    pub y: f32,
22    pub text_height: f32,
23    pub test_string_physical_length: f32,
24    pub text: String,
25}
26
27fn note(input: &str) -> IResult<&str, Note> {
28    let (remaining, (x, y, text_height, test_string_physical_length, text)) = ws_separated!((
29        float,        // x
30        float,        // y
31        float,        // text height
32        float,        // test string physical length
33        quote_string  // text
34    ))
35    .parse(input)?;
36    let note = Note {
37        x,
38        y,
39        text_height,
40        test_string_physical_length,
41        text: text.to_string(),
42    };
43    Ok((remaining, note))
44}
45
46/// Parses a section of notes from the input string.
47///
48/// # Example
49/// ```
50/// use idf_parser::notes::parse_notes_section;
51/// let input = ".NOTES
52/// 3500.0 3300.0 75.0 2500.0 \"This component rotated 14 degrees\"
53/// 400.0 4400.0 75.0 3200.0 \"Component height limited by enclosure latch\"
54/// .END_NOTES";
55///
56/// let (_remaining, notes) = parse_notes_section(input).unwrap();
57/// assert_eq!(notes.len(), 2);
58/// ```
59pub fn parse_notes_section(input: &str) -> IResult<&str, Vec<Note>> {
60    parse_section!("NOTES", many1(ws(note))).parse(input)
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66    #[test]
67    fn test_note() {
68        let input = "3500.0 3300.0 75.0 2500.0 \"This component rotated 14 degrees\"";
69
70        let expected = Note {
71            x: 3500.0,
72            y: 3300.0,
73            text_height: 75.0,
74            test_string_physical_length: 2500.0,
75            text: "This component rotated 14 degrees".to_string(),
76        };
77        let (_remaining, note) = note(input).unwrap();
78        assert_eq!(note, expected);
79    }
80    #[test]
81    fn test_notes_section() {
82        let input = ".NOTES
833500.0 3300.0 75.0 2500.0 \"This component rotated 14 degrees\"
84400.0 4400.0 75.0 3200.0 \"Component height limited by enclosure latch\"
851800.0 300.0 75.0 1700.0 \"Do not move connectors!\"
86.END_NOTES";
87
88        let expected = vec![
89            Note {
90                x: 3500.0,
91                y: 3300.0,
92                text_height: 75.0,
93                test_string_physical_length: 2500.0,
94                text: "This component rotated 14 degrees".to_string(),
95            },
96            Note {
97                x: 400.0,
98                y: 4400.0,
99                text_height: 75.0,
100                test_string_physical_length: 3200.0,
101                text: "Component height limited by enclosure latch".to_string(),
102            },
103            Note {
104                x: 1800.0,
105                y: 300.0,
106                text_height: 75.0,
107                test_string_physical_length: 1700.0,
108                text: "Do not move connectors!".to_string(),
109            },
110        ];
111        let (_remaining, notes) = parse_notes_section(input).unwrap();
112        assert_eq!(notes, expected);
113    }
114
115    #[test]
116    fn test_notes_more() {
117        let input = ".NOTES
1181800.0 300.0 75.0 1700.0 \"Do not move connectors!\"
119.END_NOTES";
120
121        let expected = vec![Note {
122            x: 1800.0,
123            y: 300.0,
124            text_height: 75.0,
125            test_string_physical_length: 1700.0,
126            text: "Do not move connectors!".to_string(),
127        }];
128        let (_remaining, notes) = parse_notes_section(input).unwrap();
129        assert_eq!(notes, expected);
130    }
131}