1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
extern crate futures;
extern crate serde_json;
use action::{Action, ActionWrapper};
use context::Context;
use futures::{future, Async, Future};
use holochain_core_types::{
cas::content::AddressableContent, entry::Entry, entry_type::EntryType, error::HolochainError,
hash::HashString, validation::ValidationData,
};
use nucleus::ribosome::callback::{self, CallbackResult};
use snowflake;
use std::{sync::Arc, thread};
pub fn validate_entry(
entry_type: EntryType,
entry: Entry,
validation_data: ValidationData,
context: &Arc<Context>,
) -> Box<dyn Future<Item = HashString, Error = HolochainError>> {
let id = snowflake::ProcessUniqueId::new();
let address = entry.address();
match context
.state()
.unwrap()
.nucleus()
.dna()
.unwrap()
.get_zome_name_for_entry_type(entry_type.as_str())
{
None => {
return Box::new(future::err(HolochainError::ValidationFailed(format!(
"Unknown entry type: '{}'",
entry_type.as_str()
))));;
}
Some(_) => {
let id = id.clone();
let address = address.clone();
let entry = entry.clone();
let context = context.clone();
thread::spawn(move || {
let maybe_validation_result = callback::validate_entry::validate_entry(
entry.clone(),
entry_type.clone(),
validation_data.clone(),
context.clone(),
);
let result = match maybe_validation_result {
Ok(validation_result) => match validation_result {
CallbackResult::Fail(error_string) => Err(error_string),
CallbackResult::Pass => Ok(()),
CallbackResult::NotImplemented => Err(format!(
"Validation callback not implemented for {:?}",
entry_type.clone()
)),
_ => unreachable!(),
},
Err(error) => Err(error.to_string()),
};
context
.action_channel
.send(ActionWrapper::new(Action::ReturnValidationResult((
(id, address),
result,
))))
.expect("action channel to be open in reducer");
});
}
};
Box::new(ValidationFuture {
context: context.clone(),
key: (id, address),
})
}
pub struct ValidationFuture {
context: Arc<Context>,
key: (snowflake::ProcessUniqueId, HashString),
}
impl Future for ValidationFuture {
type Item = HashString;
type Error = HolochainError;
fn poll(
&mut self,
cx: &mut futures::task::Context<'_>,
) -> Result<Async<Self::Item>, Self::Error> {
cx.waker().wake();
if let Some(state) = self.context.state() {
match state.nucleus().validation_results.get(&self.key) {
Some(Ok(())) => Ok(futures::Async::Ready(self.key.1.clone())),
Some(Err(e)) => Err(HolochainError::ValidationFailed(e.clone())),
None => Ok(futures::Async::Pending),
}
} else {
Ok(futures::Async::Pending)
}
}
}