horned_functional/
lib.rs

1#![doc = include_str!("../README.md")]
2
3#[macro_use]
4extern crate thiserror;
5#[macro_use]
6extern crate pest_derive;
7
8extern crate curie;
9extern crate horned_owl;
10#[cfg(feature = "memmap")]
11extern crate memmap;
12extern crate pest;
13
14mod as_ofn;
15mod error;
16mod from_ofn;
17mod from_pair;
18mod parser;
19
20use std::collections::HashMap;
21use std::fmt::Debug;
22use std::fmt::Formatter;
23use std::fmt::Write;
24use std::fs::File;
25use std::io::Read;
26use std::path::Path;
27
28use curie::PrefixMapping;
29use horned_owl::model::Build;
30use horned_owl::model::Ontology;
31use horned_owl::ontology::axiom_mapped::AxiomMappedOntology;
32
33pub use self::as_ofn::AsFunctional;
34pub use self::as_ofn::Functional;
35pub use self::error::Error;
36pub use self::error::Result;
37pub use self::from_ofn::FromFunctional;
38
39/// A context to pass around while parsing and writing OWL functional documents.
40#[derive(Default)]
41pub struct Context<'a> {
42    build: Option<&'a Build>,
43    prefixes: Option<&'a PrefixMapping>,
44}
45
46// Before `v0.1.1`, `curie::PrefixMapping` doesn't implement `Debug`.
47impl<'a> Debug for Context<'a> {
48    fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
49        f.debug_struct("Context")
50            .field("build", &self.build)
51            .field(
52                "prefixes",
53                &match &self.prefixes {
54                    None => format!("{}", "None"),
55                    Some(p) => {
56                        format!("{:?}", p.mappings().collect::<HashMap<_, _>>())
57                    }
58                },
59            )
60            .finish()
61    }
62}
63
64impl<'a> Context<'a> {
65    /// Create a new context with the given IRI builder and prefix mapping.
66    pub fn new<B, P>(build: B, prefixes: P) -> Self
67    where
68        B: Into<Option<&'a Build>>,
69        P: Into<Option<&'a PrefixMapping>>,
70    {
71        Self {
72            build: build.into(),
73            prefixes: prefixes.into(),
74        }
75    }
76
77    /// Obtain an IRI for the given string, using the internal builder if any.
78    pub fn iri<S: Into<String>>(&self, s: S) -> horned_owl::model::IRI
79    where
80        S: AsRef<str>,
81    {
82        match self.build {
83            Some(b) => b.iri(s),
84            None => Build::default().iri(s),
85        }
86    }
87}
88
89impl<'a> From<&'a Build> for Context<'a> {
90    fn from(build: &'a Build) -> Context<'a> {
91        Self {
92            build: Some(build),
93            prefixes: None,
94        }
95    }
96}
97
98impl<'a> From<&'a PrefixMapping> for Context<'a> {
99    fn from(prefixes: &'a PrefixMapping) -> Context<'a> {
100        Self {
101            build: None,
102            prefixes: Some(prefixes),
103        }
104    }
105}
106
107/// Parse an entire OWL document from a string.
108#[inline]
109pub fn from_str<O, S>(src: S) -> Result<(O, PrefixMapping)>
110where
111    O: Ontology + FromFunctional,
112    S: AsRef<str>,
113{
114    FromFunctional::from_ofn(src.as_ref())
115}
116
117/// Parse an entire OWL document from a `Read` implementor.
118#[inline]
119pub fn from_reader<O, R>(mut r: R) -> Result<(O, PrefixMapping)>
120where
121    O: Ontology + FromFunctional,
122    R: Read,
123{
124    let mut s = String::new();
125    r.read_to_string(&mut s)?;
126    from_str(s)
127}
128
129/// Parse an entire OWL document from a file on the local filesystem.
130#[inline]
131pub fn from_file<O, P>(path: P) -> Result<(O, PrefixMapping)>
132where
133    O: Ontology + FromFunctional,
134    P: AsRef<Path>,
135{
136    let f = File::open(path)?; // .and_then(from_reader)
137    #[cfg(not(feature = "memmap"))]
138    return from_reader(f);
139
140    #[cfg(feature = "memmap")]
141    unsafe {
142        let map = memmap::Mmap::map(&f)?;
143        match std::str::from_utf8(&map) {
144            Ok(text) => from_str(text),
145            Err(error) => Err(Error::IO(std::io::Error::new(
146                std::io::ErrorKind::InvalidData,
147                error,
148            ))),
149        }
150    }
151}
152
153/// Render an entire OWL document to a string.
154#[inline]
155pub fn to_string<'a, P>(ontology: &AxiomMappedOntology, prefixes: P) -> String
156where
157    P: Into<Option<&'a PrefixMapping>>,
158{
159    let mut dest = String::new();
160    // write the prefixes
161    let p = prefixes.into();
162    if let Some(pm) = p {
163        write!(dest, "{}", pm.as_ofn()).expect("infallible");
164    }
165    // write the ontology
166    let ctx = Context::new(None, p);
167    write!(dest, "{}", ontology.as_ofn_ctx(&ctx)).expect("infallible");
168    // return the final string
169    dest
170}