off_rs/
lib.rs

1#![warn(clippy::pedantic)]
2
3//! A simple `.off` file parser.
4//!
5//! # Usage
6//!
7//! ```rust
8//!    let off_string = r#"
9//!OFF
10//!3 1
11//!1.0 0.0 0.0
12//!0.0 1.0 0.0
13//!0.0 0.0 1.0
14//!4  0 1 2 3  255 0 0 # red
15//!"#;
16//!
17//!let mesh = off_rs::parse(
18//!    off_string,
19//!    Default::default() // optional ParserOptions
20//!);
21//! ```
22
23pub mod geometry;
24pub mod parser;
25
26use crate::geometry::mesh::Mesh;
27use crate::parser::options::Options;
28use crate::parser::Parser;
29use std::fs::File;
30use std::io::{self, Read};
31use std::path::Path;
32
33/// Contains errors that occur during parsing.
34#[derive(Debug)]
35pub enum Error {
36    /// An IO error occurred while reading the file.
37    IOError(io::Error),
38    /// An error occurred during parsing the `off` data.
39    ParserError(crate::parser::error::Error),
40}
41
42impl std::error::Error for Error {}
43
44impl std::fmt::Display for Error {
45    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
46        match self {
47            Error::IOError(e) => write!(f, "IO Error: {}", e),
48            Error::ParserError(e) => write!(f, "Parser Error: {}", e),
49        }
50    }
51}
52
53impl From<io::Error> for Error {
54    fn from(e: io::Error) -> Self {
55        Error::IOError(e)
56    }
57}
58
59impl From<crate::parser::error::Error> for Error {
60    fn from(e: crate::parser::error::Error) -> Self {
61        Error::ParserError(e)
62    }
63}
64
65/// This result may contain the parsed [`crate::geometry::mesh::Mesh`] or the [`self::Result`] that occurred.
66pub type Result<D = Mesh> = std::result::Result<D, Error>;
67
68/// Parse a [`crate::geometry::mesh::Mesh`] from a [`std::path::Path`] pointing to an `.off` file.
69///
70/// # Errors
71///
72/// Will return `self::Error` if an error occurs while reading the file or parsing the `off` data.
73pub fn from_path<P: AsRef<Path>>(path: P, options: Options) -> Result {
74    let mut file = File::open(path).map_err(Error::IOError)?;
75
76    let mut string = String::new();
77    match file.read_to_string(&mut string) {
78        Ok(_) => {}
79        Err(inner) => return Err(Error::IOError(inner)),
80    };
81
82    parse(&string, options)
83}
84
85/// Directly parse a [`crate::geometry::mesh::Mesh`] from an `off` string.
86///
87/// # Examples
88///
89/// ```rust
90///     let off_string = r#"
91///OFF
92///3 1
93///1.0 0.0 0.0
94///0.0 1.0 0.0
95///0.0 0.0 1.0
96///4  0 1 2 3  1.0 0.0 0.0 1.0 # red
97///"#;
98///
99///    let mesh = off_rs::parse(
100///        off_string,
101///        Default::default(), // optional ParserOptions
102///    );
103///
104///    println!("{:#?}", mesh);
105/// ```
106///
107/// # Errors
108///
109/// Will return `self::Error` if an error occurs while parsing the `off` data.
110pub fn parse(string: &str, options: Options) -> Result {
111    Parser::new(&string, options).parse()
112}