// Copyright © 2022 The Radicle Link Contributors // // This file is part of radicle-link, distributed under the GPLv3 with Radicle // Linking Exception. For full terms see the included LICENSE file. use std::{error::Error, fmt}; use serde::{Deserialize, Serialize}; use crate::{ history::{Contents, Timestamp}, signatures, TypeName, }; /// Change storage. pub trait Storage { type StoreError: Error + Send + Sync + 'static; type LoadError: Error + Send + Sync + 'static; type ObjectId; type Resource; type Signatures; /// Store a new change. #[allow(clippy::type_complexity)] fn store( &self, authority: Self::Resource, signer: &G, template: Template, ) -> Result, Self::StoreError> where G: crypto::Signer; /// Load a change. #[allow(clippy::type_complexity)] fn load( &self, id: Self::ObjectId, ) -> Result, Self::LoadError>; } /// Change template, used to create a new change. pub struct Template { pub typename: TypeName, pub history_type: String, pub tips: Vec, pub message: String, pub contents: Contents, } #[derive(Clone, Debug)] pub struct Change { /// The content address of the `Change` itself. pub id: Id, /// The content address of the tree of the `Change`. pub revision: Id, /// The cryptographic signature(s) and their public keys of the /// authors. pub signature: Signature, /// The parent resource that this change lives under. For example, /// this change could be for a patch of a project. pub resource: Resource, /// The manifest describing the type of object as well as the type /// of history for this `Change`. pub manifest: Manifest, /// The contents that describe `Change`. pub contents: Contents, /// Timestamp of change. pub timestamp: Timestamp, } impl fmt::Display for Change where Id: fmt::Display, { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "Change {{ id: {} }}", self.id) } } impl Change { pub fn id(&self) -> &Id { &self.id } pub fn typename(&self) -> &TypeName { &self.manifest.typename } pub fn contents(&self) -> &Contents { &self.contents } pub fn resource(&self) -> &Resource { &self.resource } } impl Change where Id: AsRef<[u8]>, { pub fn valid_signatures(&self) -> bool { self.signature .iter() .all(|(key, sig)| key.verify(self.revision.as_ref(), sig).is_ok()) } } impl Change where Id: AsRef<[u8]>, { pub fn valid_signatures(&self) -> bool { self.signature.verify(self.revision.as_ref()) } } #[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)] pub struct Manifest { /// The name given to the type of collaborative object. pub typename: TypeName, /// The type of history for the collaborative oject. pub history_type: String, }