use std::borrow::Cow; use std::num::NonZero; use futures::FutureExt; use futures::future::LocalBoxFuture; use hashbrown::HashMap; use orchid_base::interner::{Interner, Tok}; use orchid_base::pure_seq::pushed; use crate::api; use crate::system::SysCtx; pub trait VirtFS: Send + Sync + 'static { fn load<'a>( &'a self, path: &'a [Tok], ctx: SysCtx, ) -> LocalBoxFuture<'a, api::OrcResult>; } #[derive(Clone)] pub struct DeclVmod(Cow<'static, [(&'static str, DeclFs)]>); impl DeclVmod { pub fn new(items: &'static [(&'static str, DeclFs)]) -> DeclVmod { DeclVmod(Cow::Borrowed(items)) } pub fn entry( key: &'static str, items: &'static [(&'static str, DeclFs)], ) -> (&'static str, DeclVmod) { (key, DeclVmod(Cow::Borrowed(items))) } pub fn merge(&self, other: &Self) -> Result> { let mut items = Vec::new(); for (k, v1) in self.0.iter() { items.push((*k, match other.0.iter().find(|(k2, _)| k == k2) { Some((_, v2)) => v1.merge(v2).map_err(|e| pushed::<_, Vec<_>>(e, *k))?, None => v1.clone(), })); } for (k, v) in other.0.iter() { if !items.iter().any(|(k2, _)| k2 == k) { items.push((*k, v.clone())) } } Ok(Self(Cow::Owned(items))) } pub async fn to_api_rec( &self, vfses: &mut HashMap, i: &Interner, ) -> std::collections::HashMap { let mut output = std::collections::HashMap::new(); for (k, v) in self.0.iter() { output.insert(i.i::(*k).await.to_api(), v.to_api_rec(vfses, i).boxed_local().await); } output } } #[derive(Clone)] pub enum DeclFs { Lazy(&'static dyn VirtFS), Mod(DeclVmod), } impl DeclFs { pub fn merge(&self, other: &Self) -> Result> { match (self, other) { (Self::Mod(m1), Self::Mod(m2)) => Ok(Self::Mod(m1.merge(m2)?)), (..) => Err(Vec::new()), } } pub async fn to_api_rec( &self, vfses: &mut HashMap, i: &Interner, ) -> api::EagerVfs { match self { DeclFs::Lazy(fs) => { let vfsc: u16 = vfses.len().try_into().expect("too many vfses (more than u16::MAX)"); let id = api::VfsId(NonZero::new(vfsc + 1).unwrap()); vfses.insert(id, *fs); api::EagerVfs::Lazy(id) }, DeclFs::Mod(m) => api::EagerVfs::Eager(m.to_api_rec(vfses, i).await), } } }