1use crate::{Error, OptionValue, Options, ParseError, Source, SourceBuilder};
4use std::borrow::Cow;
5use std::collections::HashMap;
6
7impl From<Source> for SourceBuilder {
8 fn from(value: Source) -> Self {
9 Self {
10 source: Some(value.source().to_string()),
11 options: value.options().clone(),
12 resource: value.resource().to_string(),
13 ignore_errors: value.ignore_errors(),
14 resource_colon: value.resource_colon(),
15 }
16 }
17}
18
19impl TryFrom<&str> for SourceBuilder {
20 type Error = Error;
21
22 fn try_from(value: &str) -> Result<Self, Self::Error> {
23 Ok(Source::parse(value)?.into())
24 }
25}
26
27impl TryFrom<String> for SourceBuilder {
28 type Error = Error;
29
30 fn try_from(value: String) -> Result<Self, Self::Error> {
31 Self::try_from(value.as_str())
32 }
33}
34
35impl TryFrom<&String> for SourceBuilder {
36 type Error = Error;
37
38 fn try_from(value: &String) -> Result<Self, Self::Error> {
39 Self::try_from(value.as_str())
40 }
41}
42
43impl TryFrom<Cow<'_, str>> for SourceBuilder {
44 type Error = Error;
45
46 fn try_from(value: Cow<'_, str>) -> Result<Self, Self::Error> {
47 Self::try_from(value.as_ref())
48 }
49}
50
51impl From<bool> for OptionValue {
52 fn from(value: bool) -> Self {
53 Self::Bool(value)
54 }
55}
56
57impl From<i64> for OptionValue {
58 fn from(value: i64) -> Self {
59 Self::Integer(value)
60 }
61}
62
63impl From<i32> for OptionValue {
64 fn from(value: i32) -> Self {
65 Self::Integer(value as i64)
66 }
67}
68
69impl From<i16> for OptionValue {
70 fn from(value: i16) -> Self {
71 Self::Integer(value as i64)
72 }
73}
74
75impl From<i8> for OptionValue {
76 fn from(value: i8) -> Self {
77 Self::Integer(value as i64)
78 }
79}
80
81impl From<u64> for OptionValue {
82 fn from(value: u64) -> Self {
83 Self::Integer(value as i64)
84 }
85}
86
87impl From<u32> for OptionValue {
88 fn from(value: u32) -> Self {
89 Self::Integer(value as i64)
90 }
91}
92
93impl From<u16> for OptionValue {
94 fn from(value: u16) -> Self {
95 Self::Integer(value as i64)
96 }
97}
98
99impl From<u8> for OptionValue {
100 fn from(value: u8) -> Self {
101 Self::Integer(value as i64)
102 }
103}
104
105impl From<isize> for OptionValue {
106 fn from(value: isize) -> Self {
107 Self::Integer(value as i64)
108 }
109}
110
111impl From<usize> for OptionValue {
112 fn from(value: usize) -> Self {
113 Self::Integer(value as i64)
114 }
115}
116
117impl From<f64> for OptionValue {
118 fn from(value: f64) -> Self {
119 Self::Float(value)
120 }
121}
122
123impl From<f32> for OptionValue {
124 fn from(value: f32) -> Self {
125 Self::Float(value as f64)
126 }
127}
128
129impl From<&str> for OptionValue {
130 fn from(value: &str) -> Self {
131 Self::String(value.to_string())
132 }
133}
134
135impl From<String> for OptionValue {
136 fn from(value: String) -> Self {
137 Self::String(value)
138 }
139}
140
141impl From<&String> for OptionValue {
142 fn from(value: &String) -> Self {
143 Self::String(value.clone())
144 }
145}
146
147impl<T: Into<OptionValue>> From<Vec<T>> for OptionValue {
148 fn from(value: Vec<T>) -> Self {
149 Self::List(value.into_iter().map(Into::into).collect())
150 }
151}
152
153impl<T: Into<OptionValue> + Clone> From<&[T]> for OptionValue {
154 fn from(value: &[T]) -> Self {
155 Self::List(value.iter().cloned().map(Into::into).collect())
156 }
157}
158
159impl From<Options> for OptionValue {
160 fn from(value: Options) -> Self {
161 Self::Map(value)
162 }
163}
164
165impl<K: Into<String>, V: Into<OptionValue>> From<HashMap<K, V>> for OptionValue {
166 fn from(value: HashMap<K, V>) -> Self {
167 let mut options = Options::default();
168 for (key, value) in value {
169 options.insert(key, value);
170 }
171 Self::Map(options)
172 }
173}
174
175impl std::str::FromStr for Source {
176 type Err = ParseError;
177
178 fn from_str(value: &str) -> Result<Self, Self::Err> {
179 Self::parse(value)
180 }
181}
182
183impl TryFrom<&str> for Source {
184 type Error = ParseError;
185
186 fn try_from(value: &str) -> Result<Self, Self::Error> {
187 Self::parse(value)
188 }
189}
190
191impl TryFrom<String> for Source {
192 type Error = ParseError;
193
194 fn try_from(value: String) -> Result<Self, Self::Error> {
195 Self::parse(&value)
196 }
197}
198
199impl TryFrom<&String> for Source {
200 type Error = ParseError;
201
202 fn try_from(value: &String) -> Result<Self, Self::Error> {
203 Self::parse(value)
204 }
205}
206
207impl TryFrom<Cow<'_, str>> for Source {
208 type Error = ParseError;
209
210 fn try_from(value: Cow<'_, str>) -> Result<Self, Self::Error> {
211 Self::parse(&value)
212 }
213}
214
215#[cfg(test)]
216mod tests {
217 use super::*;
218 use std::convert::TryFrom;
219
220 #[test]
221 fn try_from_str() {
222 let source = Source::try_from("file:/tmp/x").unwrap();
223 assert_eq!(source.resource(), "/tmp/x");
224 }
225
226 #[test]
227 fn builder_try_from_str() {
228 let builder = SourceBuilder::try_from("env(prefix=APP_)").unwrap();
229 let source = builder.build().unwrap();
230 assert_eq!(source.source(), "env");
231 assert_eq!(
232 source.options().get("prefix"),
233 Some(&OptionValue::String("APP_".into()))
234 );
235 }
236
237 #[test]
238 fn builder_try_from_invalid_is_parse_error() {
239 let error = SourceBuilder::try_from("env(prefix=)").unwrap_err();
240 assert!(matches!(error, Error::Parse(ParseError::EmptyValue { .. })));
241 }
242}