diff --git a/Cargo.lock b/Cargo.lock index 3c914bb..92d1ee3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,6 +77,7 @@ dependencies = [ "quote", "semver", "sha3", + "thiserror", ] [[package]] @@ -283,6 +284,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "thiserror" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "typenum" version = "1.17.0" diff --git a/bok-macro/src/lib.rs b/bok-macro/src/lib.rs index 588ec74..c24716b 100644 --- a/bok-macro/src/lib.rs +++ b/bok-macro/src/lib.rs @@ -42,7 +42,7 @@ pub fn repository(attrs: TokenStream, input: TokenStream) -> TokenStream { } quote! { - #[derive(::bok::Repository)] + #[derive(::bok::Repository, Debug)] #ast } .into() diff --git a/bok/Cargo.toml b/bok/Cargo.toml index 33b4624..9f46424 100644 --- a/bok/Cargo.toml +++ b/bok/Cargo.toml @@ -21,3 +21,4 @@ proc-macro2 = "1.0" quote = "1.0" semver = { version = "1.0" } sha3 = { version = "0.10" } +thiserror = { version = "2.0" } diff --git a/bok/src/collection.rs b/bok/src/collection.rs index 358c896..75bce07 100644 --- a/bok/src/collection.rs +++ b/bok/src/collection.rs @@ -16,29 +16,99 @@ */ use ::std::{ - collections::HashMap, + collections::BTreeMap, sync::{Arc, RwLock}, vec::Vec, }; +use crate::{Path, Pkg, PkgName, RepoName, Repository}; + +#[derive(Debug, ::thiserror::Error)] +pub enum Error { + #[error("package already present")] + AlreadyPresent((Arc, ArcLock)), + #[error("not found")] + NotFound, +} + type ArcLock = Arc>; -type PkgMap = HashMap>; +type PkgMap = BTreeMap, (Arc, ArcLock)>; /// Collection of packages, subset of what is present on one repository only pub struct Collection { - repos: RwLock>>, - pkgs: RwLock, - repos_pkgs: RwLock>, - //repos_pkgs: RwLock>, + repos: RwLock>>, + repos_pkgs: RwLock, PkgMap>>, } impl Collection { + /// Create a new empty collection of pkgs pub fn new() -> Collection { - const PKGNUM: usize = 512; Collection { repos: RwLock::new(Vec::with_capacity(8)), - pkgs: RwLock::new(HashMap::with_capacity(PKGNUM)), - repos_pkgs: RwLock::new(HashMap::with_capacity(PKGNUM)), + repos_pkgs: RwLock::new(BTreeMap::new()), + } + } + pub fn add_pkg( + &self, + r: Arc, + p: ArcLock, + ) -> Result<(), Error> { + let repo_name = r.path(); + let mut repos = self.repos.write().unwrap(); + let mut repos_pkgs = self.repos_pkgs.write().unwrap(); + if repos + .binary_search_by(|x| x.path().cmp(&repo_name)) + .is_err() + { + repos.push(r.clone()); + repos.sort_by(|a, b| a.path().cmp(&b.path())) + } + let pkg_name = p.read().unwrap().path(); + match repos_pkgs.get_mut(&repo_name) { + Some(pkg_map) => match pkg_map.get(&pkg_name) { + Some((r, p)) => { + return Err(Error::AlreadyPresent((r.clone(), p.clone()))); + } + None => { + pkg_map.insert(pkg_name, (r, p)); + } + }, + None => { + let mut pkg_map: PkgMap = BTreeMap::new(); + pkg_map.insert(pkg_name, (r, p)); + repos_pkgs.insert(repo_name, pkg_map); + } + } + + Ok(()) + } + pub fn find( + &self, + pkg_path: Path, + ) -> Result<(Arc, ArcLock), Error> { + let repos_pkgs = self.repos_pkgs.read().unwrap(); + for (_, pkg_map) in repos_pkgs.iter() { + match pkg_map.get(&pkg_path) { + Some((r, p)) => { + return Ok((r.clone(), p.clone())); + } + None => {} + } + } + Err(Error::NotFound) + } + pub fn find_in_repo( + &self, + repo_path: Path, + pkg_path: Path, + ) -> Result<(Arc, ArcLock), Error> { + let repos_pkgs = self.repos_pkgs.read().unwrap(); + match repos_pkgs.get(&repo_path) { + None => Err(Error::NotFound), + Some(pkg_map) => match pkg_map.get(&pkg_path) { + Some((r, p)) => Ok((r.clone(), p.clone())), + None => Err(Error::NotFound), + }, } } } diff --git a/bok/src/lib.rs b/bok/src/lib.rs index bbe129c..1ddfd1a 100644 --- a/bok/src/lib.rs +++ b/bok/src/lib.rs @@ -86,13 +86,13 @@ macro_rules! packages { } /// Marks your struct as a repository -pub trait Repository { +pub trait Repository: ::std::fmt::Debug { fn name(&self) -> RepoName; fn path(&self) -> Path; } /// This is an empty Package List. -#[derive(::std::default::Default)] +#[derive(::std::default::Default, Debug)] pub struct RepositoryEmpty {} impl Repository for RepositoryEmpty { fn name(&self) -> RepoName { diff --git a/bok/src/names.rs b/bok/src/names.rs index 0c15ddd..f9d6e0b 100644 --- a/bok/src/names.rs +++ b/bok/src/names.rs @@ -82,24 +82,6 @@ where } } -/// Marks your struct as a repository -pub trait Repository { - fn name(&self) -> RepoName; - fn path(&self) -> Path; -} - -/// This is an empty Package List. -#[derive(::std::default::Default)] -pub struct RepositoryEmpty {} -impl Repository for RepositoryEmpty { - fn name(&self) -> RepoName { - "RepositoryEmpty".into() - } - fn path(&self) -> Path { - Path::new("::bok::RepositoryEmpty") - } -} - /// Strong typedef for a package name #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)] pub struct PkgName(pub String);