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}