rune/compile/
source_loader.rsuse crate::alloc::path::Path;
#[cfg(feature = "std")]
use crate::alloc::prelude::*;
use crate::ast::Spanned;
use crate::compile;
#[cfg(feature = "std")]
use crate::compile::ErrorKind;
#[cfg(feature = "std")]
use crate::item::ComponentRef;
use crate::{Item, Source};
pub trait SourceLoader {
fn load(&mut self, root: &Path, item: &Item, span: &dyn Spanned) -> compile::Result<Source>;
}
#[derive(Default)]
#[non_exhaustive]
pub struct NoopSourceLoader;
impl SourceLoader for NoopSourceLoader {
fn load(&mut self, _: &Path, _: &Item, span: &dyn Spanned) -> compile::Result<Source> {
Err(compile::Error::msg(span, "Source loading is not supported"))
}
}
cfg_std! {
#[derive(Default)]
#[non_exhaustive]
pub struct FileSourceLoader;
impl FileSourceLoader {
pub fn new() -> Self {
Self::default()
}
}
impl SourceLoader for FileSourceLoader {
fn load(&mut self, root: &Path, item: &Item, span: &dyn Spanned) -> compile::Result<Source> {
let mut base = root.try_to_owned()?;
if !base.pop() {
return Err(compile::Error::new(
span,
ErrorKind::UnsupportedModuleRoot {
root: root.try_to_owned()?,
},
));
}
for c in item {
if let ComponentRef::Str(string) = c {
base.push(string);
} else {
return Err(compile::Error::new(
span,
ErrorKind::UnsupportedModuleItem {
item: item.try_to_owned()?,
},
));
}
}
let candidates = [base.join("mod.rn"), base.with_extension("rn")];
let mut found = None;
for path in &candidates[..] {
if path.is_file() {
found = Some(path);
break;
}
}
let Some(path) = found else {
return Err(compile::Error::new(
span,
ErrorKind::ModNotFound { path: base },
));
};
match Source::from_path(path) {
Ok(source) => Ok(source),
Err(error) => Err(compile::Error::new(
span,
ErrorKind::SourceError {
path: path.clone(),
error,
},
)),
}
}
}
}