use super::Conductor;
use crate::core::ribosome::guest_callback::entry_defs::EntryDefsHostAccess;
use crate::core::ribosome::guest_callback::entry_defs::EntryDefsInvocation;
use crate::core::ribosome::guest_callback::entry_defs::EntryDefsResult;
use crate::core::ribosome::real_ribosome::RealRibosome;
use crate::core::ribosome::RibosomeT;
use error::EntryDefStoreError;
use error::EntryDefStoreResult;
use holo_hash::*;
use holochain_types::prelude::*;
use std::collections::HashMap;
pub mod error;
pub(crate) async fn get_entry_def(
entry_def_index: EntryDefIndex,
zome: IntegrityZomeDef,
dna_hash: &DnaHash,
conductor_handle: &Conductor,
) -> EntryDefStoreResult<Option<EntryDef>> {
let key = EntryDefBufferKey::new(zome, entry_def_index);
let entry_def = conductor_handle.get_entry_def(&key);
let ribosome = conductor_handle
.get_any_ribosome_for_dna_hash(dna_hash)
.map_err(|_| EntryDefStoreError::DnaFileMissing(dna_hash.clone()))?;
match &entry_def {
Some(_) => Ok(entry_def),
None => Ok(get_entry_defs(ribosome)
.await?
.into_iter()
.find(
|(
EntryDefBufferKey {
entry_def_position, ..
},
_,
)| *entry_def_position == entry_def_index,
)
.map(|(_, v)| v)),
}
}
#[cfg_attr(feature = "instrument", tracing::instrument(skip(ribosome)))]
pub(crate) async fn get_entry_defs(
ribosome: RealRibosome,
) -> EntryDefStoreResult<Vec<(EntryDefBufferKey, EntryDef)>> {
let invocation = EntryDefsInvocation;
let zomes = ribosome
.dna_def_hashed()
.integrity_zomes
.iter()
.cloned()
.enumerate()
.map(|(i, (zome_name, zome))| (zome_name, (ZomeIndex(i as u8), zome)))
.collect::<HashMap<_, _>>();
let result = ribosome
.run_entry_defs(EntryDefsHostAccess, invocation)
.await?;
match result {
EntryDefsResult::Defs(map) => {
map.into_iter()
.filter_map(|(zome_name, entry_defs)| {
zomes.get(&zome_name).map(|zome| (zome.clone(), entry_defs))
})
.flat_map(|((_id, zome), entry_defs)| {
entry_defs
.into_iter()
.enumerate()
.map(move |(local_index, entry_def)| {
let entry_def_position = u8::try_from(local_index)
.map_err(|_| EntryDefStoreError::EntryTypeMissing)?;
Ok((
EntryDefBufferKey {
zome: zome.clone(),
entry_def_position: entry_def_position.into(),
},
entry_def,
))
})
})
.collect()
}
EntryDefsResult::Err(zome_name, msg) => {
Err(EntryDefStoreError::CallbackFailed(zome_name, msg))
}
}
}
#[cfg(test)]
mod tests {
use super::EntryDefBufferKey;
use crate::conductor::Conductor;
use holo_hash::{fixt::AgentPubKeyFixturator, HasHash};
use holochain_state::prelude::test_db_dir;
use holochain_types::prelude::*;
use holochain_types::test_utils::fake_dna_zomes;
use holochain_wasm_test_utils::TestWasm;
#[tokio::test(flavor = "multi_thread")]
async fn test_store_entry_defs() {
holochain_trace::test_run();
let db_dir = test_db_dir();
let handle = Conductor::builder()
.with_data_root_path(db_dir.path().to_path_buf().into())
.test(&[])
.await
.unwrap();
let dna_file = fake_dna_zomes(
"",
vec![(TestWasm::EntryDefs.into(), TestWasm::EntryDefs.into())],
);
let post_def = EntryDef {
id: "post".into(),
visibility: EntryVisibility::Public,
required_validations: 5.into(),
..Default::default()
};
let comment_def = EntryDef {
id: "comment".into(),
visibility: EntryVisibility::Private,
required_validations: 5.into(),
..Default::default()
};
let dna_wasm = DnaWasmHashed::from_content(TestWasm::EntryDefs.into())
.await
.into_hash();
let post_def_key = EntryDefBufferKey {
zome: IntegrityZomeDef::from_hash(dna_wasm.clone()),
entry_def_position: 0.into(),
};
let comment_def_key = EntryDefBufferKey {
zome: IntegrityZomeDef::from_hash(dna_wasm),
entry_def_position: 1.into(),
};
let fake_agent = ::fixt::fixt!(AgentPubKey);
handle
.register_dna_file(
CellId::new(dna_file.dna_hash().clone(), fake_agent),
dna_file,
)
.await
.unwrap();
assert_eq!(handle.get_entry_def(&post_def_key), Some(post_def.clone()));
assert_eq!(
handle.get_entry_def(&comment_def_key),
Some(comment_def.clone())
);
std::mem::drop(handle);
let handle = Conductor::builder()
.with_data_root_path(db_dir.path().to_path_buf().into())
.test(&[])
.await
.unwrap();
assert_eq!(handle.get_entry_def(&post_def_key), Some(post_def));
assert_eq!(
handle.get_entry_def(&comment_def_key),
Some(comment_def.clone())
);
}
}