use std::path::{Path, PathBuf};
use pedant_syntax::go::GoFactLimits;
use crate::resolution::provider::SourceProviderOf;
use crate::resolution::read::{ByteCeilings, ReadFault};
use crate::resolution::source_language::SourceLanguage;
use super::error::GoProjectError;
use super::fault::GoSourceFault;
use super::inventory::GoFileInventory;
use super::limits::GoResolutionLimits;
use super::paths;
pub type GoSourceProvider = SourceProviderOf<GoSourceRules, GoFileInventory>;
impl GoSourceProvider {
pub fn new(root: &Path, limits: GoResolutionLimits) -> Result<Self, GoProjectError> {
Ok(Self::at_canonical_root(
paths::canonical_root(root)?,
GoSourceRules { limits },
))
}
pub(super) fn at_project_root(root: PathBuf, limits: GoResolutionLimits) -> Self {
Self::at_canonical_root(root, GoSourceRules { limits })
}
}
#[derive(Debug)]
pub struct GoSourceRules {
limits: GoResolutionLimits,
}
impl GoSourceRules {
fn fact_limits(&self) -> GoFactLimits {
GoFactLimits::new(
self.limits.max_syntax_depth,
self.limits.max_facts_per_source,
)
}
}
impl ByteCeilings for GoSourceRules {
fn source_bytes(&self) -> u64 {
self.limits.source_bytes()
}
fn total_bytes(&self) -> u64 {
self.limits.total_bytes()
}
}
impl SourceLanguage for GoSourceRules {
type Inventory = GoFileInventory;
type Fault = GoSourceFault;
fn max_source_files(&self) -> u32 {
self.limits.max_source_files
}
fn source_files_fault(&self) -> GoSourceFault {
GoSourceFault::SourceFiles {
ceiling: self.limits.max_source_files,
}
}
fn refused_again(&self, path: &str) -> GoSourceFault {
GoSourceFault::Refused {
path: Box::from(path),
}
}
fn confine(&self, root: &Path, relative: &str) -> Result<PathBuf, GoSourceFault> {
let joined = root.join(relative);
let confined = paths::canonical_in_root(root, &joined)?;
Ok(confined.unwrap_or(joined))
}
fn refusal(&self, fault: ReadFault) -> GoSourceFault {
GoSourceFault::of_read(fault, self.limits)
}
fn decode(&self, bytes: Vec<u8>) -> Result<String, GoSourceFault> {
String::from_utf8(bytes).map_err(|error| GoSourceFault::NonUtf8 {
reason: error.to_string().into_boxed_str(),
})
}
fn inventory(&self, path: &str, text: &str) -> Result<GoFileInventory, GoSourceFault> {
GoFileInventory::of_source(path, text, self.fact_limits())
}
}