use super::*;
use holochain_integrity_types::prelude::{CapClaimEntry, CapGrantEntry};
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OpEntry<ET>
where
ET: UnitEnum,
{
CreateEntry {
app_entry: ET,
action: TypedAction<CreateData>,
},
CreateAgent {
action: TypedAction<CreateData>,
},
UpdateEntry {
app_entry: ET,
action: TypedAction<UpdateData>,
},
UpdateAgent {
action: TypedAction<UpdateData>,
},
CreateCapGrant {
entry: CapGrantEntry,
action: TypedAction<CreateData>,
},
CreateCapClaim {
entry: CapClaimEntry,
action: TypedAction<CreateData>,
},
UpdateCapGrant {
action: TypedAction<UpdateData>,
entry: CapGrantEntry,
},
UpdateCapClaim {
action: TypedAction<UpdateData>,
entry: CapClaimEntry,
},
}
impl<ET: UnitEnum> OpEntry<ET> {
pub fn agent(&self) -> Option<AgentPubKey> {
match self {
OpEntry::CreateAgent { action } => Some(action.data.entry_hash.clone().into()),
_ => None,
}
}
pub fn new_key(&self) -> Option<AgentPubKey> {
match self {
OpEntry::UpdateAgent { action } => Some(action.data.entry_hash.clone().into()),
_ => None,
}
}
pub fn original_key(&self) -> Option<AgentPubKey> {
match self {
OpEntry::UpdateAgent { action } => {
Some(action.data.original_entry_address.clone().into())
}
_ => None,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum OpUpdate<ET>
where
ET: UnitEnum,
{
Entry {
app_entry: ET,
action: TypedAction<UpdateData>,
},
PrivateEntry {
app_entry_type: <ET as UnitEnum>::Unit,
action: TypedAction<UpdateData>,
},
Agent {
new_key: AgentPubKey,
original_key: AgentPubKey,
action: TypedAction<UpdateData>,
},
CapClaim {
action: TypedAction<UpdateData>,
},
CapGrant {
action: TypedAction<UpdateData>,
},
}
impl<ET: UnitEnum> OpUpdate<ET> {
pub fn action(&self) -> &TypedAction<UpdateData> {
match self {
OpUpdate::Entry { action, .. }
| OpUpdate::PrivateEntry { action, .. }
| OpUpdate::Agent { action, .. }
| OpUpdate::CapClaim { action, .. }
| OpUpdate::CapGrant { action, .. } => action,
}
}
pub fn original_action_hash(&self) -> &ActionHash {
&self.action().data.original_action_address
}
pub fn original_entry_hash(&self) -> &EntryHash {
&self.action().data.original_entry_address
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct OpDelete {
pub action: TypedAction<DeleteData>,
}
#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::short_hand::{ah, ak, eh};
fn header() -> ActionHeader {
ActionHeader {
author: ak(1),
timestamp: Timestamp::from_micros(0),
action_seq: 0,
prev_action: None,
}
}
#[test]
fn op_delete_constructs_and_clones() {
let op = OpDelete {
action: TypedAction {
header: header(),
data: DeleteData {
deletes_address: ah(2),
deletes_entry_address: eh(3),
},
},
};
assert_eq!(op.clone(), op);
}
fn update_action(
original_action_address: ActionHash,
original_entry_address: EntryHash,
) -> TypedAction<UpdateData> {
TypedAction {
header: header(),
data: UpdateData {
original_action_address,
original_entry_address,
entry_type: holochain_integrity_types::action::EntryType::AgentPubKey,
entry_hash: eh(9),
},
}
}
#[test]
fn op_update_action_and_hashes_are_uniform_across_variants() {
let action = update_action(ah(4), eh(5));
let op = OpUpdate::<()>::CapClaim {
action: action.clone(),
};
assert_eq!(op.action(), &action);
assert_eq!(op.original_action_hash(), &ah(4));
assert_eq!(op.original_entry_hash(), &eh(5));
}
#[test]
fn op_update_entry_has_the_same_accessors_as_every_other_variant() {
let action = update_action(ah(6), eh(7));
let op = OpUpdate::<()>::Entry {
app_entry: (),
action: action.clone(),
};
assert_eq!(op.original_action_hash(), &ah(6));
assert_eq!(op.original_entry_hash(), &eh(7));
}
#[test]
fn op_entry_create_agent_exposes_agent_key() {
let action = TypedAction {
header: header(),
data: CreateData {
entry_type: holochain_integrity_types::action::EntryType::AgentPubKey,
entry_hash: eh(9),
},
};
let op = OpEntry::<()>::CreateAgent { action };
assert_eq!(op.agent(), Some(AgentPubKey::from(eh(9))));
assert_eq!(op.new_key(), None);
}
#[test]
fn op_entry_update_agent_exposes_keys() {
let action = update_action(ah(10), eh(11));
let op = OpEntry::<()>::UpdateAgent { action };
assert_eq!(op.new_key(), Some(AgentPubKey::from(eh(9))));
assert_eq!(op.original_key(), Some(AgentPubKey::from(eh(11))));
}
#[test]
fn op_entry_create_entry_has_no_agent_key() {
let action = TypedAction {
header: header(),
data: CreateData {
entry_type: holochain_integrity_types::action::EntryType::App(
crate::test_utils::short_hand::public_app_entry_def(0, 0),
),
entry_hash: eh(12),
},
};
let op = OpEntry::<()>::CreateEntry {
app_entry: (),
action,
};
assert_eq!(op.agent(), None);
}
}