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