use std::path::{Path, PathBuf};
use crate::resolution::confinement::{ConfinementFault, canonical_present};
use crate::resolution::provider::SourceProviderOf;
use crate::resolution::read::{ByteCeilings, ReadFault};
use crate::resolution::source_language::SourceLanguage;
use super::error::RustProjectError;
use super::fault::RustSourceFault;
use super::inventory::RustFileInventory;
use super::limits::ResolutionLimits;
use super::paths;
pub type RustSourceProvider = SourceProviderOf<RustSourceRules, RustFileInventory>;
impl RustSourceProvider {
pub fn new(root: &Path, limits: ResolutionLimits) -> Result<Self, RustProjectError> {
Ok(Self::at_canonical_root(
paths::canonical_root(root)?,
RustSourceRules { limits },
))
}
pub(super) fn at_project_root(root: PathBuf, limits: ResolutionLimits) -> Self {
Self::at_canonical_root(root, RustSourceRules { limits })
}
}
#[derive(Debug)]
pub struct RustSourceRules {
limits: ResolutionLimits,
}
impl ByteCeilings for RustSourceRules {
fn source_bytes(&self) -> u64 {
self.limits.source_bytes()
}
fn total_bytes(&self) -> u64 {
self.limits.total_bytes()
}
}
impl SourceLanguage for RustSourceRules {
type Inventory = RustFileInventory;
type Fault = RustSourceFault;
fn max_source_files(&self) -> u32 {
self.limits.max_source_files
}
fn source_files_fault(&self) -> RustSourceFault {
RustSourceFault::SourceFiles {
ceiling: self.limits.max_source_files.into(),
}
}
fn refused_again(&self, path: &str) -> RustSourceFault {
RustSourceFault::Refused {
path: Box::from(path),
}
}
fn confine(&self, root: &Path, relative: &str) -> Result<PathBuf, RustSourceFault> {
canonical_present(root, &root.join(relative)).map_err(|fault| match fault {
ConfinementFault::Unreadable(source) => RustSourceFault::Unreadable(source),
ConfinementFault::OutOfRoot { canonical } => RustSourceFault::OutOfRoot {
path: Box::from(relative),
landing: crate::resolution::paths::path_text(&canonical),
},
})
}
fn refusal(&self, fault: ReadFault) -> RustSourceFault {
RustSourceFault::of_read(fault, self.limits)
}
fn decode(&self, bytes: Vec<u8>) -> Result<String, RustSourceFault> {
String::from_utf8(bytes).map_err(|error| RustSourceFault::InvalidUtf8 {
reason: error.to_string().into_boxed_str(),
})
}
fn inventory(&self, path: &str, text: &str) -> Result<RustFileInventory, RustSourceFault> {
RustFileInventory::of_source(path, text, self.limits.max_syntax_depth)
}
}