json_ld/core/loader/
fs.rs1use json_syntax::parse::JsonParseError;
2use json_syntax::{JsonParse, JsonValue};
3use rdf_syntax::{Iri, IriBuf};
4use std::fs::File;
5use std::io::{BufReader, Read};
6use std::path::{Path, PathBuf};
7
8use crate::{JsonLdDocument, JsonLdLoadError, JsonLdSourceCode};
9
10use super::JsonLdLoader;
11
12#[derive(Debug, thiserror::Error)]
14pub enum Error {
15 #[error("no mount point")]
17 NoMountPoint,
18
19 #[error("IO: {0}")]
21 IO(std::io::Error),
22
23 #[error("parse error: {0}")]
25 Parse(JsonParseError),
26}
27
28#[derive(Default)]
36pub struct JsonLdFsLoader {
37 mount_points: Vec<(PathBuf, IriBuf)>,
38}
39
40impl JsonLdFsLoader {
41 pub fn new() -> Self {
43 Self::default()
44 }
45
46 #[inline(always)]
51 pub fn mount<P: AsRef<Path>>(&mut self, url: IriBuf, path: P) {
52 self.mount_points.push((path.as_ref().into(), url));
53 }
54
55 pub fn filepath(&self, url: &Iri) -> Option<PathBuf> {
57 for (path, target_url) in &self.mount_points {
58 let relative = url.as_iri_ref().relative_to(target_url);
59 if relative.as_iri().is_none() {
60 let mut filepath = path.clone();
61 for seg in relative.path().segments() {
62 filepath.push(seg.as_str())
63 }
64
65 return Some(filepath);
66 }
67 }
76
77 None
78 }
79}
80
81impl JsonLdLoader for JsonLdFsLoader {
82 fn load(&self, url: &Iri) -> Result<JsonLdDocument, JsonLdLoadError> {
83 match self.filepath(url) {
84 Some(filepath) => {
85 let file = File::open(filepath)
86 .map_err(|e| JsonLdLoadError::new(url.to_owned(), Error::IO(e)))?;
87 let mut buf_reader = BufReader::new(file);
88 let mut contents = String::new();
89 buf_reader
90 .read_to_string(&mut contents)
91 .map_err(|e| JsonLdLoadError::new(url.to_owned(), Error::IO(e)))?;
92 let (doc, code_map) = JsonValue::parse_str(&contents)
93 .map_err(|e| JsonLdLoadError::new(url.to_owned(), Error::Parse(e)))?;
94 Ok(JsonLdDocument::new_full(
95 Some(url.to_owned()),
96 Some("application/ld+json".parse().unwrap()),
97 None,
98 Default::default(),
99 Some(JsonLdSourceCode::new(contents, code_map)),
100 doc,
101 ))
102 }
103 None => Err(JsonLdLoadError::new(url.to_owned(), Error::NoMountPoint)),
104 }
105 }
106}