1#![warn(missing_docs)]
2#![warn(clippy::std_instead_of_core)]
3#![warn(clippy::std_instead_of_alloc)]
4#![forbid(unsafe_code)]
5#![doc = include_str!("../README.md")]
6
7use facet_core::{Def, Facet, FieldAttribute};
8use facet_reflect::{ReflectError, Wip};
9
10fn parse_field<'mem>(wip: Wip<'mem>, value: &str) -> Result<Wip<'mem>, ReflectError> {
11 let shape = wip.shape();
12 match shape.def {
13 Def::Scalar(_) => {
14 if shape.is_type::<String>() {
15 wip.put(value.to_string())
16 } else if shape.is_type::<bool>() {
17 log::trace!("Boolean field detected, setting to true");
18 wip.put(value.to_lowercase() == "true")
19 } else {
20 wip.parse(value)
21 }
22 }
23 _def => {
24 return Err(ReflectError::OperationFailed {
25 shape,
26 operation: "parsing field",
27 });
28 }
29 }?
30 .pop()
31}
32
33pub fn from_slice<T: Facet>(s: &[&str]) -> T {
35 log::trace!("Entering from_slice function");
36 let mut s = s;
37 let mut wip = Wip::alloc::<T>();
38 log::trace!("Allocated Poke for type T");
39
40 while let Some(token) = s.first() {
41 log::trace!("Processing token: {}", token);
42 s = &s[1..];
43
44 if let Some(key) = token.strip_prefix("--") {
45 log::trace!("Found named argument: {}", key);
46 let field_index = match wip.field_index(key) {
47 Some(index) => index,
48 None => panic!("Unknown argument: {}", key),
49 };
50 let field = wip.field(field_index).unwrap();
51
52 if field.shape().is_type::<bool>() {
53 wip = parse_field(field, "true").unwrap();
54 } else {
55 let value = s.first().expect("expected value after argument");
56 log::trace!("Field value: {}", value);
57 s = &s[1..];
58 wip = parse_field(field, value).unwrap();
59 }
60 } else {
61 log::trace!("Encountered positional argument: {}", token);
62 let Def::Struct(sd) = wip.shape().def else {
63 panic!("Expected struct definition");
64 };
65
66 for (field_index, f) in sd.fields.iter().enumerate() {
67 if f.attributes
68 .iter()
69 .any(|a| matches!(a, FieldAttribute::Arbitrary(a) if a.contains("positional")))
70 {
71 let field = wip.field(field_index).unwrap();
72 wip = parse_field(field, token).unwrap();
73 break;
74 }
75 }
76 }
77 }
78 wip.build().unwrap().materialize().unwrap()
79}