use crate::eval::GlobalRuntimeState;
use crate::{
Engine, ModuleResolver, Position, RhaiResultOf, Scope, SharedModule, StaticVec, AST, ERR,
STATIC_VEC_INLINE_SIZE,
};
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
use std::{ops::AddAssign, slice::Iter};
#[derive(Default)]
pub struct ModuleResolversCollection(StaticVec<Box<dyn ModuleResolver>>);
impl ModuleResolversCollection {
#[inline(always)]
#[must_use]
pub const fn new() -> Self {
Self(StaticVec::new_const())
}
#[inline(always)]
pub fn push(&mut self, resolver: impl ModuleResolver + 'static) -> &mut Self {
self.0.push(Box::new(resolver));
self
}
#[inline(always)]
pub fn insert(&mut self, index: usize, resolver: impl ModuleResolver + 'static) -> &mut Self {
self.0.insert(index, Box::new(resolver));
self
}
#[inline(always)]
pub fn pop(&mut self) -> Option<Box<dyn ModuleResolver>> {
self.0.pop()
}
#[inline(always)]
pub fn remove(&mut self, index: usize) -> Box<dyn ModuleResolver> {
self.0.remove(index)
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = &dyn ModuleResolver> {
self.0.iter().map(<_>::as_ref)
}
#[inline(always)]
pub fn clear(&mut self) -> &mut Self {
self.0.clear();
self
}
#[inline(always)]
#[must_use]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline(always)]
#[must_use]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn append(&mut self, other: Self) -> &mut Self {
self.0.extend(other.0);
self
}
}
impl IntoIterator for ModuleResolversCollection {
type Item = Box<dyn ModuleResolver>;
type IntoIter = smallvec::IntoIter<[Box<dyn ModuleResolver>; STATIC_VEC_INLINE_SIZE]>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a> IntoIterator for &'a ModuleResolversCollection {
type Item = &'a Box<dyn ModuleResolver>;
type IntoIter = Iter<'a, Box<dyn ModuleResolver>>;
#[inline(always)]
fn into_iter(self) -> Self::IntoIter {
self.0.iter()
}
}
impl Extend<Box<dyn ModuleResolver>> for ModuleResolversCollection {
#[inline(always)]
fn extend<T: IntoIterator<Item = Box<dyn ModuleResolver>>>(&mut self, iter: T) {
self.0.extend(iter);
}
}
impl<M: ModuleResolver + 'static> AddAssign<M> for ModuleResolversCollection {
#[inline(always)]
fn add_assign(&mut self, rhs: M) {
self.push(rhs);
}
}
impl ModuleResolver for ModuleResolversCollection {
fn resolve(
&self,
engine: &Engine,
source_path: Option<&str>,
path: &str,
pos: Position,
) -> RhaiResultOf<SharedModule> {
for resolver in &self.0 {
match resolver.resolve(engine, source_path, path, pos) {
Ok(module) => return Ok(module),
Err(err) => match *err {
ERR::ErrorModuleNotFound(..) => (),
ERR::ErrorInModule(..) => return Err(err),
_ => unreachable!("ModuleResolver::resolve returns error that is not ErrorModuleNotFound or ErrorInModule"),
},
}
}
Err(ERR::ErrorModuleNotFound(path.into(), pos).into())
}
fn resolve_raw(
&self,
engine: &Engine,
global: &mut GlobalRuntimeState,
scope: &mut Scope,
path: &str,
pos: Position,
) -> RhaiResultOf<SharedModule> {
for resolver in &self.0 {
match resolver.resolve_raw(engine,global, scope, path, pos) {
Ok(module) => return Ok(module),
Err(err) => match *err {
ERR::ErrorModuleNotFound(..) => (),
ERR::ErrorInModule(..) => return Err(err),
_ => unreachable!("ModuleResolver::resolve returns error that is not ErrorModuleNotFound or ErrorInModule"),
},
}
}
Err(ERR::ErrorModuleNotFound(path.into(), pos).into())
}
fn resolve_ast(
&self,
engine: &Engine,
source: Option<&str>,
path: &str,
pos: Position,
) -> Option<RhaiResultOf<AST>> {
for resolver in &self.0 {
match resolver.resolve_ast(engine, source, path, pos) {
None => (),
Some(Err(err)) => match *err {
ERR::ErrorModuleNotFound(..) => (),
_ => unreachable!("ModuleResolver::resolve_ast returns error that is not ErrorModuleNotFound or ErrorInModule"),
},
r => return r,
}
}
None
}
}