use crate::action::ZomeIndex;
use crate::zome::ZomeName;
use crate::EntryDefIndex;
use crate::EntryDefs;
use crate::FunctionName;
use crate::LinkType;
use crate::Timestamp;
use holo_hash::DnaHash;
use holochain_serialized_bytes::prelude::*;
use std::time::Duration;
#[cfg(test)]
mod test;
#[allow(missing_docs)]
#[derive(Clone, Debug, Serialize, Deserialize, SerializedBytes, PartialEq)]
pub struct ZomeInfo {
pub name: ZomeName,
pub id: ZomeIndex,
pub properties: SerializedBytes,
pub entry_defs: EntryDefs,
pub extern_fns: Vec<FunctionName>,
pub zome_types: ScopedZomeTypesSet,
}
impl ZomeInfo {
pub fn new(
name: ZomeName,
id: ZomeIndex,
properties: SerializedBytes,
entry_defs: EntryDefs,
extern_fns: Vec<FunctionName>,
zome_types: ScopedZomeTypesSet,
) -> Self {
Self {
name,
id,
properties,
entry_defs,
extern_fns,
zome_types,
}
}
}
pub type NetworkSeed = String;
#[allow(dead_code)]
const fn standard_quantum_time() -> Duration {
Duration::from_secs(60 * 5)
}
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[cfg_attr(
feature = "fuzzing",
derive(arbitrary::Arbitrary, proptest_derive::Arbitrary)
)]
#[cfg_attr(feature = "full-dna-def", derive(derive_builder::Builder))]
pub struct DnaModifiers {
pub network_seed: NetworkSeed,
#[cfg_attr(feature = "full-dna-def", builder(default = "().try_into().unwrap()"))]
pub properties: SerializedBytes,
#[cfg_attr(feature = "full-dna-def", builder(default = "Timestamp::now()"))]
pub origin_time: Timestamp,
#[cfg_attr(feature = "full-dna-def", builder(default = "standard_quantum_time()"))]
#[cfg_attr(feature = "full-dna-def", serde(default = "standard_quantum_time"))]
pub quantum_time: Duration,
}
impl DnaModifiers {
pub fn update(mut self, modifiers: DnaModifiersOpt) -> DnaModifiers {
self.network_seed = modifiers.network_seed.unwrap_or(self.network_seed);
self.properties = modifiers.properties.unwrap_or(self.properties);
self.origin_time = modifiers.origin_time.unwrap_or(self.origin_time);
self.quantum_time = modifiers.quantum_time.unwrap_or(self.quantum_time);
self
}
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[cfg_attr(
feature = "fuzzing",
derive(arbitrary::Arbitrary, proptest_derive::Arbitrary)
)]
pub struct DnaModifiersOpt<P = SerializedBytes> {
pub network_seed: Option<NetworkSeed>,
pub properties: Option<P>,
pub origin_time: Option<Timestamp>,
pub quantum_time: Option<Duration>,
}
impl<P: TryInto<SerializedBytes, Error = E>, E: Into<SerializedBytesError>> Default
for DnaModifiersOpt<P>
{
fn default() -> Self {
Self::none()
}
}
impl<P: TryInto<SerializedBytes, Error = E>, E: Into<SerializedBytesError>> DnaModifiersOpt<P> {
pub fn none() -> Self {
Self {
network_seed: None,
properties: None,
origin_time: None,
quantum_time: None,
}
}
pub fn serialized(self) -> Result<DnaModifiersOpt<SerializedBytes>, E> {
let Self {
network_seed,
properties,
origin_time,
quantum_time,
} = self;
let properties = if let Some(p) = properties {
Some(p.try_into()?)
} else {
None
};
Ok(DnaModifiersOpt {
network_seed,
properties,
origin_time,
quantum_time,
})
}
pub fn with_network_seed(mut self, network_seed: NetworkSeed) -> Self {
self.network_seed = Some(network_seed);
self
}
pub fn with_properties(mut self, properties: P) -> Self {
self.properties = Some(properties);
self
}
pub fn with_origin_time(mut self, origin_time: Timestamp) -> Self {
self.origin_time = Some(origin_time);
self
}
pub fn with_quantum_time(mut self, quantum_time: Duration) -> Self {
self.quantum_time = Some(quantum_time);
self
}
pub fn has_some_option_set(&self) -> bool {
self.network_seed.is_some() || self.properties.is_some() || self.origin_time.is_some()
}
}
#[derive(Debug, Serialize, Deserialize)]
pub struct DnaInfoV1 {
pub name: String,
pub hash: DnaHash,
pub properties: SerializedBytes,
pub zome_names: Vec<ZomeName>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct DnaInfoV2 {
pub name: String,
pub hash: DnaHash,
pub modifiers: DnaModifiers,
pub zome_names: Vec<ZomeName>,
}
pub type DnaInfo = DnaInfoV2;
#[derive(Clone, Debug, Serialize, Deserialize, SerializedBytes, PartialEq, Default)]
pub struct ScopedZomeTypesSet {
pub entries: ScopedZomeTypes<EntryDefIndex>,
pub links: ScopedZomeTypes<LinkType>,
}
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct ScopedZomeTypes<T>(pub Vec<(ZomeIndex, Vec<T>)>);
impl<T> Default for ScopedZomeTypes<T> {
fn default() -> Self {
Self(Default::default())
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ZomeTypesKey<T>
where
T: U8Index + Copy,
{
pub zome_index: ZomeDependencyIndex,
pub type_index: T,
}
pub type ZomeEntryTypesKey = ZomeTypesKey<EntryDefIndex>;
pub type ZomeLinkTypesKey = ZomeTypesKey<LinkType>;
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ZomeDependencyIndex(pub u8);
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ScopedZomeType<T> {
pub zome_index: ZomeIndex,
pub zome_type: T,
}
pub type ScopedEntryDefIndex = ScopedZomeType<EntryDefIndex>;
pub type ScopedLinkType = ScopedZomeType<LinkType>;
impl<T> ScopedZomeTypes<T>
where
T: U8Index + Copy,
{
pub fn get<K>(&self, key: K) -> Option<ScopedZomeType<T>>
where
K: Into<ZomeTypesKey<T>>,
{
let key = key.into();
self.0
.get(key.zome_index.index())
.and_then(|(zome_index, types)| {
types
.get(key.type_index.index())
.copied()
.map(|zome_type| ScopedZomeType {
zome_index: *zome_index,
zome_type,
})
})
}
pub fn find<I, K>(&self, iter: I, scoped_type: ScopedZomeType<T>) -> Option<I::Item>
where
I: IntoIterator<Item = K>,
K: Into<ZomeTypesKey<T>> + Copy,
T: PartialEq,
{
iter.into_iter()
.find_map(|key| (self.get(key)? == scoped_type).then_some(key))
}
pub fn find_key(&self, scoped_type: ScopedZomeType<T>) -> Option<ZomeTypesKey<T>>
where
T: PartialEq,
T: From<u8>,
{
self.0
.iter()
.position(|(zome_index, _)| *zome_index == scoped_type.zome_index)
.and_then(|zome_index| {
self.0[zome_index]
.1
.iter()
.position(|zome_type| *zome_type == scoped_type.zome_type)
.and_then(|type_index| {
Some(ZomeTypesKey {
zome_index: u8::try_from(zome_index).ok()?.into(),
type_index: u8::try_from(type_index).ok()?.into(),
})
})
})
}
pub fn dependencies(&self) -> impl Iterator<Item = ZomeIndex> + '_ {
self.0.iter().map(|(zome_index, _)| *zome_index)
}
}
impl From<EntryDefIndex> for ZomeEntryTypesKey {
fn from(type_index: EntryDefIndex) -> Self {
Self {
zome_index: 0.into(),
type_index,
}
}
}
impl From<LinkType> for ZomeLinkTypesKey {
fn from(type_index: LinkType) -> Self {
Self {
zome_index: 0.into(),
type_index,
}
}
}
#[doc(hidden)]
pub trait EnumLen {
const ENUM_LEN: u8;
}
#[doc(hidden)]
pub trait EnumVariantLen<const V: u8> {
const ENUM_VARIANT_START: u8;
const ENUM_VARIANT_INNER_LEN: u8;
const ENUM_VARIANT_LEN: u8 = Self::ENUM_VARIANT_START + Self::ENUM_VARIANT_INNER_LEN;
}
pub trait U8Index {
fn index(&self) -> usize;
}
impl U8Index for ZomeDependencyIndex {
fn index(&self) -> usize {
self.0 as usize
}
}
impl U8Index for EntryDefIndex {
fn index(&self) -> usize {
self.0 as usize
}
}
impl U8Index for LinkType {
fn index(&self) -> usize {
self.0 as usize
}
}
impl From<u8> for ZomeDependencyIndex {
fn from(v: u8) -> Self {
Self(v)
}
}
impl From<()> for ZomeEntryTypesKey {
fn from(_: ()) -> Self {
unimplemented!("Should not ever be used")
}
}