satex_core/component/
configurable.rs1use crate::component::Args;
2use crate::Error;
3use serde::de::DeserializeOwned;
4use serde_yaml::Value;
5use std::cmp::min;
6
7const COMMA: char = ',';
8
9const COLON: char = ':';
10
11const LF: char = '\n';
12
13const LINE: char = '-';
14
15const SPACE: char = ' ';
16
17pub trait Configurable: DeserializeOwned {
18 const FIELDS: &'static [&'static str];
22
23 const COMPANION: &'static str;
27
28 const SHORTCUT_MODE: ShortcutMode;
32
33 fn with_args(args: Args) -> Result<Self, Error> {
37 match args {
38 Args::Full(value) => serde_yaml::from_value((*value).clone()).map_err(Error::new),
39 Args::Shortcut(None) => serde_yaml::from_value(Value::default()).map_err(Error::new),
40 Args::Shortcut(Some(value)) => {
41 let mut builder = String::default();
42 let fields = Self::FIELDS;
43 let shortcut_mode = Self::SHORTCUT_MODE;
44 let companion = Self::COMPANION;
45 match shortcut_mode {
46 ShortcutMode::Object => {
47 let values = value.split(COMMA).map(|value| value.trim());
48 let size = min(fields.len(), values.clone().count());
49 fields
50 .iter()
51 .take(size)
52 .zip(values.take(size))
53 .for_each(|(k, v)| {
54 append_k_v(&mut builder, k, v);
55 });
56 }
57 ShortcutMode::Sequence => {
58 if fields.len() != 1 {
59 return Err(Error::new(format!(
60 "[{}] configure with shortcut mode `Sequence` must have exactly 1 field",
61 companion
62 )));
63 }
64 let field = fields[0];
65 append_k_seq(&mut builder, field, value);
66 }
67 ShortcutMode::TailingSequence => {
68 if fields.len() != 2 {
69 return Err(Error::new(format!(
70 "[{}] configure with shortcut mode [TailingSequence] must have exactly 2 fields",
71 companion
72 )));
73 }
74 let k1 = fields[0];
75 let k2 = fields[1];
76 match value.rsplit_once(COMMA) {
77 Some((v1, v2)) => {
78 append_k_v(&mut builder, k1, v1);
79 append_k_seq(&mut builder, k2, v2);
80 }
81 None => {
82 return Err(Error::new(format!(
83 "[{}] configure with shortcut mode [TailingSequence] value must contains `,`",
84 companion
85 )));
86 }
87 }
88 }
89 ShortcutMode::Unsupported => {
90 return Err(Error::new(format!(
91 "[{}] configure unsupported shortcut",
92 companion
93 )));
94 }
95 };
96 serde_yaml::from_str(&builder).map_err(Error::new)
97 }
98 }
99 }
100}
101
102#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
106pub enum ShortcutMode {
107 Object,
108 Sequence,
109 TailingSequence,
110 Unsupported,
111}
112
113fn append_k_v(builder: &mut String, key: &str, value: &str) {
114 builder.push_str(key);
115 builder.push(COLON);
116 builder.push(SPACE);
117 builder.push_str(value);
118 builder.push(LF);
119}
120
121fn append_k_seq(builder: &mut String, key: &str, value: &str) {
122 builder.push_str(key);
123 builder.push(COLON);
124 builder.push(LF);
125 value.split(COMMA).for_each(|item| {
126 builder.push(LINE);
127 builder.push(SPACE);
128 builder.push_str(item.trim());
129 builder.push(LF);
130 });
131}