sdml_core/
load.rs

1/*!
2This module provides the traits for loading modules from some source.
3
4The goal of the traits [`ModuleResolver`] and [`ModuleLoader`] is to provide the ability to load
5a module into memory from some resource.
6
7# Example
8
9```
10use sdml_core::model::identifiers::Identifier;
11use sdml_core::load::ModuleLoader;
12use sdml_core::store::ModuleStore;
13
14fn module_found(
15    module: &Identifier,
16    loader: &mut impl ModuleLoader,
17    cache: &mut impl ModuleStore
18) -> bool {
19    loader.load(module, None, cache, false).is_ok()
20}
21```
22
23 */
24
25use crate::{
26    model::{identifiers::Identifier, modules::ModulePath},
27    store::ModuleStore,
28};
29use sdml_errors::{
30    diagnostics::{reporter::ReportCounters, SeverityFilter},
31    Diagnostic, FileId, Source,
32};
33use tracing::warn;
34use url::Url;
35
36// ------------------------------------------------------------------------------------------------
37// Public Types
38// ------------------------------------------------------------------------------------------------
39
40///
41/// A resolver implementation is responsible for determining the resource identifier (URL) for
42/// a module named `name`.
43///
44/// The additional parameter `imported_by` identifies the module source making the request.
45///
46pub trait ModuleResolver: Default {
47    ///
48    /// Return a URL given the module name `name`.
49    ///
50    fn name_to_resource(
51        &self,
52        name: &Identifier,
53        imported_by: Option<FileId>,
54    ) -> Result<Url, sdml_errors::Error>;
55
56    fn path_name_to_resource(
57        &self,
58        name: &ModulePath,
59        imported_by: Option<FileId>,
60    ) -> Result<Url, sdml_errors::Error> {
61        warn!("path_name_to_resource({name:?}, {imported_by:?}) not implemented");
62        todo!();
63    }
64}
65
66///
67/// A loader instance is responsible for resolving a module into a resource URL and parsing it into
68/// memory. Note that the loader does not return the module instance itself but rather the module's
69/// name parsed from the resource, the module itself is inserted into the `cache`.
70///
71pub trait ModuleLoader: Default {
72    ///
73    /// Resolve `name` into a resource identifier (URL) and parse into memory. The loader will check
74    /// the `store` first to see if the module is already loaded, and will add the module into the
75    /// store after parsing. The value of `recursive` tells the loader whether to also load
76    /// the module's dependencies as well.
77    ///
78    fn load(
79        &mut self,
80        name: &Identifier,
81        imported_by: Option<FileId>,
82        store: &mut impl ModuleStore,
83        recursive: bool,
84    ) -> Result<Identifier, sdml_errors::Error>;
85
86    ///
87    /// Returns the instance of [`ModuleResolver`] used by this loader.
88    ///
89    fn resolver(&self) -> &impl ModuleResolver;
90
91    fn get_file_id(&self, name: &Identifier) -> Option<FileId>;
92
93    fn get_source_by_name(&self, name: &Identifier) -> Option<Source> {
94        self.get_file_id(name).and_then(|id| self.get_source(id))
95    }
96
97    fn has_source(&self, file_id: FileId) -> bool {
98        self.get_source(file_id).is_some()
99    }
100
101    fn get_source(&self, file_id: FileId) -> Option<Source>;
102
103    fn report(&self, diagnostic: &Diagnostic) -> Result<(), sdml_errors::Error>;
104    fn reporter_done(
105        &self,
106        top_module_name: Option<String>,
107    ) -> Result<ReportCounters, sdml_errors::Error>;
108
109    fn set_severity_filter(&mut self, filter: SeverityFilter);
110}