tuf 0.3.0-beta4

Library for The Update Framework (TUF)
Documentation
use {
    crate::{
        interchange::DataInterchange,
        metadata::{MetadataPath, MetadataVersion, TargetPath},
        repository::{RepositoryProvider, RepositoryStorage},
        Error, Result,
    },
    futures_io::AsyncRead,
    futures_util::future::{BoxFuture, FutureExt},
    std::sync::{
        atomic::{AtomicBool, Ordering},
        Arc,
    },
};

pub(crate) struct ErrorRepository<R> {
    repo: R,
    fail_metadata_stores: Arc<AtomicBool>,
}

impl<R> ErrorRepository<R> {
    pub(crate) fn new(repo: R) -> Self {
        Self {
            repo,
            fail_metadata_stores: Arc::new(AtomicBool::new(false)),
        }
    }

    pub(crate) fn fail_metadata_stores(&self, fail_metadata_stores: bool) {
        self.fail_metadata_stores
            .store(fail_metadata_stores, Ordering::SeqCst);
    }
}

impl<D, R> RepositoryProvider<D> for ErrorRepository<R>
where
    R: RepositoryProvider<D> + Sync,
    D: DataInterchange + Sync,
{
    fn fetch_metadata<'a>(
        &'a self,
        meta_path: &MetadataPath,
        version: &MetadataVersion,
    ) -> BoxFuture<'a, Result<Box<dyn AsyncRead + Send + Unpin + 'a>>> {
        self.repo.fetch_metadata(meta_path, version)
    }

    fn fetch_target<'a>(
        &'a self,
        target_path: &TargetPath,
    ) -> BoxFuture<'a, Result<Box<dyn AsyncRead + Send + Unpin + 'a>>> {
        self.repo.fetch_target(target_path)
    }
}

impl<D, R> RepositoryStorage<D> for ErrorRepository<R>
where
    R: RepositoryStorage<D> + Sync,
    D: DataInterchange + Sync,
{
    fn store_metadata<'a>(
        &'a mut self,
        meta_path: &MetadataPath,
        version: &MetadataVersion,
        metadata: &'a mut (dyn AsyncRead + Send + Unpin + 'a),
    ) -> BoxFuture<'a, Result<()>> {
        if self.fail_metadata_stores.load(Ordering::SeqCst) {
            async { Err(Error::Encoding("failed".into())) }.boxed()
        } else {
            self.repo.store_metadata(meta_path, version, metadata)
        }
    }

    fn store_target<'a>(
        &'a mut self,
        target_path: &TargetPath,
        target: &'a mut (dyn AsyncRead + Send + Unpin + 'a),
    ) -> BoxFuture<'a, Result<()>> {
        self.repo.store_target(target_path, target)
    }
}