reactive_graph_sys_binary/behaviour/component/
load_binary_data.rs1use std::fs::File;
2use std::io::Read;
3use std::path::Path;
4
5use base64::Engine;
6use base64::engine::general_purpose::STANDARD;
7use mime_guess::from_path;
8use reactive_graph_behaviour_model_api::behaviour_validator;
9use reactive_graph_behaviour_model_api::prelude::*;
10use reactive_graph_behaviour_model_impl::entity_behaviour;
11use reactive_graph_graph::prelude::*;
12use reactive_graph_reactive_model_impl::ReactiveEntity;
13use reactive_graph_runtime_model::ActionProperties::TRIGGER;
14use serde_json::Value;
15use serde_json::json;
16use uuid::Uuid;
17
18use reactive_graph_sys_binary_model::BinaryDataProperties::DATA_URL;
19use reactive_graph_sys_file_model::FileProperties::FILENAME;
20
21entity_behaviour!(
22 LoadBinaryData,
23 LoadBinaryDataFactory,
24 LoadBinaryDataFsm,
25 LoadBinaryDataBehaviourTransitions,
26 LoadBinaryDataValidator
27);
28
29behaviour_validator!(LoadBinaryDataValidator, Uuid, ReactiveEntity, TRIGGER.as_ref(), FILENAME.as_ref(), DATA_URL.as_ref());
30
31impl BehaviourInit<Uuid, ReactiveEntity> for LoadBinaryDataBehaviourTransitions {
32 fn init(&self) -> Result<(), BehaviourInitializationFailed> {
33 if self.reactive_instance.as_bool(TRIGGER).unwrap_or(false) {
34 if let Some(value) = self.reactive_instance.as_string(FILENAME).and_then(load_binary_data) {
35 self.reactive_instance.set(DATA_URL, value);
36 }
37 }
38 Ok(())
39 }
40}
41
42impl BehaviourConnect<Uuid, ReactiveEntity> for LoadBinaryDataBehaviourTransitions {
43 fn connect(&self) -> Result<(), BehaviourConnectFailed> {
44 let reactive_instance = self.reactive_instance.clone();
45 self.property_observers.observe_with_handle(TRIGGER.as_ref(), move |trigger: &Value| {
46 if !trigger.as_bool().unwrap_or(false) {
47 return;
49 }
50 if let Some(value) = reactive_instance.as_string(FILENAME).and_then(load_binary_data) {
51 reactive_instance.set(DATA_URL, value);
52 }
53 });
54 let reactive_instance = self.reactive_instance.clone();
55 self.property_observers.observe_with_handle(FILENAME.as_ref(), move |filename: &Value| {
56 if let Some(value) = filename.as_str().map(String::from).and_then(load_binary_data) {
57 reactive_instance.set(DATA_URL, value);
58 }
59 });
60 Ok(())
61 }
62}
63
64impl BehaviourShutdown<Uuid, ReactiveEntity> for LoadBinaryDataBehaviourTransitions {}
65impl BehaviourTransitions<Uuid, ReactiveEntity> for LoadBinaryDataBehaviourTransitions {}
66
67fn load_binary_data(filename: String) -> Option<Value> {
68 let filename = shellexpand::tilde(&filename);
69 let path = Path::new(filename.as_ref());
70 File::open(path).ok().and_then(|mut file| {
71 let mut buffer = Vec::new();
72 let _ = file.read_to_end(&mut buffer);
73 infer::get(&buffer)
74 .map(|kind| kind.mime_type().to_string())
75 .or_else(|| from_path(path).first().map(|x| x.to_string()))
76 .map(|mime_type| json!(format!("data:{};base64,{}", mime_type, STANDARD.encode(&buffer))))
77 })
78}