Mercurial > crates > nonstick
comparison libpam-sys/libpam-sys-impls/src/lib.rs @ 109:bb465393621f
Minor cleanup and reorg.
- Use those nice new macros we just implemented.
- Straighten out the macro file.
- Move the `BinaryPayload` into `structs.rs`, leaving helpers behind.
author | Paul Fisher <paul@pfish.zone> |
---|---|
date | Sat, 28 Jun 2025 02:49:35 -0400 |
parents | e97534be35e3 |
children | 2346fd501b7a |
comparison
equal
deleted
inserted
replaced
108:e97534be35e3 | 109:bb465393621f |
---|---|
10 /// meaningful internal implementation differences, like the way `pam_conv` | 10 /// meaningful internal implementation differences, like the way `pam_conv` |
11 /// is handled (see [the Linux-PAM man page for details][man7]). | 11 /// is handled (see [the Linux-PAM man page for details][man7]). |
12 /// | 12 /// |
13 /// ``` | 13 /// ``` |
14 /// # use libpam_sys_impls::cfg_pam_impl; | 14 /// # use libpam_sys_impls::cfg_pam_impl; |
15 /// #[cfg_pam_impl("illumos")] | 15 /// #[cfg_pam_impl("Illumos")] |
16 /// fn do_something() { /* illumos-only code */ } | 16 /// fn do_something() { /* illumos-only code */ } |
17 /// | 17 /// |
18 /// #[cfg_pam_impl(not("illumos"))] | 18 /// #[cfg_pam_impl(not("Illumos"))] |
19 /// fn do_something() { /* non-illumos code */ } | 19 /// fn do_something() { /* non-illumos code */ } |
20 /// | 20 /// |
21 /// #[cfg_pam_impl(any("linux-pam", "openpam"))] | 21 /// #[cfg_pam_impl(any("LinuxPam", "MinimalOpenPam"))] |
22 /// fn do_something_else() { /* Linux-PAM or OpenPAM */ } | 22 /// fn do_something_else() { /* Linux-PAM or minimal OpenPAM */ } |
23 /// | 23 /// |
24 /// #[cfg_pam_impl(not(any("illumos", "openpam")))] | 24 /// #[cfg_pam_impl(not(any("Illumos", "OpenPam")))] |
25 /// fn do_a_third_thing() { /* Neither Illumos nor OpenPAM */ } | 25 /// fn do_a_third_thing() { /* Neither Illumos nor OpenPAM */ } |
26 /// | 26 /// |
27 /// #[cfg_pam_impl(any())] | 27 /// #[cfg_pam_impl(any())] |
28 /// fn this_will_never_build() { /* why would you do this? */ } | 28 /// fn this_will_never_build() { /* why would you do this? */ } |
29 /// | |
30 /// #[cfg_pam_impl(not(any()))] | |
31 /// fn this_will_always_build() { /* this is technically legal */ } | |
29 /// ``` | 32 /// ``` |
30 /// | 33 /// |
31 /// [man7]: https://man7.org/linux/man-pages/man3/pam_conv.3.html | 34 /// [man7]: https://man7.org/linux/man-pages/man3/pam_conv.3.html |
32 #[proc_macro_attribute] | 35 #[proc_macro_attribute] |
33 pub fn cfg_pam_impl(attr: pm::TokenStream, item: pm::TokenStream) -> pm::TokenStream { | 36 pub fn cfg_pam_impl(attr: pm::TokenStream, item: pm::TokenStream) -> pm::TokenStream { |
34 eprintln!("Got TokenStream: {:?}", attr); | |
35 Predicate::parse(attr.into(), None) | 37 Predicate::parse(attr.into(), None) |
36 .map(|p| { | 38 .map(|p| { |
37 if p.matches(pam_impl_str()) { | 39 if p.matches(pam_impl_str()) { |
38 item | 40 item |
39 } else { | 41 } else { |
41 } | 43 } |
42 }) | 44 }) |
43 .unwrap_or_else(|e| syn::Error::from(e).into_compile_error().into()) | 45 .unwrap_or_else(|e| syn::Error::from(e).into_compile_error().into()) |
44 } | 46 } |
45 | 47 |
48 /// Outputs the `PamImpl` enum and `LIBPAMSYS_IMPL` constant. Private. | |
49 #[proc_macro] | |
50 pub fn pam_impl_enum(data: pm::TokenStream) -> pm::TokenStream { | |
51 if !data.is_empty() { | |
52 panic!("unexpected stuff in pam_impl_enum!()") | |
53 } | |
54 | |
55 let variant = format_ident!("{}", pam_impl_str()); | |
56 | |
57 quote!( | |
58 /// The PAM implementations supported by `libpam-sys`. | |
59 #[non_exhaustive] | |
60 #[derive(Clone, Copy, Debug, PartialEq)] | |
61 pub enum PamImpl { | |
62 /// [Linux-PAM] is provided by most Linux implementations. | |
63 /// | |
64 /// [Linux-PAM]: https://github.com/linux-pam/linux-pam | |
65 LinuxPam, | |
66 /// [OpenPAM] is used by most BSD distributions, including Mac OS X. | |
67 /// | |
68 /// [OpenPAM]: https://git.des.dev/OpenPAM/OpenPAM | |
69 OpenPam, | |
70 /// [Illumos PAM] is used on Illumos and Solaris systems. | |
71 /// | |
72 /// [Illumos PAM]: https://code.illumos.org/plugins/gitiles/illumos-gate/+/refs/heads/master/usr/src/lib/libpam | |
73 Illumos, | |
74 /// Only the functionality in [the PAM spec], | |
75 /// with OpenPAM/Illumos constants. | |
76 /// | |
77 /// [the PAM spec]: https://pubs.opengroup.org/onlinepubs/8329799/toc.htm | |
78 MinimalOpenPam, | |
79 } | |
80 | |
81 #[doc = concat!("This version of libpam-sys was built for **", stringify!(#variant), "**.")] | |
82 pub const LIBPAMSYS_IMPL: PamImpl = PamImpl::#variant; | |
83 ) | |
84 .into() | |
85 } | |
86 | |
87 /// The name of the PAM implementation. Used only in `libpam-sys`. Private. | |
88 #[proc_macro] | |
89 pub fn pam_impl_name(data: pm::TokenStream) -> pm::TokenStream { | |
90 if !data.is_empty() { | |
91 panic!("pam_impl_name! does not take any input") | |
92 } | |
93 pm::TokenTree::Literal(pm::Literal::string(pam_impl_str())).into() | |
94 } | |
95 | |
96 fn pam_impl_str() -> &'static str { | |
97 env!("LIBPAMSYS_IMPL") | |
98 } | |
99 | |
46 #[derive(Debug)] | 100 #[derive(Debug)] |
47 enum Error { | 101 enum Error { |
48 WithSpan(syn::Error), | 102 WithSpan(syn::Error), |
49 WithoutSpan(String), | 103 WithoutSpan(String), |
50 } | 104 } |
91 impl Predicate { | 145 impl Predicate { |
92 fn matches(&self, value: &str) -> bool { | 146 fn matches(&self, value: &str) -> bool { |
93 match self { | 147 match self { |
94 Self::Literal(literal) => value == literal, | 148 Self::Literal(literal) => value == literal, |
95 Self::Not(pred) => !pred.matches(value), | 149 Self::Not(pred) => !pred.matches(value), |
96 Self::Any(options) => { | 150 Self::Any(options) => options.iter().any(|s| s == value), |
97 options.iter().any(|s| s == value) | |
98 } | |
99 } | 151 } |
100 } | 152 } |
101 | 153 |
102 fn parse(stream: TokenStream, span: Option<Span>) -> Result<Self> { | 154 fn parse(stream: TokenStream, span: Option<Span>) -> Result<Self> { |
103 let mut iter = stream.into_iter(); | 155 let mut iter = stream.into_iter(); |
142 match iter.next() { | 194 match iter.next() { |
143 None => break, | 195 None => break, |
144 Some(TokenTree::Literal(lit)) => { | 196 Some(TokenTree::Literal(lit)) => { |
145 output.push(Self::string_lit(lit)?); | 197 output.push(Self::string_lit(lit)?); |
146 if !maybe_comma(iter.next())? { | 198 if !maybe_comma(iter.next())? { |
147 break | 199 break; |
148 } | 200 } |
149 }, | 201 } |
150 Some(other) => return unexpected(&other, "string literal"), | 202 Some(other) => return unexpected(&other, "string literal"), |
151 } | 203 } |
152 } | 204 } |
153 Ok(output) | 205 Ok(output) |
154 } | 206 } |
183 } | 235 } |
184 } | 236 } |
185 unexpected(&tree, "',' or ')'") | 237 unexpected(&tree, "',' or ')'") |
186 } | 238 } |
187 } | 239 } |
188 } | |
189 | |
190 /// A proc macro that outputs the PAM implementation macro and const. | |
191 #[proc_macro] | |
192 pub fn pam_impl_enum(data: pm::TokenStream) -> pm::TokenStream { | |
193 if !data.is_empty() { panic!("unexpected stuff in pam_impl_enum!()") } | |
194 | |
195 let variant = format_ident!("{}", pam_impl_str()); | |
196 | |
197 quote!( | |
198 /// The PAM implementations supported by `libpam-sys`. | |
199 #[non_exhaustive] | |
200 #[derive(Clone, Copy, Debug, PartialEq)] | |
201 pub enum PamImpl { | |
202 /// [Linux-PAM] is provided by most Linux implementations. | |
203 /// | |
204 /// [Linux-PAM]: https://github.com/linux-pam/linux-pam | |
205 LinuxPam, | |
206 /// [OpenPAM] is used by most BSD distributions, including Mac OS X. | |
207 /// | |
208 /// [OpenPAM]: https://git.des.dev/OpenPAM/OpenPAM | |
209 OpenPam, | |
210 /// [Illumos PAM] is used on Illumos and Solaris systems. | |
211 /// | |
212 /// [Illumos PAM]: https://code.illumos.org/plugins/gitiles/illumos-gate/+/refs/heads/master/usr/src/lib/libpam | |
213 Illumos, | |
214 /// Only the functionality in [the PAM spec], | |
215 /// with OpenPAM/Illumos constants. | |
216 /// | |
217 /// [the PAM spec]: https://pubs.opengroup.org/onlinepubs/8329799/toc.htm | |
218 MinimalOpenPam, | |
219 } | |
220 | |
221 #[doc = concat!("This version of libpam-sys was built for **", stringify!(#variant), "**.")] | |
222 pub const LIBPAMSYS_IMPL: PamImpl = PamImpl::#variant; | |
223 ).into() | |
224 } | |
225 | |
226 /// String literal of the name of the PAM implementation this was built for. | |
227 /// | |
228 /// The value is the string value of `libpamsys::PamImpl`. | |
229 #[proc_macro] | |
230 pub fn pam_impl_name(data: pm::TokenStream) -> pm::TokenStream { | |
231 if !data.is_empty() { | |
232 panic!("pam_impl_name! does not take any input") | |
233 } | |
234 pm::TokenTree::Literal(pm::Literal::string(pam_impl_str())).into() | |
235 } | |
236 | |
237 fn pam_impl_str() -> &'static str { | |
238 env!("LIBPAMSYS_IMPL") | |
239 } | 240 } |
240 | 241 |
241 #[cfg(test)] | 242 #[cfg(test)] |
242 mod tests { | 243 mod tests { |
243 use super::*; | 244 use super::*; |
294 [$(($e, quote!($($i)*))),*] | 295 [$(($e, quote!($($i)*))),*] |
295 } | 296 } |
296 } | 297 } |
297 let matching = cases![ | 298 let matching = cases![ |
298 ("Illumos", (any("Illumos", "OpenPam"))), | 299 ("Illumos", (any("Illumos", "OpenPam"))), |
300 ("OpenPam", (any("Illumos", "OpenPam"))), | |
299 ("LinuxPam", (not("OpenPam"))), | 301 ("LinuxPam", (not("OpenPam"))), |
302 ("MinimalOpenPam", (not("OpenPam"))), | |
300 ("Other", (not(any("This", "That")))), | 303 ("Other", (not(any("This", "That")))), |
301 ("OpenPam", (not(not("OpenPam")))), | 304 ("OpenPam", (not(not("OpenPam")))), |
302 ("Anything", (not(any()))), | 305 ("Anything", (not(any()))), |
303 ]; | 306 ]; |
304 for (good, tree) in matching { | 307 for (good, tree) in matching { |