1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3use std::{collections::HashMap, ops::Index};
4
5#[derive(Serialize, Deserialize, Default, Debug, Clone)]
6pub struct Example {
7 pub data: HashMap<String, Value>,
8 pub input_keys: Vec<String>,
9 pub output_keys: Vec<String>,
10}
11
12impl Example {
13 pub fn new(
14 data: HashMap<String, Value>,
15 input_keys: Vec<String>,
16 output_keys: Vec<String>,
17 ) -> Self {
18 let output_keys = if !output_keys.is_empty() {
19 output_keys
20 } else if !input_keys.is_empty() {
21 data.keys()
22 .filter(|key| !input_keys.contains(key))
23 .cloned()
24 .collect()
25 } else {
26 vec![]
27 };
28
29 Self {
30 data,
31 input_keys,
32 output_keys,
33 }
34 }
35
36 pub fn get(&self, key: &str, default: Option<&str>) -> Value {
37 self.data
38 .get(key)
39 .unwrap_or(&default.unwrap_or_default().to_string().into())
40 .clone()
41 }
42
43 pub fn keys(&self) -> Vec<String> {
44 self.data.keys().cloned().collect()
45 }
46
47 pub fn values(&self) -> Vec<Value> {
48 self.data.values().cloned().collect()
49 }
50
51 pub fn set_input_keys(&mut self, keys: Vec<String>) {
52 self.input_keys = keys;
53
54 self.output_keys = self
55 .data
56 .keys()
57 .filter(|key| !self.input_keys.contains(key))
58 .cloned()
59 .collect();
60 }
61
62 pub fn with_input_keys(&self, keys: Vec<String>) -> Self {
63 let output_keys = self
64 .data
65 .keys()
66 .filter(|key| !keys.contains(key))
67 .cloned()
68 .collect();
69
70 Self {
71 data: self.data.clone(),
72 input_keys: keys,
73 output_keys,
74 }
75 }
76
77 pub fn without(&self, keys: Vec<String>) -> Self {
78 Self {
79 data: self
80 .data
81 .iter()
82 .filter(|(key, _)| !keys.contains(key))
83 .map(|(k, v)| (k.clone(), v.clone()))
84 .collect(),
85 input_keys: self
86 .input_keys
87 .iter()
88 .filter(|key| !keys.contains(key))
89 .cloned()
90 .collect(),
91 output_keys: self
92 .output_keys
93 .iter()
94 .filter(|key| !keys.contains(key))
95 .cloned()
96 .collect(),
97 }
98 }
99}
100
101impl IntoIterator for Example {
102 type Item = (String, Value);
103 type IntoIter = std::collections::hash_map::IntoIter<String, Value>;
104
105 fn into_iter(self) -> Self::IntoIter {
106 self.data.into_iter()
107 }
108}
109
110impl Index<String> for Example {
111 type Output = Value;
112
113 fn index(&self, index: String) -> &Self::Output {
114 &self.data[&index]
115 }
116}