151 lines · 4.8 KB · Rust
RawDownload
use std::{convert::TryFrom, rc::Rc, sync::Arc}; use parking_lot::lock_api::{ArcRwLockReadGuard, ArcRwLockWriteGuard}; use crate::{easy, Easy, EasyArc, EasyArcExclusive, EasyShared, Repository}; impl From<Repository> for Easy {    fn from(repo: Repository) -> Self {        Easy {            repo: Rc::new(repo),            state: Default::default(),        }    }} impl TryFrom<Easy> for Repository {    type Error = easy::borrow::repo::Error;     fn try_from(value: Easy) -> Result<Self, Self::Error> {        Rc::try_unwrap(value.repo).map_err(|_| easy::borrow::repo::Error)    }} impl TryFrom<EasyArc> for Repository {    type Error = easy::borrow::repo::Error;     fn try_from(value: EasyArc) -> Result<Self, Self::Error> {        Arc::try_unwrap(value.repo).map_err(|_| easy::borrow::repo::Error)    }} impl From<Repository> for EasyArc {    fn from(repo: Repository) -> Self {        EasyArc {            repo: Arc::new(repo),            state: Default::default(),        }    }} impl From<Repository> for EasyArcExclusive {    fn from(repo: Repository) -> Self {        EasyArcExclusive {            repo: Arc::new(parking_lot::RwLock::new(repo)),            state: Default::default(),        }    }} /// # Which `Easy` is for me?////// For one-off commands and single-threaded applications, use [`EasyShared`] or [`Easy`] as they don't allow mutable repository/// access which won't be needed.////// When multiple threads are involved, use [`EasyArc`] instead.////// Finally, if there is the need for adapting to changed object packs on disk or working with namespaces, mutable `Repository` access/// is needed, as provided by `EasyArcExclusive`. Currently mutable shared access is only available in thread-save versions, but that/// shall be fixed in the future as Rust's support for GATs becomes stable.// TODO: Update this once there is `EasyExclusive` as well.impl Repository {    /// Transform this instance into an [`EasyShared`] with borrowed `Repository`.    ///    /// Since a standard reference is used, the repository can never be mutated, which is required for the    /// fewest operations.    pub fn to_easy(&self) -> EasyShared<'_> {        EasyShared {            repo: self,            state: Default::default(),        }    }    /// Transform this instance into an [`Easy`], offering shared immutable access to the repository, for the current thread.    pub fn into_easy(self) -> Easy {        self.into()    }     /// Transform this instance into an [`EasyArc`], offering shared immutable access to the repository for use across threads.    pub fn into_easy_arc(self) -> EasyArc {        self.into()    }     /// Transform this instance into an [`EasyArcExclusive`], offering shared immutable access to the repository for use across threads.    pub fn into_easy_arc_exclusive(self) -> EasyArcExclusive {        self.into()    }} impl<'repo> easy::Access for EasyShared<'repo> {    type RepoRef = &'repo Repository;    type RepoRefMut = &'repo mut Repository;     fn repo(&self) -> Result<Self::RepoRef, easy::borrow::repo::Error> {        Ok(self.repo)    }     fn repo_mut(&self) -> Result<Self::RepoRefMut, easy::borrow::repo::Error> {        Err(easy::borrow::repo::Error)    }     fn state(&self) -> &easy::State {        &self.state    }} impl easy::Access for Easy {    type RepoRef = Rc<Repository>; // TODO: this could be a reference with GATs    type RepoRefMut = &'static mut Repository; // this is a lie     fn repo(&self) -> Result<Self::RepoRef, easy::borrow::repo::Error> {        Ok(self.repo.clone())    }     /// TODO: With GATs, this can return an actual RefMut<'a, _> so mutability is possible in single-threaded mode.    fn repo_mut(&self) -> Result<Self::RepoRefMut, easy::borrow::repo::Error> {        Err(easy::borrow::repo::Error)    }     fn state(&self) -> &easy::State {        &self.state    }} impl easy::Access for EasyArc {    type RepoRef = Arc<Repository>;    type RepoRefMut = &'static mut Repository; // this is a lie     fn repo(&self) -> Result<Self::RepoRef, easy::borrow::repo::Error> {        Ok(self.repo.clone())    }    fn repo_mut(&self) -> Result<Self::RepoRefMut, easy::borrow::repo::Error> {        Err(easy::borrow::repo::Error)    }    fn state(&self) -> &easy::State {        &self.state    }} impl easy::Access for EasyArcExclusive {    type RepoRef = ArcRwLockReadGuard<parking_lot::RawRwLock, Repository>;    type RepoRefMut = ArcRwLockWriteGuard<parking_lot::RawRwLock, Repository>;     fn repo(&self) -> Result<Self::RepoRef, easy::borrow::repo::Error> {        Ok(self.repo.read_arc())    }    fn repo_mut(&self) -> Result<Self::RepoRefMut, easy::borrow::repo::Error> {        Ok(self.repo.write_arc())    }    fn state(&self) -> &easy::State {        &self.state    }}