Skip to main content

json_ld/core/loader/
tokio_fs.rs

1use json_syntax::{JsonParse, JsonValue};
2use rdf_syntax::{Iri, IriBuf};
3use std::path::PathBuf;
4
5use crate::{JsonLdDocument, JsonLdLoadError, JsonLdSourceCode};
6
7use super::{AsyncJsonLdLoader, JsonLdFsLoader};
8
9pub use super::fs::Error;
10
11/// Async file-system loader backed by Tokio.
12///
13/// This is an async counterpart to [`JsonLdFsLoader`] that performs file I/O using
14/// [`tokio::fs`] rather than blocking the thread.
15///
16/// Loaded documents are not cached: a new file system read is made each time
17/// an IRI is loaded even if it has already been queried before.
18pub struct JsonLdTokioFsLoader(JsonLdFsLoader);
19
20impl Default for JsonLdTokioFsLoader {
21	fn default() -> Self {
22		Self(JsonLdFsLoader::default())
23	}
24}
25
26impl JsonLdTokioFsLoader {
27	/// Creates a new Tokio file-system loader.
28	pub fn new() -> Self {
29		Self::default()
30	}
31
32	/// Bind the given IRI prefix to the given local directory path.
33	///
34	/// Any document whose IRI matches the given prefix will be loaded from the
35	/// referenced local directory.
36	pub fn mount<P: AsRef<std::path::Path>>(&mut self, url: IriBuf, path: P) {
37		self.0.mount(url, path)
38	}
39
40	/// Returns the local file path associated to the given `url`, if any.
41	pub fn filepath(&self, url: &Iri) -> Option<PathBuf> {
42		self.0.filepath(url)
43	}
44}
45
46impl AsyncJsonLdLoader for JsonLdTokioFsLoader {
47	async fn async_load(&self, url: &Iri) -> Result<JsonLdDocument, JsonLdLoadError> {
48		match self.filepath(url) {
49			Some(filepath) => {
50				let contents = tokio::fs::read_to_string(&filepath)
51					.await
52					.map_err(|e| JsonLdLoadError::new(url.to_owned(), Error::IO(e)))?;
53				let (doc, code_map) = JsonValue::parse_str(&contents)
54					.map_err(|e| JsonLdLoadError::new(url.to_owned(), Error::Parse(e)))?;
55				Ok(JsonLdDocument::new_full(
56					Some(url.to_owned()),
57					Some("application/ld+json".parse().unwrap()),
58					None,
59					Default::default(),
60					Some(JsonLdSourceCode::new(contents, code_map)),
61					doc,
62				))
63			}
64			None => Err(JsonLdLoadError::new(url.to_owned(), Error::NoMountPoint)),
65		}
66	}
67}