1use std::collections::{HashMap, HashSet};
2use std::io::{self, Error as IoError, ErrorKind as Kind};
3
4use serde::de;
5use serde::Deserialize;
6
7use crate::de::{Deserializer, SECTION_CTX};
8use crate::error::Result;
9use crate::parser::Watcher;
10use crate::tokenizer::Mode;
11
12pub fn from_str<T>(s: &str) -> Result<T>
17where
18 T: for<'de> Deserialize<'de>,
19{
20 Builder::new().from_str(s)
21}
22
23pub fn from_file<T>(name: impl Into<String>) -> io::Result<T>
28where
29 T: for<'de> Deserialize<'de>,
30{
31 Builder::new().from_file(name)
32}
33
34pub struct Builder {
36 mode: Mode,
37 aliases: HashMap<String, String>,
38 ignored: HashSet<String>,
39 watcher: Option<Watcher>,
40}
41
42impl Builder {
43 pub fn new() -> Builder {
45 Builder {
46 mode: Mode::Semicolon,
47 aliases: HashMap::new(),
48 ignored: HashSet::new(),
49 watcher: None,
50 }
51 }
52
53 pub fn mode(mut self, mode: Mode) -> Builder {
57 self.mode = mode;
58 self
59 }
60
61 pub fn alias<T>(mut self, alias: &str, section_name: &str) -> Builder {
67 let type_name = std::any::type_name::<T>().split(":").last().unwrap();
68 let type_dot_alias = format!("{}.{}", type_name, alias);
69 self.aliases
70 .insert(type_dot_alias, section_name.to_string());
71 self
72 }
73
74 pub fn ignore<T>(mut self, key: &str) -> Builder {
76 let type_name = std::any::type_name::<T>().split(":").last().unwrap();
77 let type_dot_alias = format!("{}.{}", type_name, key);
78 self.ignored.insert(type_dot_alias);
79 self
80 }
81
82 pub fn watcher(mut self, watcher: &Watcher) -> Builder {
84 self.watcher = Some(watcher.clone());
85 self
86 }
87
88 pub fn from_str<T>(self, text: &str) -> Result<T>
90 where
91 T: for<'de> Deserialize<'de>,
92 {
93 let mut deserializer =
94 Deserializer::from_str(text, self.mode, self.aliases, self.ignored, self.watcher);
95 T::deserialize(&mut deserializer)
96 }
97
98 pub fn from_file<T>(self, name: impl Into<String>) -> io::Result<T>
100 where
101 T: for<'de> Deserialize<'de>,
102 {
103 let mut deserializer =
104 Deserializer::from_file(name, self.mode, self.aliases, self.ignored, self.watcher)?;
105 T::deserialize(&mut deserializer)
106 .map_err(|e| IoError::new(Kind::Other, e))
107 }
108}
109
110pub trait ParserAccess {
114 fn value_name(&self) -> String {
123 SECTION_CTX.with(|ctx| ctx.borrow().subsection_name().to_string())
124 }
125
126 fn parser(&self) -> Parser {
129 Parser
130 }
131}
132
133impl<'de, T> ParserAccess for T where T: de::Deserializer<'de> {}
134
135pub struct Parser;
141impl ParserAccess for Parser {}
142
143#[cfg(test)]
144mod tests {
145 use super::*;
146 use serde::Deserialize;
147
148 fn init() {
149 let _ = env_logger::builder().is_test(true).try_init();
150 }
151
152 #[test]
153 fn test_struct() {
154 init();
155
156 #[derive(Deserialize, PartialEq, Debug)]
157 struct Main {
158 test: Test,
159 }
160
161 #[derive(Deserialize, PartialEq, Debug)]
162 #[serde(rename = "test")]
163 struct Test {
164 __label__: String,
165 int: u32,
166 seq: Vec<String>,
167 }
168
169 let j = r#"test foo {
170 int 1;
171 seq a,"b";
172 }"#;
173 let expected = Main {
174 test: Test {
175 __label__: "foo".to_owned(),
176 int: 1,
177 seq: vec!["a".to_owned(), "b".to_owned()],
178 },
179 };
180 assert_eq!(expected, from_str(j).unwrap());
181 }
182}