1#![warn(missing_docs)]
2#![doc = include_str!("../README.md")]
3
4pub mod error;
5mod to_scalar;
6
7use std::{
8 borrow::Cow,
9 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
10 num::NonZero,
11};
12
13use error::AnyErr;
14use facet_core::{Facet, Opaque, VariantKind};
15use facet_reflect::{PokeEnumNoVariant, PokeStruct, PokeUninit, PokeValueUninit};
16use toml_edit::{DocumentMut, Item, TomlError};
17
18pub fn from_str<T: Facet>(toml: &str) -> Result<T, AnyErr> {
20 let (poke, _guard) = PokeUninit::alloc::<T>();
21 let opaque = from_str_opaque(poke, toml)?;
22 Ok(unsafe { opaque.read::<T>() })
23}
24
25fn from_str_opaque<'mem>(poke: PokeUninit<'mem>, toml: &str) -> Result<Opaque<'mem>, AnyErr> {
26 let docs: DocumentMut = toml.parse().map_err(|e| TomlError::to_string(&e))?;
27 deserialize_item(poke, docs.as_item())
28}
29
30fn deserialize_item<'mem>(poke: PokeUninit<'mem>, item: &Item) -> Result<Opaque<'mem>, AnyErr> {
31 match poke {
32 PokeUninit::Scalar(poke) => deserialize_as_scalar(poke, item),
33 PokeUninit::List(_) => todo!(),
34 PokeUninit::Map(_) => todo!(),
35 PokeUninit::Struct(poke) => deserialize_as_struct(poke, item),
36 PokeUninit::Enum(poke) => deserialize_as_enum(poke, item),
37 _ => todo!("unsupported poke type"),
38 }
39}
40
41fn deserialize_as_struct<'mem>(
42 mut poke: PokeStruct<'mem>,
43 item: &Item,
44) -> Result<Opaque<'mem>, AnyErr> {
45 if item.is_value() {
47 if poke.def().fields.len() > 1 {
49 return Err(
50 "Failed trying to parse a single value as a struct with multiple fields".into(),
51 );
52 }
53
54 return deserialize_item(
55 poke.field(0)
56 .map_err(|e| format!("Unit struct is missing value: {e}"))?,
57 item,
58 );
59 }
60
61 let table = item
63 .as_table_like()
64 .ok_or_else(|| format!("Expected table like structure, got {}", item.type_name()))?;
65
66 for (k, v) in table.iter() {
67 let (index, field_poke) = poke
68 .field_by_name(k)
69 .map_err(|e| format!("Field '{}' error: {}", k, e))?;
70 let _v = deserialize_item(field_poke, v)
71 .map_err(|e| format!("Error deserializing field '{}': {}", k, e))?;
72 unsafe {
73 poke.mark_initialized(index);
74 }
75 }
76
77 Ok(poke.build_in_place())
78}
79
80fn deserialize_as_enum<'mem>(
81 poke: PokeEnumNoVariant<'mem>,
82 item: &Item,
83) -> Result<Opaque<'mem>, AnyErr> {
84 if item.is_value() {
86 let value = item
87 .as_str()
88 .ok_or_else(|| format!("Expokected string, got: {}", item.type_name()))?;
89
90 let variant = poke
91 .variant_by_name(value)
92 .ok_or_else(|| format!("Enum does not have a variant named '{value}'"))?;
93
94 if variant.kind != VariantKind::Unit {
95 return Err(format!("variant '{value}' is not a unit variant").into());
96 }
97
98 Ok(poke
99 .set_variant_by_name(value)
100 .map_err(|err| err.to_string())?
101 .build_in_place())
102 } else {
103 todo!()
104 }
105}
106
107fn deserialize_as_scalar<'mem>(
108 poke: PokeValueUninit<'mem>,
109 item: &Item,
110) -> Result<Opaque<'mem>, AnyErr> {
111 let shape = poke.shape();
112
113 Ok(if shape.is_type::<String>() {
114 poke.put(to_scalar::string(item)?)
115 } else if shape.is_type::<Cow<'_, str>>() {
116 poke.put(Cow::Owned(to_scalar::string(item)?))
117 } else if shape.is_type::<bool>() {
118 poke.put(to_scalar::boolean(item)?)
119 } else if shape.is_type::<f64>() {
120 poke.put(to_scalar::number::<f64>(item)?)
121 } else if shape.is_type::<f32>() {
122 poke.put(to_scalar::number::<f32>(item)?)
123 } else if shape.is_type::<usize>() {
124 poke.put(to_scalar::number::<usize>(item)?)
125 } else if shape.is_type::<u128>() {
126 poke.put(to_scalar::number::<u128>(item)?)
127 } else if shape.is_type::<u64>() {
128 poke.put(to_scalar::number::<u64>(item)?)
129 } else if shape.is_type::<u32>() {
130 poke.put(to_scalar::number::<u32>(item)?)
131 } else if shape.is_type::<u16>() {
132 poke.put(to_scalar::number::<u16>(item)?)
133 } else if shape.is_type::<u8>() {
134 poke.put(to_scalar::number::<u8>(item)?)
135 } else if shape.is_type::<isize>() {
136 poke.put(to_scalar::number::<isize>(item)?)
137 } else if shape.is_type::<i128>() {
138 poke.put(to_scalar::number::<i128>(item)?)
139 } else if shape.is_type::<i64>() {
140 poke.put(to_scalar::number::<i64>(item)?)
141 } else if shape.is_type::<i32>() {
142 poke.put(to_scalar::number::<i32>(item)?)
143 } else if shape.is_type::<i16>() {
144 poke.put(to_scalar::number::<i16>(item)?)
145 } else if shape.is_type::<i8>() {
146 poke.put(to_scalar::number::<i8>(item)?)
147 } else if shape.is_type::<NonZero<usize>>() {
148 poke.put(
150 NonZero::new(to_scalar::number::<usize>(item)?)
151 .ok_or("Could not convert number to non-zero variant")?,
152 )
153 } else if shape.is_type::<NonZero<u128>>() {
154 poke.put(
155 NonZero::new(to_scalar::number::<u128>(item)?)
156 .ok_or("Could not convert number to non-zero variant")?,
157 )
158 } else if shape.is_type::<NonZero<u64>>() {
159 poke.put(
160 NonZero::new(to_scalar::number::<u64>(item)?)
161 .ok_or("Could not convert number to non-zero variant")?,
162 )
163 } else if shape.is_type::<NonZero<u32>>() {
164 poke.put(
165 NonZero::new(to_scalar::number::<u32>(item)?)
166 .ok_or("Could not convert number to non-zero variant")?,
167 )
168 } else if shape.is_type::<NonZero<u16>>() {
169 poke.put(
170 NonZero::new(to_scalar::number::<u16>(item)?)
171 .ok_or("Could not convert number to non-zero variant")?,
172 )
173 } else if shape.is_type::<NonZero<u8>>() {
174 poke.put(
175 NonZero::new(to_scalar::number::<u8>(item)?)
176 .ok_or("Could not convert number to non-zero variant")?,
177 )
178 } else if shape.is_type::<NonZero<isize>>() {
179 poke.put(
180 NonZero::new(to_scalar::number::<isize>(item)?)
181 .ok_or("Could not convert number to non-zero variant")?,
182 )
183 } else if shape.is_type::<NonZero<i128>>() {
184 poke.put(
185 NonZero::new(to_scalar::number::<i128>(item)?)
186 .ok_or("Could not convert number to non-zero variant")?,
187 )
188 } else if shape.is_type::<NonZero<i64>>() {
189 poke.put(
190 NonZero::new(to_scalar::number::<i64>(item)?)
191 .ok_or("Could not convert number to non-zero variant")?,
192 )
193 } else if shape.is_type::<NonZero<i32>>() {
194 poke.put(
195 NonZero::new(to_scalar::number::<i32>(item)?)
196 .ok_or("Could not convert number to non-zero variant")?,
197 )
198 } else if shape.is_type::<NonZero<i16>>() {
199 poke.put(
200 NonZero::new(to_scalar::number::<i16>(item)?)
201 .ok_or("Could not convert number to non-zero variant")?,
202 )
203 } else if shape.is_type::<NonZero<i8>>() {
204 poke.put(
205 NonZero::new(to_scalar::number::<i8>(item)?)
206 .ok_or("Could not convert number to non-zero variant")?,
207 )
208 } else if shape.is_type::<SocketAddr>() {
209 poke.put(to_scalar::from_str::<SocketAddr>(item, "socket address")?)
210 } else if shape.is_type::<IpAddr>() {
211 poke.put(to_scalar::from_str::<IpAddr>(item, "ip address")?)
212 } else if shape.is_type::<Ipv4Addr>() {
213 poke.put(to_scalar::from_str::<Ipv4Addr>(item, "ipv4 address")?)
214 } else if shape.is_type::<Ipv6Addr>() {
215 poke.put(to_scalar::from_str::<Ipv6Addr>(item, "ipv6 address")?)
216 } else {
217 return Err(format!("Unsupported scalar type: {}", poke.shape()).into());
218 })
219}