use std::{
fmt, io,
path::{Path, PathBuf},
};
use indexmap::IndexMap;
use nwnrs_resman::prelude::*;
use nwnrs_resref::prelude::*;
#[derive(Debug)]
pub enum ResDirError {
Io(io::Error),
ResMan(ResManError),
ResRef(nwnrs_resref::ResRefError),
Message(String),
}
impl ResDirError {
pub(crate) fn msg(message: impl Into<String>) -> Self {
Self::Message(message.into())
}
}
impl fmt::Display for ResDirError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Io(error) => error.fmt(f),
Self::ResMan(error) => error.fmt(f),
Self::ResRef(error) => error.fmt(f),
Self::Message(message) => f.write_str(message),
}
}
}
impl std::error::Error for ResDirError {}
impl From<io::Error> for ResDirError {
fn from(value: io::Error) -> Self {
Self::Io(value)
}
}
impl From<ResManError> for ResDirError {
fn from(value: ResManError) -> Self {
Self::ResMan(value)
}
}
impl From<nwnrs_resref::ResRefError> for ResDirError {
fn from(value: nwnrs_resref::ResRefError) -> Self {
Self::ResRef(value)
}
}
#[derive(Debug, Clone)]
pub struct ResDir {
pub(crate) root: PathBuf,
pub(crate) label: String,
pub(crate) entries: IndexMap<ResRef, Res>,
}
impl ResDir {
#[must_use]
pub fn root(&self) -> &Path {
&self.root
}
#[must_use]
pub fn label(&self) -> &str {
&self.label
}
#[must_use]
pub fn entries(&self) -> &IndexMap<ResRef, Res> {
&self.entries
}
}
impl fmt::Display for ResDir {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ResDir:{}", self.label)
}
}
impl ResContainer for ResDir {
fn contains(&self, rr: &ResRef) -> bool {
self.entries.contains_key(rr)
}
fn demand(&self, rr: &ResRef) -> ResManResult<Res> {
self.entries
.get(rr)
.cloned()
.ok_or_else(|| ResManError::Message(format!("not found: {rr}")))
}
fn count(&self) -> usize {
self.entries.len()
}
fn contents(&self) -> Vec<ResRef> {
self.entries.keys().cloned().collect()
}
}
pub type ResDirResult<T> = Result<T, ResDirError>;