use crate::MigrationTarget;
use holo_hash::ActionHash;
use holo_hash::AgentPubKey;
use holochain_serialized_bytes::prelude::*;
use holochain_timestamp::Timestamp;
use std::collections::HashSet;
#[cfg(test)]
mod test;
#[derive(Serialize, Deserialize, SerializedBytes, Debug, PartialEq, Eq, Hash, Clone)]
pub struct ChainFilter<H: Eq + Ord + std::hash::Hash = ActionHash> {
pub chain_top: H,
pub limit_conditions: LimitConditions<H>,
pub include_cached_entries: bool,
}
#[derive(Serialize, Deserialize, Debug, Eq, Clone)]
pub enum LimitConditions<H: Eq + Ord + std::hash::Hash = ActionHash> {
ToGenesis,
Take(u32),
UntilTimestamp(Timestamp),
UntilHash(HashSet<H>),
Multiple(Option<u32>, HashSet<H>, Option<Timestamp>),
}
impl<H: Eq + Ord + std::hash::Hash> core::hash::Hash for LimitConditions<H> {
fn hash<HH: std::hash::Hasher>(&self, state: &mut HH) {
core::mem::discriminant(self).hash(state);
match self {
LimitConditions::ToGenesis => (),
LimitConditions::Take(t) => t.hash(state),
LimitConditions::UntilTimestamp(ts) => ts.hash(state),
LimitConditions::UntilHash(u) => {
let mut u: Vec<_> = u.iter().collect();
u.sort_unstable();
u.hash(state);
}
LimitConditions::Multiple(n, u, t) => {
let mut u: Vec<_> = u.iter().collect();
u.sort_unstable();
u.hash(state);
n.hash(state);
t.hash(state);
}
}
}
}
impl<H: Eq + Ord + std::hash::Hash> core::cmp::PartialEq for LimitConditions<H> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Take(l0), Self::Take(r0)) => l0 == r0,
(Self::UntilTimestamp(l0), Self::UntilTimestamp(r0)) => l0 == r0,
(Self::UntilHash(a), Self::UntilHash(b)) => {
let mut a: Vec<_> = a.iter().collect();
let mut b: Vec<_> = b.iter().collect();
a.sort_unstable();
b.sort_unstable();
a == b
}
(Self::Multiple(l0, a, t0), Self::Multiple(r0, b, t1)) => {
let mut a: Vec<_> = a.iter().collect();
let mut b: Vec<_> = b.iter().collect();
a.sort_unstable();
b.sort_unstable();
l0 == r0 && a == b && t0 == t1
}
_ => core::mem::discriminant(self) == core::mem::discriminant(other),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct MustGetAgentActivityInput {
pub author: AgentPubKey,
pub chain_filter: ChainFilter,
}
impl<H: Eq + Ord + std::hash::Hash> ChainFilter<H> {
pub fn new(chain_top: H) -> Self {
Self {
chain_top,
limit_conditions: Default::default(),
include_cached_entries: false,
}
}
pub fn take(mut self, n: u32) -> Self {
self.limit_conditions = match self.limit_conditions {
LimitConditions::ToGenesis => LimitConditions::Take(n),
LimitConditions::Take(old_n) => LimitConditions::Take(old_n.min(n)),
LimitConditions::UntilTimestamp(t) => {
LimitConditions::Multiple(Some(n), HashSet::new(), Some(t))
}
LimitConditions::UntilHash(u) => LimitConditions::Multiple(Some(n), u, None),
LimitConditions::Multiple(old_n, u, t) => {
LimitConditions::Multiple(Some(old_n.unwrap_or(u32::MAX).min(n)), u, t)
}
};
self
}
pub fn include_cached_entries(mut self) -> Self {
self.include_cached_entries = true;
self
}
pub fn until_timestamp(mut self, timestamp: Timestamp) -> Self {
self.limit_conditions = match self.limit_conditions {
LimitConditions::ToGenesis => LimitConditions::UntilTimestamp(timestamp),
LimitConditions::Take(n) => {
LimitConditions::Multiple(Some(n), HashSet::new(), Some(timestamp))
}
LimitConditions::UntilTimestamp(old_ts) => {
LimitConditions::UntilTimestamp(timestamp.max(old_ts))
}
LimitConditions::UntilHash(u) => LimitConditions::Multiple(None, u, Some(timestamp)),
LimitConditions::Multiple(n, u, old_ts) => {
LimitConditions::Multiple(n, u, Some(old_ts.unwrap_or(Timestamp(0)).max(timestamp)))
}
};
self
}
pub fn until_hash(mut self, action_hash: H) -> Self {
self.limit_conditions = match self.limit_conditions {
LimitConditions::ToGenesis => {
LimitConditions::UntilHash(Some(action_hash).into_iter().collect())
}
LimitConditions::Take(n) => {
LimitConditions::Multiple(Some(n), Some(action_hash).into_iter().collect(), None)
}
LimitConditions::UntilTimestamp(t) => {
LimitConditions::Multiple(None, Some(action_hash).into_iter().collect(), Some(t))
}
LimitConditions::UntilHash(mut u) => {
u.insert(action_hash);
LimitConditions::UntilHash(u)
}
LimitConditions::Multiple(n, mut u, t) => {
u.insert(action_hash);
LimitConditions::Multiple(n, u, t)
}
};
self
}
pub fn get_until_hash(&self) -> Option<&HashSet<H>> {
match &self.limit_conditions {
LimitConditions::UntilHash(u) => Some(u),
LimitConditions::Multiple(_, u, _) => Some(u),
_ => None,
}
}
pub fn get_take(&self) -> Option<u32> {
match self.limit_conditions {
LimitConditions::Take(n) => Some(n),
LimitConditions::Multiple(n, _, _) => n,
_ => None,
}
}
pub fn get_until_timestamp(&self) -> Option<Timestamp> {
match self.limit_conditions {
LimitConditions::UntilTimestamp(ts) => Some(ts),
LimitConditions::Multiple(_, _, ts) => ts,
_ => None,
}
}
}
impl<H: Eq + Ord + std::hash::Hash> Default for LimitConditions<H> {
fn default() -> Self {
Self::ToGenesis
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, SerializedBytes)]
pub struct CloseChainInput {
pub new_target: Option<MigrationTarget>,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, SerializedBytes)]
pub struct OpenChainInput {
pub prev_target: MigrationTarget,
pub close_hash: ActionHash,
}