reactive_graph_sys_binary/behaviour/component/
save_binary_data.rs1use std::fs::OpenOptions;
2use std::io::Write;
3use std::path::Path;
4
5use base64::Engine;
6use base64::engine::general_purpose::STANDARD;
7use reactive_graph_behaviour_model_api::behaviour_validator;
8use reactive_graph_behaviour_model_api::prelude::*;
9use reactive_graph_behaviour_model_impl::entity_behaviour;
10use reactive_graph_graph::prelude::*;
11use reactive_graph_reactive_model_impl::ReactiveEntity;
12use reactive_graph_runtime_model::ActionProperties::TRIGGER;
13use serde_json::Value;
14use uuid::Uuid;
15
16use reactive_graph_sys_binary_model::BinaryDataProperties::DATA_URL;
17use reactive_graph_sys_file_model::FileProperties::FILENAME;
18
19entity_behaviour!(
20 SaveBinaryData,
21 SaveBinaryDataFactory,
22 SaveBinaryDataFsm,
23 SaveBinaryDataBehaviourTransitions,
24 SaveBinaryDataValidator
25);
26
27behaviour_validator!(SaveBinaryDataValidator, Uuid, ReactiveEntity, TRIGGER.as_ref(), FILENAME.as_ref(), DATA_URL.as_ref());
28
29impl BehaviourInit<Uuid, ReactiveEntity> for SaveBinaryDataBehaviourTransitions {}
30
31impl BehaviourConnect<Uuid, ReactiveEntity> for SaveBinaryDataBehaviourTransitions {
32 fn connect(&self) -> Result<(), BehaviourConnectFailed> {
33 let reactive_instance = self.reactive_instance.clone();
34 self.property_observers.observe_with_handle(TRIGGER.as_ref(), move |trigger: &Value| {
35 if !trigger.as_bool().unwrap_or(false) {
36 return;
37 }
38 if let Some(filename) = reactive_instance.as_string(FILENAME) {
39 let filename = shellexpand::tilde(&filename);
40 let path = Path::new(filename.as_ref());
41
42 if let Some(data_url) = reactive_instance.get(DATA_URL).and_then(|v| v.as_str().map(String::from)) {
43 let mut parts = data_url.splitn(2, ',');
46 let _part_data_url_prefix = parts.next();
47 let bytes = match parts.next() {
48 Some(part_base64_encoded_data) => STANDARD.decode(part_base64_encoded_data).ok(),
49 None => None,
50 };
51 if bytes.is_none() {
52 return;
53 }
54
55 if let Ok(mut file) = OpenOptions::new().write(true).create(true).truncate(true).open(path) {
57 let _success = file.write_all(bytes.unwrap().as_slice());
58 }
59 }
60 }
61 });
62 Ok(())
63 }
64}
65
66impl BehaviourShutdown<Uuid, ReactiveEntity> for SaveBinaryDataBehaviourTransitions {}
67impl BehaviourTransitions<Uuid, ReactiveEntity> for SaveBinaryDataBehaviourTransitions {}