off_rs/parser/
mod.rs

1pub mod color_format;
2pub mod error;
3mod iter;
4pub mod options;
5mod utils;
6
7use crate::geometry::{
8    color::Color,
9    mesh::{Face, Mesh, Vertex},
10    position::Position,
11};
12
13use self::{
14    error::{Error, Kind},
15    iter::OffLines,
16    options::Options,
17    utils::{ConvertVec, StrParts},
18};
19
20pub type Result<T = ()> = std::result::Result<T, Error>;
21
22/// Parses a [`crate::geometry::mesh::Mesh`] from a `off` string.
23#[derive(Debug, Clone)]
24pub struct Parser<'a> {
25    lines: OffLines<'a>,
26    prev_line_index: usize,
27    vertex_count: usize,
28    face_count: usize,
29    edge_count: usize,
30    document: Mesh,
31    options: Options,
32}
33
34impl<'a> Parser<'a> {
35    /// Creates a new [`Parser`] from a `off` string.
36    pub fn new<S: AsRef<str>>(s: &'a S, options: Options) -> Self {
37        let lines = OffLines::new(s.as_ref());
38
39        Parser {
40            lines,
41            prev_line_index: 0,
42            vertex_count: 0,
43            face_count: 0,
44            edge_count: 0,
45            document: Mesh::new(),
46            options,
47        }
48    }
49
50    /// Parses the `off` string and returns a [`Result`] containing the [`crate::geometry::mesh::Mesh`] or an [`Error`].
51    ///
52    /// # Errors
53    ///
54    /// Will return `Error` if an error occurs while parsing the `off` data.
55    pub fn parse(mut self) -> crate::Result {
56        self.parse_header()?;
57        self.parse_counts()?;
58        self.parse_vertices()?;
59        self.parse_faces()?;
60
61        Ok(self.finalize())
62    }
63
64    /// Progress to the next line.
65    fn next_line(&mut self) -> Option<(usize, &'a str)> {
66        let (line_index, line) = self.lines.next()?;
67
68        self.prev_line_index = line_index;
69
70        Some((line_index, line))
71    }
72
73    /// Parses the header of the `off` string.
74    fn parse_header(&mut self) -> Result {
75        let (line_index, line) = self
76            .next_line()
77            .ok_or_else(|| Error::without_message(Kind::Empty, 0))?;
78
79        if line != "OFF" {
80            return Err(Error::with_message(
81                Kind::InvalidHeader,
82                line_index,
83                "First non-comment line should be `OFF`",
84            ));
85        }
86
87        Ok(())
88    }
89
90    /// Parses the counts of the `off` string.
91    fn parse_counts(&mut self) -> Result {
92        let (line_index, line) = self.next_line().ok_or_else(|| {
93            Error::with_message(Kind::Missing, self.prev_line_index + 1, "No counts present")
94        })?;
95
96        let counts: Vec<&str> = line.split_line();
97
98        let num: Vec<usize> = counts.parse_string_to().map_err(|err| {
99            Error::with_message(
100                Kind::InvalidCounts,
101                line_index,
102                format!("Failed to parse count as number ({})", err),
103            )
104        })?;
105
106        match num[..] {
107            [vertex_count, face_count, edge_count] => {
108                self.vertex_count = vertex_count;
109                self.face_count = face_count;
110                self.edge_count = edge_count;
111            }
112            [vertex_count, face_count] => {
113                self.vertex_count = vertex_count;
114                self.face_count = face_count;
115            }
116            _ => {
117                return Err(Error::with_message(
118                    Kind::InvalidCounts,
119                    line_index,
120                    format!(
121                        "Invalid amount of counts present (expected: 2-3, actual: {})",
122                        num.len()
123                    ),
124                ));
125            }
126        }
127
128        // Check for limits
129        if self.vertex_count > self.options.limits.vertex_count {
130            return Err(Error::with_message(
131                Kind::LimitExceeded,
132                line_index,
133                format!(
134                    "Vertext count exceeds limit (limit: {}, actual: {})",
135                    self.options.limits.vertex_count, self.vertex_count
136                ),
137            ));
138        }
139
140        if self.face_count > self.options.limits.face_count {
141            return Err(Error::with_message(
142                Kind::LimitExceeded,
143                line_index,
144                format!(
145                    "Face count exceeds limit (limit: {}, actual: {})",
146                    self.options.limits.face_count, self.face_count
147                ),
148            ));
149        }
150
151        Ok(())
152    }
153
154    /// Parses the vertices of the `off` string.
155    fn parse_vertices(&mut self) -> Result {
156        for _ in 0..self.vertex_count {
157            let (line_index, line) = self.next_line().ok_or_else(|| {
158                Error::with_message(
159                    Kind::Missing,
160                    self.prev_line_index + 1,
161                    "Expected vertex definition",
162                )
163            })?;
164
165            let parts = line.split_line();
166            let vertex = self.parse_vertex(line_index, &parts)?;
167            self.document.vertices.push(vertex);
168        }
169
170        Ok(())
171    }
172
173    /// Parses a vertex from a `off` string.
174    fn parse_vertex(&mut self, line_index: usize, parts: &[&str]) -> Result<Vertex> {
175        if parts.len() < 3 {
176            return Err(Error::with_message(
177                Kind::InvalidVertexPosition,
178                line_index,
179                format!(
180                    "Not enough parts for position (expected: >= 3, actual: {})",
181                    parts.len()
182                ),
183            ));
184        }
185
186        let position = Parser::parse_position(line_index, &parts[0..=2])?;
187
188        let color = if parts.len() > 3 {
189            Some(self.parse_color(line_index, &parts[3..])?)
190        } else {
191            None
192        };
193
194        Ok(Vertex { position, color })
195    }
196
197    /// Parses a position from a `off` string.
198    fn parse_position(line_index: usize, parts: &[&str]) -> Result<Position> {
199        if parts.len() != 3 {
200            return Err(Error::with_message(
201                Kind::InvalidVertexPosition,
202                line_index,
203                format!(
204                    "Invalid number of coordinates given (expected: 3, actual: {})",
205                    parts.len()
206                ),
207            ));
208        }
209
210        let position_parts: Vec<f32> = parts
211            .iter()
212            .map(|s| {
213                s.parse().map_err(|err| {
214                    Error::with_message(
215                        Kind::InvalidVertexPosition,
216                        line_index,
217                        format!("Failed to parse coordinate as number: ({})", err),
218                    )
219                })
220            })
221            .collect::<Result<Vec<f32>>>()?;
222
223        Position::try_from(position_parts).map_err(|err| {
224            Error::with_message(
225                Kind::InvalidVertexPosition,
226                line_index,
227                format!("Failed to parse position: ({})", err),
228            )
229        })
230    }
231
232    /// Parses a color from a `off` string.
233    fn parse_color(&mut self, line_index: usize, parts: &[&str]) -> Result<Color> {
234        if parts.len() != self.options.color_format.channel_count() {
235            return Err(Error::with_message(
236                Kind::InvalidColor,
237                line_index,
238                format!(
239                    "Invalid number of color elements given (expected: {}, actual: {})",
240                    self.options.color_format.channel_count(),
241                    parts.len()
242                ),
243            ));
244        }
245
246        if self.options.color_format.is_float() {
247            // parse as f32
248            let color_parts = parts
249                .iter()
250                .map(|s| {
251                    s.parse::<f32>().map_err(|err| {
252                        Error::with_message(
253                            Kind::InvalidColor,
254                            line_index,
255                            format!("Failed to parse color as float: {}", err),
256                        )
257                    })
258                })
259                .collect::<Result<Vec<f32>>>()?;
260
261            Color::try_from(color_parts).map_err(|err| {
262                Error::with_message(
263                    Kind::InvalidColor,
264                    line_index,
265                    format!("Failed to parse color: {}", err),
266                )
267            })
268        } else {
269            // parse as u8
270            let color_parts = parts
271                .iter()
272                .map(|s| {
273                    s.parse::<u8>().map_err(|err| {
274                        Error::with_message(
275                            Kind::InvalidColor,
276                            line_index,
277                            format!("Failed to parse color as u8: {}", err),
278                        )
279                    })
280                })
281                .collect::<Result<Vec<u8>>>()?;
282
283            Color::try_from(color_parts).map_err(|err| {
284                Error::with_message(
285                    Kind::InvalidColor,
286                    line_index,
287                    format!("Failed to parse color: {}", err),
288                )
289            })
290        }
291    }
292
293    /// Parses the faces of the `off` string.
294    fn parse_faces(&mut self) -> Result {
295        for _ in 0..self.face_count {
296            let (line_index, line) = self.next_line().ok_or_else(|| {
297                Error::with_message(
298                    Kind::Missing,
299                    self.prev_line_index + 1,
300                    "Expected face definition",
301                )
302            })?;
303
304            let parts: Vec<&str> = line.split_line();
305            let face = self.parse_face(line_index, &parts)?;
306            self.document.faces.push(face);
307        }
308
309        Ok(())
310    }
311
312    /// Parses a face from a `off` string.
313    fn parse_face(&mut self, line_index: usize, mut parts: &[&str]) -> Result<Face> {
314        if parts.len() < 4 {
315            return Err(Error::with_message(
316                Kind::InvalidFace,
317                line_index,
318                format!("Not enough arguments. At least three vertex indicies required (e.g. `3 1 2 3`). {} arguments given", parts.len()),
319            ));
320        }
321
322        let vertex_count: usize = parts[0].parse().map_err(|err| {
323            Error::with_message(
324                Kind::InvalidFace,
325                line_index,
326                format!("Failed to parse vertex count for face definition: {}", err),
327            )
328        })?;
329
330        if vertex_count < 3 {
331            return Err(Error::with_message(
332                Kind::InvalidFace,
333                line_index,
334                format!(
335                    "Vertex count should be at least 3 (actual: {})",
336                    vertex_count
337                ),
338            ));
339        }
340
341        if vertex_count > self.options.limits.face_vertex_count {
342            return Err(Error::with_message(
343                Kind::LimitExceeded,
344                line_index,
345                format!(
346                    "Vertex count of face exceeds limit (limit: {}, actual: {})",
347                    self.options.limits.face_vertex_count, vertex_count
348                ),
349            ));
350        }
351
352        // "Consume" vertex_count
353        parts = &parts[1..];
354
355        // faces are polygons and might have to be triangulated later. Therefore we require at least three vertices
356        if parts.len() < 3 {
357            return Err(Error::with_message(
358                Kind::InvalidFace,
359                line_index,
360                format!(
361                    "Not enough vertices for face (expected: >= 3, actual: {})",
362                    parts.len()
363                ),
364            ));
365        }
366
367        // sanity check: at least vertex_count parts
368        if parts.len() < vertex_count {
369            return Err(Error::with_message(
370                Kind::InvalidFace,
371                line_index,
372                format!(
373                    "Not enough vertex indices given for face definition (expected: {}, actual: {})",
374                    vertex_count,
375                    parts.len()
376                ),
377            ));
378        }
379
380        let vertices = Parser::parse_face_indices(line_index, vertex_count, parts)?;
381
382        // "Consume" vertex indexes
383        parts = &parts[vertex_count..];
384
385        let color = if parts.is_empty() {
386            None
387        } else {
388            Some(self.parse_color(line_index, parts)?)
389        };
390
391        Ok(Face { vertices, color })
392    }
393
394    /// Parses the face vertex indices from a line.
395    fn parse_face_indices(
396        line_index: usize,
397        vertex_count: usize,
398        parts: &[&str],
399    ) -> Result<Vec<usize>> {
400        let vertices: Vec<usize> = parts
401            .iter()
402            .take(vertex_count)
403            .map(|s| {
404                s.parse().map_err(|err| {
405                    Error::with_message(
406                        Kind::InvalidFaceIndex,
407                        line_index,
408                        format!("Failed to parse vertex index as number: ({})", err),
409                    )
410                })
411            })
412            .collect::<Result<Vec<usize>>>()?;
413
414        if vertices.len() != vertex_count {
415            return Err(Error::with_message(
416                Kind::InvalidFaceIndex,
417                line_index,
418                format!(
419                    "Invalid number of face indexes given (expected: {}, actual: {})",
420                    vertex_count,
421                    vertices.len()
422                ),
423            ));
424        }
425
426        Ok(vertices)
427    }
428
429    /// Finalizes the parsing by returning the [`Mesh`].
430    fn finalize(self) -> Mesh {
431        self.document
432    }
433}
434
435#[cfg(test)]
436#[allow(unused)]
437mod tests {
438
439    use crate::parser::color_format::ColorFormat;
440
441    use super::*;
442
443    #[test]
444    fn parse_header() {
445        let mut parser = Parser::new(&"OFF", Options::default());
446        assert!(parser.parse_header().is_ok());
447    }
448
449    #[test]
450    fn parse_header_missing() {
451        let mut parser = Parser::new(&"", Options::default());
452        let header = parser.parse_header();
453        assert!(header.is_err());
454        assert!(matches!(
455            header.unwrap_err(),
456            Error {
457                kind: Kind::Empty,
458                ..
459            }
460        ));
461    }
462
463    #[test]
464    fn parse_header_invalid() {
465        let mut parser = Parser::new(&"COFF", Options::default());
466        let header = parser.parse_header();
467        assert!(header.is_err());
468        assert!(matches!(
469            header.unwrap_err(),
470            Error {
471                kind: Kind::InvalidHeader,
472                ..
473            }
474        ));
475    }
476
477    #[test]
478    fn parse_counts() {
479        let mut parser = Parser::new(&"8 6 12", Options::default());
480        assert!(parser.parse_counts().is_ok());
481        assert_eq!(parser.vertex_count, 8);
482        assert_eq!(parser.face_count, 6);
483        assert_eq!(parser.edge_count, 12);
484    }
485
486    #[test]
487    fn parse_counts_missing() {
488        let mut parser = Parser::new(&"", Options::default());
489        let counts = parser.parse_counts();
490        assert!(counts.is_err());
491        assert!(matches!(
492            counts.unwrap_err(),
493            Error {
494                kind: Kind::Missing,
495                ..
496            }
497        ));
498    }
499
500    #[test]
501    fn parse_counts_too_many() {
502        let mut parser = Parser::new(&"8 6 12 16", Options::default());
503        let counts = parser.parse_counts();
504        assert!(counts.is_err());
505        assert!(matches!(
506            counts.unwrap_err(),
507            Error {
508                kind: Kind::InvalidCounts,
509                ..
510            }
511        ));
512    }
513
514    #[test]
515    fn parse_counts_limits() {
516        let mut parser = Parser::new(&"999999999999 888888888888 777777777", Options::default());
517        let counts = parser.parse_counts();
518        assert!(counts.is_err());
519        assert!(matches!(
520            counts.unwrap_err(),
521            Error {
522                kind: Kind::LimitExceeded,
523                ..
524            }
525        ));
526    }
527
528    #[test]
529    fn parse_vertices() {
530        let mut parser = Parser::new(
531            &"3.0 1.0 2.0 0.1 0.2 0.3 1.0\n1.0 2.0 3.0 0.1 0.2 0.3 1.0",
532            Options::default(),
533        );
534        parser.vertex_count = 2;
535        let result = parser.parse_vertices();
536        assert!(result.is_ok());
537        assert!(parser.next_line().is_none());
538        assert!(parser.document.vertices.len() == 2);
539        assert!(
540            parser.document.vertices[0]
541                == Vertex::new(
542                    Position::new(3.0, 1.0, 2.0),
543                    Some(Color::new(0.1, 0.2, 0.3, 1.0).unwrap()),
544                )
545        );
546        assert!(
547            parser.document.vertices[1]
548                == Vertex::new(
549                    Position::new(1.0, 2.0, 3.0),
550                    Some(Color::new(0.1, 0.2, 0.3, 1.0).unwrap()),
551                )
552        );
553    }
554
555    #[test]
556    fn parse_vertex() {
557        let mut parser = Parser::new(&"", Options::default());
558
559        let vertex = parser.parse_vertex(0, &["1.0", "2.0", "3.0"]);
560        assert!(vertex.is_ok());
561        assert_eq!(
562            vertex.unwrap(),
563            Vertex::new(Position::new(1.0, 2.0, 3.0), None)
564        );
565    }
566
567    #[test]
568    fn parse_vertex_too_few_parts() {
569        let mut parser = Parser::new(&"", Options::default());
570
571        let vertex = parser.parse_vertex(0, &["1.0", "2.0"]);
572        assert!(vertex.is_err());
573        assert!(matches!(
574            vertex.unwrap_err(),
575            Error {
576                kind: Kind::InvalidVertexPosition,
577                ..
578            }
579        ));
580    }
581
582    #[test]
583    fn parse_position() {
584        let position = Parser::parse_position(0, &["1", "2", "3"]);
585        assert!(position.is_ok());
586        assert_eq!(
587            position.unwrap(),
588            Position {
589                x: 1.0,
590                y: 2.0,
591                z: 3.0
592            }
593        );
594    }
595
596    #[test]
597    fn parse_position_no_number() {
598        let position = Parser::parse_position(0, &["1", "2", "a"]);
599        assert!(position.is_err());
600        assert!(matches!(
601            position.unwrap_err(),
602            Error {
603                kind: Kind::InvalidVertexPosition,
604                ..
605            }
606        ));
607    }
608
609    #[test]
610    fn parse_position_too_few_parts() {
611        let position = Parser::parse_position(0, &["1", "2"]);
612        assert!(position.is_err());
613        assert!(matches!(
614            position.unwrap_err(),
615            Error {
616                kind: Kind::InvalidVertexPosition,
617                ..
618            }
619        ));
620    }
621
622    #[test]
623    fn parse_position_too_many_parts() {
624        let position = Parser::parse_position(0, &["1", "2", "3", "5"]);
625        assert!(position.is_err());
626        assert!(matches!(
627            position.unwrap_err(),
628            Error {
629                kind: Kind::InvalidVertexPosition,
630                ..
631            }
632        ));
633    }
634
635    #[test]
636    fn parse_color_rgbfloat() {
637        let mut parser = Parser::new(
638            &"",
639            Options {
640                color_format: ColorFormat::RGBFloat,
641                ..Options::default()
642            },
643        );
644        let color = parser.parse_color(0, &["1.0", "0.5", "0.3"]);
645        assert!(color.is_ok());
646        assert_eq!(
647            color.unwrap(),
648            Color {
649                red: 1.0,
650                green: 0.5,
651                blue: 0.3,
652                alpha: 1.0,
653            }
654        );
655    }
656
657    #[test]
658    fn parse_color_rgbafloat() {
659        let mut parser = Parser::new(
660            &"",
661            Options {
662                color_format: ColorFormat::RGBAFloat,
663                ..Options::default()
664            },
665        );
666        let color = parser.parse_color(0, &["1.0", "0.5", "0.3", "0.5"]);
667        assert!(color.is_ok());
668        assert_eq!(
669            color.unwrap(),
670            Color {
671                red: 1.0,
672                green: 0.5,
673                blue: 0.3,
674                alpha: 0.5,
675            }
676        );
677    }
678
679    #[test]
680    fn parse_color_rgbinterger() {
681        let mut parser = Parser::new(
682            &"",
683            Options {
684                color_format: ColorFormat::RGBInteger,
685                ..Options::default()
686            },
687        );
688        let color = parser.parse_color(0, &["255", "128", "0"]);
689        assert!(color.is_ok());
690        assert_eq!(
691            color.unwrap(),
692            Color {
693                red: 1.0,
694                green: 0.501_960_8,
695                blue: 0.0,
696                alpha: 1.0,
697            }
698        );
699    }
700
701    #[test]
702    fn parse_color_rgbinterger_fail() {
703        let mut parser = Parser::new(
704            &"",
705            Options {
706                color_format: ColorFormat::RGBInteger,
707                ..Options::default()
708            },
709        );
710        let color = parser.parse_color(0, &["255", "128.0", "0"]);
711        assert!(color.is_err());
712        assert!(matches!(
713            color.unwrap_err(),
714            Error {
715                kind: Kind::InvalidColor,
716                ..
717            }
718        ));
719    }
720
721    #[test]
722    fn parse_color_rgbainterger() {
723        let mut parser = Parser::new(
724            &"",
725            Options {
726                color_format: ColorFormat::RGBAInteger,
727                ..Options::default()
728            },
729        );
730        let color = parser.parse_color(0, &["255", "128", "0", "255"]);
731        assert!(color.is_ok());
732        assert_eq!(
733            color.unwrap(),
734            Color {
735                red: 1.0,
736                green: 0.501_960_8,
737                blue: 0.0,
738                alpha: 1.0,
739            }
740        );
741    }
742
743    #[test]
744    fn parse_color_element_count() {
745        let mut parser = Parser::new(
746            &"",
747            Options {
748                color_format: ColorFormat::RGBFloat,
749                ..Options::default()
750            },
751        );
752        let color = parser.parse_color(0, &["1.0", "0.5", "0.3", "0.4"]);
753        assert!(color.is_err());
754        assert!(matches!(
755            color.unwrap_err(),
756            Error {
757                kind: Kind::InvalidColor,
758                ..
759            }
760        ));
761    }
762
763    #[test]
764    fn parse_faces() {
765        let mut parser = Parser::new(
766            &"3 1 2 3 0.1 0.2 0.3 1.0\n3 3 2 1 0.2 0.3 0.4 1.0",
767            Options::default(),
768        );
769        parser.face_count = 2;
770        let result = parser.parse_faces();
771        assert!(result.is_ok());
772        assert!(parser.next_line().is_none());
773        assert!(parser.document.faces.len() == 2);
774        assert!(parser.document.faces[0].vertices == vec![1, 2, 3]);
775        assert!(
776            parser.document.faces[0].color
777                == Some(Color {
778                    red: 0.1,
779                    green: 0.2,
780                    blue: 0.3,
781                    alpha: 1.0,
782                })
783        );
784        assert!(parser.document.faces[1].vertices == vec![3, 2, 1]);
785        assert!(
786            parser.document.faces[1].color
787                == Some(Color {
788                    red: 0.2,
789                    green: 0.3,
790                    blue: 0.4,
791                    alpha: 1.0,
792                })
793        );
794    }
795
796    #[test]
797    fn parse_face() {
798        let mut parser = Parser::new(&"", Options::default());
799        let result = parser.parse_face(0, &["3", "1", "2", "3"]);
800        assert!(result.is_ok());
801        assert_eq!(
802            result.unwrap(),
803            Face {
804                vertices: vec![1, 2, 3],
805                color: None
806            }
807        );
808    }
809
810    #[test]
811    fn parse_face_more() {
812        let mut parser = Parser::new(&"", Options::default());
813        let result = parser.parse_face(0, &["4", "2", "3", "1", "1337"]);
814        assert!(result.is_ok());
815        assert_eq!(
816            result.unwrap(),
817            Face {
818                vertices: vec![2, 3, 1, 1337],
819                color: None
820            }
821        );
822    }
823
824    #[test]
825    fn parse_face_too_little_parts() {
826        let mut parser = Parser::new(&"", Options::default());
827        let result = parser.parse_face(0, &["6", "1", "2", "3"]);
828        assert!(result.is_err());
829        assert!(matches!(
830            result.unwrap_err(),
831            Error {
832                kind: Kind::InvalidFace,
833                ..
834            }
835        ));
836    }
837
838    #[test]
839    fn parse_face_too_many_parts() {
840        let mut parser = Parser::new(&"", Options::default());
841        let result = parser.parse_face(0, &["3", "2", "3", "2", "3"]);
842        assert!(result.is_err());
843        assert!(matches!(
844            result.unwrap_err(),
845            Error {
846                kind: Kind::InvalidColor,
847                ..
848            }
849        ));
850    }
851
852    #[test]
853    fn parse_face_no_number() {
854        let mut parser = Parser::new(&"", Options::default());
855        let result = parser.parse_face(0, &["3", "1", "asdf", "3"]);
856        assert!(result.is_err());
857        println!("{:?}", result);
858        assert!(matches!(
859            result.unwrap_err(),
860            Error {
861                kind: Kind::InvalidFaceIndex,
862                ..
863            }
864        ));
865    }
866
867    #[test]
868    fn parse_face_color() {
869        let mut parser = Parser::new(&"", Options::default());
870        let result = parser.parse_face(0, &["3", "1", "2", "3", "0.1", "0.2", "0.3", "0.4"]);
871        assert!(result.is_ok());
872        assert_eq!(
873            result.unwrap(),
874            Face {
875                vertices: vec![1, 2, 3],
876                color: Some(Color {
877                    red: 0.1,
878                    green: 0.2,
879                    blue: 0.3,
880                    alpha: 0.4
881                })
882            }
883        );
884    }
885
886    #[test]
887    fn parse_face_color_fail() {
888        let mut parser = Parser::new(&"", Options::default());
889        let result = parser.parse_face(0, &["3", "1", "2", "3", "0.1", "0.2"]);
890        assert!(result.is_err());
891        assert!(matches!(
892            result.unwrap_err(),
893            Error {
894                kind: Kind::InvalidColor,
895                ..
896            }
897        ));
898    }
899
900    #[test]
901    fn parse_face_color_fail_no_alpha() {
902        let mut parser = Parser::new(
903            &"",
904            Options {
905                color_format: ColorFormat::RGBFloat,
906                ..Options::default()
907            },
908        );
909        let result = parser.parse_face(0, &["3", "1", "2", "3", "0.1", "0.2", "0.3"]);
910        assert!(result.is_ok());
911        assert_eq!(
912            result.unwrap(),
913            Face {
914                vertices: vec![1, 2, 3],
915                color: Some(Color {
916                    red: 0.1,
917                    green: 0.2,
918                    blue: 0.3,
919                    alpha: 1.0
920                })
921            }
922        );
923    }
924
925    #[test]
926    fn parse_face_color_fail_no_alpha_fail() {
927        let mut parser = Parser::new(&"", Options::default());
928        let result = parser.parse_face(0, &["3", "1", "2", "3", "0.1", "0.2", "0.3"]);
929        assert!(result.is_err());
930        assert!(matches!(
931            result.unwrap_err(),
932            Error {
933                kind: Kind::InvalidColor,
934                ..
935            }
936        ));
937    }
938
939    #[test]
940    fn parse_face_index() {
941        let result = Parser::parse_face_indices(0, 3, &["1", "2", "3"]);
942        assert!(result.is_ok());
943        assert_eq!(result.unwrap(), vec![1, 2, 3]);
944    }
945
946    #[test]
947    fn parse_face_index_more() {
948        let result = Parser::parse_face_indices(0, 5, &["1", "2", "3", "1", "1337"]);
949        assert!(result.is_ok());
950        assert_eq!(result.unwrap(), vec![1, 2, 3, 1, 1337]);
951    }
952
953    #[test]
954    fn parse_face_index_too_little_parts() {
955        let result = Parser::parse_face_indices(0, 5, &["1", "2", "3"]);
956        assert!(result.is_err());
957        assert!(matches!(
958            result.unwrap_err(),
959            Error {
960                kind: Kind::InvalidFaceIndex,
961                ..
962            }
963        ));
964    }
965
966    #[test]
967    fn parse_face_index_too_many_parts() {
968        let result = Parser::parse_face_indices(0, 3, &["1", "2", "3", "2", "3"]);
969        assert!(result.is_ok());
970        assert_eq!(result.unwrap(), vec![1, 2, 3]);
971    }
972
973    #[test]
974    fn parse_face_index_no_number() {
975        let result = Parser::parse_face_indices(0, 3, &["1", "asdf", "3"]);
976        assert!(result.is_err());
977        assert!(matches!(
978            result.unwrap_err(),
979            Error {
980                kind: Kind::InvalidFaceIndex,
981                ..
982            }
983        ));
984    }
985}