sophia_resource/
lib.rs

1//! This crate is part of [Sophia],
2//! an [RDF] and [Linked Data] toolkit in Rust.
3//!
4//! It provides a resource-centric API on top of the [Sophia] API.
5//!
6//! [Sophia]: https://docs.rs/sophia/latest/sophia/
7//! [RDF]: https://www.w3.org/TR/rdf-primer/
8//! [Linked Data]: http://linkeddata.org/
9#![deny(missing_docs)]
10
11pub mod loader;
12pub mod resource;
13
14pub use loader::{Loader, LoaderError, LocalLoader, NoLoader};
15pub use resource::{Resource, ResourceError, TypedResource};
16
17#[cfg(test)]
18mod test {
19    use super::*;
20    use sophia_api::{
21        prelude::{Graph, Term},
22        term::SimpleTerm,
23        MownStr,
24    };
25    use sophia_iri::Iri;
26
27    pub const NS: Iri<&str> = Iri::new_unchecked_const("http://example.org/");
28    pub const F1: Iri<&str> = Iri::new_unchecked_const("http://example.org/file1.ttl");
29    pub const F1R1: Iri<&str> = Iri::new_unchecked_const("http://example.org/file1.ttl#res1");
30    pub const F1R2: Iri<&str> = Iri::new_unchecked_const("http://example.org/file1.ttl#res2");
31    pub const F1R3: Iri<&str> = Iri::new_unchecked_const("http://example.org/file1.ttl#res3");
32    pub const F2: Iri<&str> = Iri::new_unchecked_const("http://example.org/file2.ttl");
33    pub const F2R1: Iri<&str> = Iri::new_unchecked_const("http://example.org/file2.ttl#res1");
34    pub const F2R2: Iri<&str> = Iri::new_unchecked_const("http://example.org/file2.ttl#res2");
35    pub const FAIL: Iri<&str> = Iri::new_unchecked_const("http://example.org/not_there");
36    pub const F3: Iri<&str> = Iri::new_unchecked_const("http://example.org/file3.nt");
37    #[cfg(feature = "jsonld")]
38    pub const F4: Iri<&str> = Iri::new_unchecked_const("http://example.org/file4.jsonld");
39    #[cfg(feature = "xml")]
40    pub const F5: Iri<&str> = Iri::new_unchecked_const("http://example.org/file5.rdf");
41    pub const SUBDIR: Iri<&str> = Iri::new_unchecked_const("http://example.org/subdir");
42    // test with no extension (conneg emulation)
43    pub const F1X: Iri<&str> = Iri::new_unchecked_const("http://example.org/file1");
44    pub const F1XR1: Iri<&str> = Iri::new_unchecked_const("http://example.org/file1#res1");
45    pub const F3X: Iri<&str> = Iri::new_unchecked_const("http://example.org/file3");
46    #[cfg(feature = "jsonld")]
47    pub const F4X: Iri<&str> = Iri::new_unchecked_const("http://example.org/file4");
48    #[cfg(feature = "xml")]
49    pub const F5X: Iri<&str> = Iri::new_unchecked_const("http://example.org/file5");
50
51    pub const EX_ID: Iri<&str> = Iri::new_unchecked_const("http://example.org/ns#id");
52    pub const EX_LIST: Iri<&str> = Iri::new_unchecked_const("http://example.org/ns#list");
53    pub const EX_FOREIGN1: Iri<&str> = Iri::new_unchecked_const("http://example.org/ns#foreign1");
54    pub const EX_FOREIGN2: Iri<&str> = Iri::new_unchecked_const("http://example.org/ns#foreign2");
55    pub const EX_NEXT: Iri<&str> = Iri::new_unchecked_const("http://example.org/ns#next");
56    pub const EX_RELATED: Iri<&str> = Iri::new_unchecked_const("http://example.org/ns#related");
57    pub const EX_UNREACHABLE: Iri<&str> =
58        Iri::new_unchecked_const("http://example.org/ns#unreachable");
59    pub const EX_UNUSED: Iri<&str> = Iri::new_unchecked_const("http://example.org/ns#unused");
60
61    /// Number of triples in F1
62    pub const F1_LEN: usize = 20;
63    /// Number of triples in F2
64    pub const F2_LEN: usize = 2;
65    /// Number of triples in F3
66    pub const F3_LEN: usize = 20;
67    /// Number of triples in F4
68    #[cfg(feature = "jsonld")]
69    pub const F4_LEN: usize = 20;
70    /// Number of triples in F5
71    #[cfg(feature = "xml")]
72    pub const F5_LEN: usize = 20;
73
74    pub type MyGraph = Vec<[SimpleTerm<'static>; 3]>;
75    pub type TestResult = Result<(), Box<dyn std::error::Error>>;
76
77    pub fn make_loader() -> LocalLoader {
78        let ns = NS.map_unchecked(MownStr::from);
79        LocalLoader::new(vec![(
80            ns,
81            std::path::Path::new("test").canonicalize().unwrap(),
82        )])
83        .unwrap()
84    }
85
86    /// Test impl of `TypedResource`
87    pub struct WithId(Resource<MyGraph, LocalLoader>);
88
89    impl TryFrom<Resource<MyGraph, LocalLoader>> for WithId {
90        type Error = ResourceError<<MyGraph as Graph>::Error>;
91
92        fn try_from(value: Resource<MyGraph, LocalLoader>) -> Result<Self, Self::Error> {
93            if value.get_any_term(EX_ID)?.is_none() {
94                Err(ResourceError::NoValueFor {
95                    id: value.id().into_term(),
96                    predicate: EX_ID.into_term(),
97                })
98            } else {
99                Ok(Self(value))
100            }
101        }
102    }
103
104    impl std::ops::Deref for WithId {
105        type Target = Resource<MyGraph, LocalLoader>;
106
107        fn deref(&self) -> &Self::Target {
108            &self.0
109        }
110    }
111}