aopt_core/value/
parser.rs1use std::ffi::OsStr;
2use std::ffi::OsString;
3use std::io::Stdin;
4use std::path::PathBuf;
5
6use crate::ctx::Ctx;
7use crate::Error;
8
9pub trait RawValParser
11where
12 Self: Sized,
13{
14 type Error: Into<Error>;
15
16 fn parse(raw: Option<&OsStr>, ctx: &Ctx) -> Result<Self, Self::Error>;
17}
18
19fn ok_or_else(raw: Option<&OsStr>) -> Result<&OsStr, Error> {
20 raw.ok_or_else(|| Error::sp_rawval(None, "unexcepted empty value"))
21}
22
23pub fn raw2str(raw: Option<&OsStr>) -> Result<&str, Error> {
25 ok_or_else(raw)?
26 .to_str()
27 .ok_or_else(|| Error::sp_rawval(raw, "can not convert OsStr to str"))
28}
29
30impl RawValParser for () {
31 type Error = Error;
32
33 fn parse(_: Option<&OsStr>, _: &Ctx) -> Result<Self, Self::Error> {
34 Ok(())
35 }
36}
37
38macro_rules! impl_raw_val_parser {
39 ($int:ty) => {
40 impl $crate::value::parser::RawValParser for $int {
41 type Error = Error;
42
43 fn parse(raw: Option<&OsStr>, ctx: &Ctx) -> Result<$int, Self::Error> {
44 let val = $crate::value::parser::raw2str(raw)?;
45 let uid = ctx.uid()?;
46
47 val.parse::<$int>().map_err(|e| {
48 $crate::err::Error::sp_rawval(
49 raw,
50 format!("not a valid value of type {}", stringify!($int)),
51 )
52 .with_uid(uid)
53 .cause_by(e.into())
54 })
55 }
56 }
57 };
58}
59
60impl_raw_val_parser!(i8);
61impl_raw_val_parser!(i16);
62impl_raw_val_parser!(i32);
63impl_raw_val_parser!(i64);
64impl_raw_val_parser!(i128);
65impl_raw_val_parser!(u8);
66impl_raw_val_parser!(u16);
67impl_raw_val_parser!(u32);
68impl_raw_val_parser!(u64);
69impl_raw_val_parser!(u128);
70impl_raw_val_parser!(f32);
71impl_raw_val_parser!(f64);
72impl_raw_val_parser!(isize);
73impl_raw_val_parser!(usize);
74
75impl RawValParser for String {
76 type Error = Error;
77
78 fn parse(raw: Option<&OsStr>, _ctx: &Ctx) -> Result<Self, Self::Error> {
79 Ok(raw2str(raw)?.to_string())
80 }
81}
82
83impl RawValParser for OsString {
84 type Error = Error;
85
86 fn parse(raw: Option<&OsStr>, ctx: &Ctx) -> Result<Self, Self::Error> {
87 let uid = ctx.uid()?;
88
89 Ok(ok_or_else(raw).map_err(|e| e.with_uid(uid))?.to_os_string())
90 }
91}
92
93impl RawValParser for bool {
94 type Error = Error;
95
96 fn parse(raw: Option<&OsStr>, ctx: &Ctx) -> Result<Self, Self::Error> {
97 let val = raw2str(raw)?;
98
99 match val {
100 crate::opt::BOOL_TRUE => Ok(true),
101 crate::opt::BOOL_FALSE => Ok(false),
102 _ => Err(Error::sp_rawval(raw, "except true or false").with_uid(ctx.uid()?)),
103 }
104 }
105}
106
107impl RawValParser for PathBuf {
108 type Error = Error;
109
110 fn parse(raw: Option<&OsStr>, _ctx: &Ctx) -> Result<Self, Self::Error> {
111 Ok(PathBuf::from(ok_or_else(raw)?))
112 }
113}
114
115impl RawValParser for Stdin {
116 type Error = Error;
117
118 fn parse(raw: Option<&OsStr>, ctx: &Ctx) -> Result<Self, Self::Error> {
119 const STDIN: &str = "-";
120
121 if ctx.name()?.map(|v| v.as_ref()) == Some(STDIN) {
122 Ok(std::io::stdin())
123 } else {
124 Err(Error::sp_rawval(raw, "except `-` for Stdin").with_uid(ctx.uid()?))
125 }
126 }
127}