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#[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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 parts = &parts[1..];
354
355 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 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 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 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 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}