Collection work
Signed-off-by: Luca Fulchir <luca.fulchir@runesauth.com>
This commit is contained in:
parent
860659548f
commit
cfd50cf8be
21
Cargo.lock
generated
21
Cargo.lock
generated
@ -77,6 +77,7 @@ dependencies = [
|
|||||||
"quote",
|
"quote",
|
||||||
"semver",
|
"semver",
|
||||||
"sha3",
|
"sha3",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -283,6 +284,26 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"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]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
|
@ -42,7 +42,7 @@ pub fn repository(attrs: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[derive(::bok::Repository)]
|
#[derive(::bok::Repository, Debug)]
|
||||||
#ast
|
#ast
|
||||||
}
|
}
|
||||||
.into()
|
.into()
|
||||||
|
@ -21,3 +21,4 @@ proc-macro2 = "1.0"
|
|||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
semver = { version = "1.0" }
|
semver = { version = "1.0" }
|
||||||
sha3 = { version = "0.10" }
|
sha3 = { version = "0.10" }
|
||||||
|
thiserror = { version = "2.0" }
|
||||||
|
@ -16,29 +16,99 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use ::std::{
|
use ::std::{
|
||||||
collections::HashMap,
|
collections::BTreeMap,
|
||||||
sync::{Arc, RwLock},
|
sync::{Arc, RwLock},
|
||||||
vec::Vec,
|
vec::Vec,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::{Path, Pkg, PkgName, RepoName, Repository};
|
||||||
|
|
||||||
|
#[derive(Debug, ::thiserror::Error)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("package already present")]
|
||||||
|
AlreadyPresent((Arc<dyn Repository>, ArcLock<dyn Pkg>)),
|
||||||
|
#[error("not found")]
|
||||||
|
NotFound,
|
||||||
|
}
|
||||||
|
|
||||||
type ArcLock<T> = Arc<RwLock<T>>;
|
type ArcLock<T> = Arc<RwLock<T>>;
|
||||||
type PkgMap = HashMap<crate::PkgName, ArcLock<dyn crate::Pkg>>;
|
type PkgMap = BTreeMap<Path<PkgName>, (Arc<dyn Repository>, ArcLock<dyn Pkg>)>;
|
||||||
|
|
||||||
/// Collection of packages, subset of what is present on one repository only
|
/// Collection of packages, subset of what is present on one repository only
|
||||||
pub struct Collection {
|
pub struct Collection {
|
||||||
repos: RwLock<Vec<ArcLock<dyn crate::Repository>>>,
|
repos: RwLock<Vec<Arc<dyn Repository>>>,
|
||||||
pkgs: RwLock<PkgMap>,
|
repos_pkgs: RwLock<BTreeMap<Path<RepoName>, PkgMap>>,
|
||||||
repos_pkgs: RwLock<HashMap<crate::RepoName, PkgMap>>,
|
|
||||||
//repos_pkgs: RwLock<HashMap<crate::Repository, PkgMap>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Collection {
|
impl Collection {
|
||||||
|
/// Create a new empty collection of pkgs
|
||||||
pub fn new() -> Collection {
|
pub fn new() -> Collection {
|
||||||
const PKGNUM: usize = 512;
|
|
||||||
Collection {
|
Collection {
|
||||||
repos: RwLock::new(Vec::with_capacity(8)),
|
repos: RwLock::new(Vec::with_capacity(8)),
|
||||||
pkgs: RwLock::new(HashMap::with_capacity(PKGNUM)),
|
repos_pkgs: RwLock::new(BTreeMap::new()),
|
||||||
repos_pkgs: RwLock::new(HashMap::with_capacity(PKGNUM)),
|
}
|
||||||
|
}
|
||||||
|
pub fn add_pkg(
|
||||||
|
&self,
|
||||||
|
r: Arc<dyn Repository>,
|
||||||
|
p: ArcLock<dyn Pkg>,
|
||||||
|
) -> 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<PkgName>,
|
||||||
|
) -> Result<(Arc<dyn Repository>, ArcLock<dyn Pkg>), 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<RepoName>,
|
||||||
|
pkg_path: Path<PkgName>,
|
||||||
|
) -> Result<(Arc<dyn Repository>, ArcLock<dyn Pkg>), 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),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,13 +86,13 @@ macro_rules! packages {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Marks your struct as a repository
|
/// Marks your struct as a repository
|
||||||
pub trait Repository {
|
pub trait Repository: ::std::fmt::Debug {
|
||||||
fn name(&self) -> RepoName;
|
fn name(&self) -> RepoName;
|
||||||
fn path(&self) -> Path<RepoName>;
|
fn path(&self) -> Path<RepoName>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is an empty Package List.
|
/// This is an empty Package List.
|
||||||
#[derive(::std::default::Default)]
|
#[derive(::std::default::Default, Debug)]
|
||||||
pub struct RepositoryEmpty {}
|
pub struct RepositoryEmpty {}
|
||||||
impl Repository for RepositoryEmpty {
|
impl Repository for RepositoryEmpty {
|
||||||
fn name(&self) -> RepoName {
|
fn name(&self) -> RepoName {
|
||||||
|
@ -82,24 +82,6 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Marks your struct as a repository
|
|
||||||
pub trait Repository {
|
|
||||||
fn name(&self) -> RepoName;
|
|
||||||
fn path(&self) -> Path<RepoName>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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<RepoName> {
|
|
||||||
Path::new("::bok::RepositoryEmpty")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Strong typedef for a package name
|
/// Strong typedef for a package name
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)]
|
||||||
pub struct PkgName(pub String);
|
pub struct PkgName(pub String);
|
||||||
|
Loading…
Reference in New Issue
Block a user