use crate::{
Action, ActionRef, ActionType, AppEntryDef, Create, CreateLink, Delete, DeleteLink, Entry,
EntryType, Record, SignedActionHashed, SignedHashed, Update,
};
use holo_hash::{ActionHash, AgentPubKey, EntryHash, HashableContent};
use holochain_serialized_bytes::prelude::*;
use kitsune_p2p_timestamp::Timestamp;
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SerializedBytes)]
#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
pub enum Op {
StoreRecord(StoreRecord),
StoreEntry(StoreEntry),
RegisterUpdate(RegisterUpdate),
RegisterDelete(RegisterDelete),
RegisterAgentActivity(RegisterAgentActivity),
RegisterCreateLink(RegisterCreateLink),
RegisterDeleteLink(RegisterDeleteLink),
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SerializedBytes)]
#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
pub struct StoreRecord {
pub record: Record,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SerializedBytes)]
#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
pub struct StoreEntry {
pub action: SignedHashed<EntryCreationAction>,
pub entry: Entry,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SerializedBytes)]
#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
pub struct RegisterUpdate {
pub update: SignedHashed<Update>,
pub new_entry: Option<Entry>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SerializedBytes)]
#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
pub struct RegisterDelete {
pub delete: SignedHashed<Delete>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SerializedBytes)]
#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
pub struct RegisterAgentActivity {
pub action: SignedActionHashed,
pub cached_entry: Option<Entry>,
}
impl AsRef<SignedActionHashed> for RegisterAgentActivity {
fn as_ref(&self) -> &SignedActionHashed {
&self.action
}
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SerializedBytes)]
#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
pub struct RegisterCreateLink {
pub create_link: SignedHashed<CreateLink>,
}
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, SerializedBytes)]
#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
pub struct RegisterDeleteLink {
pub delete_link: SignedHashed<DeleteLink>,
pub create_link: CreateLink,
}
impl Op {
pub fn author(&self) -> &AgentPubKey {
match self {
Op::StoreRecord(StoreRecord { record }) => record.action().author(),
Op::StoreEntry(StoreEntry { action, .. }) => action.hashed.author(),
Op::RegisterUpdate(RegisterUpdate { update, .. }) => &update.hashed.author,
Op::RegisterDelete(RegisterDelete { delete, .. }) => &delete.hashed.author,
Op::RegisterAgentActivity(RegisterAgentActivity { action, .. }) => {
action.hashed.author()
}
Op::RegisterCreateLink(RegisterCreateLink { create_link }) => {
&create_link.hashed.author
}
Op::RegisterDeleteLink(RegisterDeleteLink { delete_link, .. }) => {
&delete_link.hashed.author
}
}
}
pub fn timestamp(&self) -> Timestamp {
match self {
Op::StoreRecord(StoreRecord { record }) => record.action().timestamp(),
Op::StoreEntry(StoreEntry { action, .. }) => *action.hashed.timestamp(),
Op::RegisterUpdate(RegisterUpdate { update, .. }) => update.hashed.timestamp,
Op::RegisterDelete(RegisterDelete { delete, .. }) => delete.hashed.timestamp,
Op::RegisterAgentActivity(RegisterAgentActivity { action, .. }) => {
action.hashed.timestamp()
}
Op::RegisterCreateLink(RegisterCreateLink { create_link }) => {
create_link.hashed.timestamp
}
Op::RegisterDeleteLink(RegisterDeleteLink { delete_link, .. }) => {
delete_link.hashed.timestamp
}
}
}
pub fn action_seq(&self) -> u32 {
match self {
Op::StoreRecord(StoreRecord { record }) => record.action().action_seq(),
Op::StoreEntry(StoreEntry { action, .. }) => *action.hashed.action_seq(),
Op::RegisterUpdate(RegisterUpdate { update, .. }) => update.hashed.action_seq,
Op::RegisterDelete(RegisterDelete { delete, .. }) => delete.hashed.action_seq,
Op::RegisterAgentActivity(RegisterAgentActivity { action, .. }) => {
action.hashed.action_seq()
}
Op::RegisterCreateLink(RegisterCreateLink { create_link }) => {
create_link.hashed.action_seq
}
Op::RegisterDeleteLink(RegisterDeleteLink { delete_link, .. }) => {
delete_link.hashed.action_seq
}
}
}
pub fn prev_action(&self) -> Option<&ActionHash> {
match self {
Op::StoreRecord(StoreRecord { record }) => record.action().prev_action(),
Op::StoreEntry(StoreEntry { action, .. }) => Some(action.hashed.prev_action()),
Op::RegisterUpdate(RegisterUpdate { update, .. }) => Some(&update.hashed.prev_action),
Op::RegisterDelete(RegisterDelete { delete, .. }) => Some(&delete.hashed.prev_action),
Op::RegisterAgentActivity(RegisterAgentActivity { action, .. }) => {
action.hashed.prev_action()
}
Op::RegisterCreateLink(RegisterCreateLink { create_link }) => {
Some(&create_link.hashed.prev_action)
}
Op::RegisterDeleteLink(RegisterDeleteLink { delete_link, .. }) => {
Some(&delete_link.hashed.prev_action)
}
}
}
pub fn action_type(&self) -> ActionType {
match self {
Op::StoreRecord(StoreRecord { record }) => record.action().action_type(),
Op::StoreEntry(StoreEntry { action, .. }) => action.hashed.action_type(),
Op::RegisterUpdate(RegisterUpdate { .. }) => ActionType::Update,
Op::RegisterDelete(RegisterDelete { .. }) => ActionType::Delete,
Op::RegisterAgentActivity(RegisterAgentActivity { action, .. }) => {
action.hashed.action_type()
}
Op::RegisterCreateLink(RegisterCreateLink { .. }) => ActionType::CreateLink,
Op::RegisterDeleteLink(RegisterDeleteLink { .. }) => ActionType::DeleteLink,
}
}
pub fn entry_data(&self) -> Option<(&EntryHash, &EntryType)> {
match self {
Op::StoreRecord(StoreRecord { record }) => record.action().entry_data(),
Op::StoreEntry(StoreEntry { action, .. }) => {
Some((action.hashed.entry_hash(), action.hashed.entry_type()))
}
Op::RegisterUpdate(RegisterUpdate { update, .. }) => {
Some((&update.hashed.entry_hash, &update.hashed.entry_type))
}
Op::RegisterAgentActivity(RegisterAgentActivity { action, .. }) => {
action.hashed.entry_data()
}
Op::RegisterDelete(_) | Op::RegisterCreateLink(_) | Op::RegisterDeleteLink(_) => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, SerializedBytes, Eq)]
#[cfg_attr(feature = "fuzzing", derive(arbitrary::Arbitrary))]
pub enum EntryCreationAction {
Create(Create),
Update(Update),
}
impl EntryCreationAction {
pub fn author(&self) -> &AgentPubKey {
match self {
EntryCreationAction::Create(Create { author, .. })
| EntryCreationAction::Update(Update { author, .. }) => author,
}
}
pub fn timestamp(&self) -> &Timestamp {
match self {
EntryCreationAction::Create(Create { timestamp, .. })
| EntryCreationAction::Update(Update { timestamp, .. }) => timestamp,
}
}
pub fn action_seq(&self) -> &u32 {
match self {
EntryCreationAction::Create(Create { action_seq, .. })
| EntryCreationAction::Update(Update { action_seq, .. }) => action_seq,
}
}
pub fn prev_action(&self) -> &ActionHash {
match self {
EntryCreationAction::Create(Create { prev_action, .. })
| EntryCreationAction::Update(Update { prev_action, .. }) => prev_action,
}
}
pub fn entry_type(&self) -> &EntryType {
match self {
EntryCreationAction::Create(Create { entry_type, .. })
| EntryCreationAction::Update(Update { entry_type, .. }) => entry_type,
}
}
pub fn entry_hash(&self) -> &EntryHash {
match self {
EntryCreationAction::Create(Create { entry_hash, .. })
| EntryCreationAction::Update(Update { entry_hash, .. }) => entry_hash,
}
}
pub fn app_entry_def(&self) -> Option<&AppEntryDef> {
match self.entry_type() {
EntryType::App(app_entry_def) => Some(app_entry_def),
_ => None,
}
}
pub fn is_agent_entry_type(&self) -> bool {
matches!(self.entry_type(), EntryType::AgentPubKey)
}
pub fn is_cap_claim_entry_type(&self) -> bool {
matches!(self.entry_type(), EntryType::CapClaim)
}
pub fn is_cap_grant_entry_type(&self) -> bool {
matches!(self.entry_type(), EntryType::CapGrant)
}
pub fn action_type(&self) -> ActionType {
match self {
EntryCreationAction::Create(_) => ActionType::Create,
EntryCreationAction::Update(_) => ActionType::Update,
}
}
}
impl HashableContent for EntryCreationAction {
type HashType = holo_hash::hash_type::Action;
fn hash_type(&self) -> Self::HashType {
use holo_hash::PrimitiveHashType;
holo_hash::hash_type::Action::new()
}
fn hashable_content(&self) -> holo_hash::HashableContentBytes {
let h = match self {
EntryCreationAction::Create(create) => ActionRef::Create(create),
EntryCreationAction::Update(update) => ActionRef::Update(update),
};
let sb = SerializedBytes::from(UnsafeBytes::from(
holochain_serialized_bytes::encode(&h).expect("Could not serialize HashableContent"),
));
holo_hash::HashableContentBytes::Content(sb)
}
}
impl From<EntryCreationAction> for Action {
fn from(e: EntryCreationAction) -> Self {
match e {
EntryCreationAction::Create(c) => Action::Create(c),
EntryCreationAction::Update(u) => Action::Update(u),
}
}
}
impl From<Create> for EntryCreationAction {
fn from(c: Create) -> Self {
EntryCreationAction::Create(c)
}
}
impl From<Update> for EntryCreationAction {
fn from(u: Update) -> Self {
EntryCreationAction::Update(u)
}
}
impl TryFrom<Action> for EntryCreationAction {
type Error = crate::WrongActionError;
fn try_from(value: Action) -> Result<Self, Self::Error> {
match value {
Action::Create(h) => Ok(EntryCreationAction::Create(h)),
Action::Update(h) => Ok(EntryCreationAction::Update(h)),
_ => Err(crate::WrongActionError(format!("{:?}", value))),
}
}
}
pub trait UnitEnum {
type Unit: core::fmt::Debug
+ Clone
+ Copy
+ PartialEq
+ Eq
+ PartialOrd
+ Ord
+ core::hash::Hash;
fn to_unit(&self) -> Self::Unit;
fn unit_iter() -> Box<dyn Iterator<Item = Self::Unit>>;
}
impl UnitEnum for () {
type Unit = ();
fn to_unit(&self) -> Self::Unit {}
fn unit_iter() -> Box<dyn Iterator<Item = Self::Unit>> {
Box::new([].into_iter())
}
}
#[derive(Clone, Debug)]
pub enum UnitEnumEither<E: UnitEnum> {
Enum(E),
Unit(E::Unit),
}