genotype_project 0.4.0

Genotype language project crate
Documentation
use std::{
    hash::{Hash, Hasher},
    path::{Path, PathBuf},
    sync::Arc,
};

use genotype_parser::tree::GTPath;
use miette::Result;

use crate::error::GTProjectError;

#[derive(Debug, Clone)]
pub struct GTProjectModulePath {
    root: Arc<PathBuf>,
    path: PathBuf,
    id: GTPath,
}

impl GTProjectModulePath {
    pub fn as_path(&self) -> &PathBuf {
        &self.path
    }

    pub fn as_id(&self) -> &GTPath {
        &self.id
    }

    pub fn as_name(&self) -> String {
        self.id.as_str().into()
    }

    pub fn as_path_str(&self) -> String {
        format!("{}.type", self.id.as_str())
    }

    pub fn resolve(&self, path: &GTPath) -> Result<Self> {
        let path = format!("{}.type", path.as_str());
        Self::try_new(
            Arc::clone(&self.root),
            &self.path.parent().unwrap().join(path),
        )
    }

    pub fn try_new(root: Arc<PathBuf>, path: &PathBuf) -> Result<Self> {
        let path = path.canonicalize().map_err(|_| {
            GTProjectError::CannotResolve(path.as_os_str().to_str().unwrap().to_owned())
        })?;
        let id = Self::id(&root, &path)?;
        Ok(Self { root, id, path })
    }

    pub fn id(root: &PathBuf, path: &PathBuf) -> Result<GTPath> {
        Ok(GTPath::parse(
            (0, 0).into(),
            path.as_path()
                .strip_prefix(root.as_path())
                .map_err(|_| GTProjectError::Unknown)?
                .with_extension("")
                .to_str()
                .unwrap(),
        )
        .unwrap())
    }
}

impl AsRef<Path> for GTProjectModulePath {
    fn as_ref(&self) -> &Path {
        self.path.as_ref()
    }
}

impl PartialEq for GTProjectModulePath {
    fn eq(&self, other: &Self) -> bool {
        self.path == other.path
    }
}

impl Eq for GTProjectModulePath {}

impl Hash for GTProjectModulePath {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.path.hash(state);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use pretty_assertions::assert_eq;

    #[test]
    fn test_try_new() {
        let root = Arc::new(PathBuf::from("./examples/basic").canonicalize().unwrap());
        let path = root.join("author.type");
        let module_path = GTProjectModulePath::try_new(root, &path).unwrap();
        assert_eq!(module_path.as_path(), &path.canonicalize().unwrap());
        assert_eq!(module_path.as_id().as_str(), "author")
    }
}