cyfs_util/util/
toml_helper.rs1use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult};
2use std::str::FromStr;
3use std::convert::TryFrom;
4
5
6pub struct TomlHelper;
7impl TomlHelper {
8 pub fn decode_from_string<T>(v: &toml::Value) -> BuckyResult<T>
9 where
10 T: FromStr,
11 <T as FromStr>::Err: std::fmt::Display,
12 {
13 if !v.is_str() {
14 let msg = format!("invalid toml field, except string: {}", v);
15 warn!("{}", msg);
16
17 return Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg));
18 }
19
20 let v = T::from_str(v.as_str().unwrap()).map_err(|e| {
21 let msg = format!(
22 "parse toml string error: value={}, {}",
23 v.as_str().unwrap(),
24 e
25 );
26 warn!("{}", msg);
27
28 BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
29 })?;
30
31 Ok(v)
32 }
33
34 pub fn decode_from_boolean(v: &toml::Value) -> BuckyResult<bool> {
35 let v = v.as_bool().ok_or_else(|| {
36 let msg = format!("invalid toml field, except bool: {}", v);
37 warn!("{}", msg);
38
39 BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
40 })?;
41
42 Ok(v)
43 }
44
45 pub fn decode_string_field<T>(obj: &toml::value::Table, key: &str) -> BuckyResult<T>
46 where
47 T: FromStr,
48 <T as FromStr>::Err: std::fmt::Display,
49 {
50 let v = obj.get(key).ok_or_else(|| {
51 let msg = format!("field not found: {}", key);
52 warn!("{}", msg);
53
54 BuckyError::new(BuckyErrorCode::NotFound, msg)
55 })?;
56
57 Self::decode_from_string(v)
58 }
59
60 pub fn decode_option_string_field<T>(
61 obj: &toml::value::Table,
62 key: &str,
63 ) -> BuckyResult<Option<T>>
64 where
65 T: FromStr,
66 <T as FromStr>::Err: std::fmt::Display,
67 {
68 match obj.get(key) {
69 Some(v) => {
70 let obj = Self::decode_from_string(v)?;
71 Ok(Some(obj))
72 }
73 None => Ok(None),
74 }
75 }
76
77 pub fn decode_to_int<T>(v: &toml::Value) -> BuckyResult<T>
78 where
79 T: FromStr + TryFrom<u64> + TryFrom<i64>,
80 <T as FromStr>::Err: std::fmt::Display,
81 <T as TryFrom<u64>>::Error: std::fmt::Display,
82 <T as TryFrom<i64>>::Error: std::fmt::Display,
83 {
84 if v.is_str() {
85 let v = T::from_str(v.as_str().unwrap()).map_err(|e| {
86 let msg = format!(
87 "parse toml string to int error: value={}, {}",
88 v.as_str().unwrap(),
89 e
90 );
91 warn!("{}", msg);
92 BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
93 })?;
94
95 Ok(v)
96 } else if v.is_integer() {
97 if v.is_integer() {
98 let v = T::try_from(v.as_integer().unwrap()).map_err(|e| {
99 let msg = format!(
100 "parse toml integer to int error: value={}, {}",
101 v.as_integer().unwrap(),
102 e
103 );
104 warn!("{}", msg);
105 BuckyError::new(BuckyErrorCode::InvalidFormat, msg)
106 })?;
107 Ok(v)
108 } else {
109 let msg = format!(
110 "parse toml integer to int error: value={}",
111 v.as_integer().unwrap(),
112 );
113 warn!("{}", msg);
114 Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg))
115 }
116 } else {
117 let msg = format!("invalid toml field, except string or integer: {}", v);
118 warn!("{}", msg);
119
120 Err(BuckyError::new(BuckyErrorCode::InvalidFormat, msg))
121 }
122 }
123
124
125 pub fn extract_sub_node(mut root: toml::Value, path: &str) -> BuckyResult<toml::Value> {
126 let parts: Vec<&str> = path.split('.').collect();
127
128 for part in parts {
129 root = Self::extract_node(root, part)?;
130 }
131
132 Ok(root)
133 }
134
135 pub fn extract_node(root: toml::Value, name: &str) -> BuckyResult<toml::Value> {
136 match root {
137 toml::Value::Table(mut cfg) => match cfg.remove(name) {
138 Some(v) => Ok(v),
139 None => {
140 let msg = format!("sub node not found! name={}", name);
141 error!("{}", msg);
142 Err(BuckyError::new(BuckyErrorCode::NotFound, msg))
143 }
144 }
145
146 _ => {
147 let msg = format!(
148 "node is not table! config={}", toml::to_string(&root).unwrap()
149 );
150 error!("{}", msg);
151 Err(BuckyError::from((BuckyErrorCode::InvalidFormat, msg)))
152 }
153 }
154 }
155}