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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult};
use std::str::FromStr;
use std::convert::TryFrom;
pub struct TomlHelper;
impl TomlHelper {
pub fn decode_from_string<T>(v: &toml::Value) -> BuckyResult<T>
where
T: FromStr,
<T as FromStr>::Err: std::fmt::Display,
{
if !v.is_str() {
let msg = format!("invalid toml field, except string: {}", v);
warn!("{}", msg);
return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
}
let v = T::from_str(v.as_str().unwrap()).map_err(|e| {
let msg = format!(
"parse json string error: value={}, {}",
v.as_str().unwrap(),
e
);
warn!("{}", msg);
BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
})?;
Ok(v)
}
pub fn decode_from_boolean(v: &toml::Value) -> BuckyResult<bool> {
let v = v.as_bool().ok_or_else(|| {
let msg = format!("invalid toml field, except bool: {}", v);
warn!("{}", msg);
BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
})?;
Ok(v)
}
pub fn decode_string_field<T>(obj: &toml::value::Table, key: &str) -> BuckyResult<T>
where
T: FromStr,
<T as FromStr>::Err: std::fmt::Display,
{
let v = obj.get(key).ok_or_else(|| {
let msg = format!("field not found: {}", key);
warn!("{}", msg);
BuckyError::new(BuckyErrorCode::NotFound, msg)
})?;
Self::decode_from_string(v)
}
pub fn decode_option_string_field<T>(
obj: &toml::value::Table,
key: &str,
) -> BuckyResult<Option<T>>
where
T: FromStr,
<T as FromStr>::Err: std::fmt::Display,
{
match obj.get(key) {
Some(v) => {
let obj = Self::decode_from_string(v)?;
Ok(Some(obj))
}
None => Ok(None),
}
}
pub fn decode_to_int<T>(v: &toml::Value) -> BuckyResult<T>
where
T: FromStr + TryFrom<u64> + TryFrom<i64>,
<T as FromStr>::Err: std::fmt::Display,
<T as TryFrom<u64>>::Error: std::fmt::Display,
<T as TryFrom<i64>>::Error: std::fmt::Display,
{
if v.is_str() {
let v = T::from_str(v.as_str().unwrap()).map_err(|e| {
let msg = format!(
"parse toml string to int error: value={}, {}",
v.as_str().unwrap(),
e
);
warn!("{}", msg);
BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
})?;
Ok(v)
} else if v.is_integer() {
if v.is_integer() {
let v = T::try_from(v.as_integer().unwrap()).map_err(|e| {
let msg = format!(
"parse toml integer to int error: value={}, {}",
v.as_integer().unwrap(),
e
);
warn!("{}", msg);
BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
})?;
Ok(v)
} else {
let msg = format!(
"parse toml integer to int error: value={}",
v.as_integer().unwrap(),
);
warn!("{}", msg);
Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg))
}
} else {
let msg = format!("invalid toml field, except string or integer: {}", v);
warn!("{}", msg);
Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg))
}
}
pub fn extract_sub_node(mut root: toml::Value, path: &str) -> BuckyResult<toml::Value> {
let parts: Vec<&str> = path.split('.').collect();
for part in parts {
root = Self::extract_node(root, part)?;
}
Ok(root)
}
pub fn extract_node(root: toml::Value, name: &str) -> BuckyResult<toml::Value> {
match root {
toml::Value::Table(mut cfg) => match cfg.remove(name) {
Some(v) => Ok(v),
None => {
let msg = format!("sub node not found! name={}", name);
error!("{}", msg);
Err(BuckyError::new(BuckyErrorCode::NotFound, msg))
}
}
_ => {
let msg = format!(
"node is not table! config={}", toml::to_string(&root).unwrap()
);
error!("{}", msg);
Err(BuckyError::from((BuckyErrorCode::InvalidFormat, msg)))
}
}
}
}