pedant_types/capability.rs
1use std::fmt;
2use std::str::FromStr;
3
4use serde::{Deserialize, Serialize};
5
6use crate::ParseCapabilityError;
7
8/// Define a Capability variant ↔ snake_case string mapping in one place.
9///
10/// Generates `Display` and `FromStr` from the same table so the two
11/// cannot drift. Serde uses `rename_all = "snake_case"` independently
12/// but produces identical strings for the same variants.
13macro_rules! capability_variants {
14 ($($(#[$meta:meta])* $variant:ident => $snake:literal),+ $(,)?) => {
15 /// A runtime or compile-time capability that a crate may exercise.
16 #[derive(Serialize, Deserialize, Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
17 #[serde(rename_all = "snake_case")]
18 pub enum Capability {
19 $($(#[$meta])* $variant,)+
20 }
21
22 impl fmt::Display for Capability {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 let s = match self {
25 $(Self::$variant => $snake,)+
26 };
27 f.write_str(s)
28 }
29 }
30
31 impl FromStr for Capability {
32 type Err = ParseCapabilityError;
33
34 fn from_str(s: &str) -> Result<Self, Self::Err> {
35 match s {
36 $($snake => Ok(Self::$variant),)+
37 _ => Err(ParseCapabilityError::new(s)),
38 }
39 }
40 }
41 };
42}
43
44capability_variants! {
45 /// TCP, UDP, HTTP, WebSocket, or DNS.
46 Network => "network",
47 /// Reading files or walking directories.
48 FileRead => "file_read",
49 /// Creating, writing, or deleting files and directories.
50 FileWrite => "file_write",
51 /// Spawning child processes.
52 ProcessExec => "process_exec",
53 /// Reading environment variables.
54 EnvAccess => "env_access",
55 /// `unsafe` blocks, `unsafe fn`, or `unsafe impl`.
56 UnsafeCode => "unsafe_code",
57 /// Foreign function interface calls or `extern` blocks.
58 Ffi => "ffi",
59 /// Encryption, hashing, signing, or embedded key material.
60 Crypto => "crypto",
61 /// `SystemTime`, `Instant`, or third-party clock access.
62 SystemTime => "system_time",
63 /// Proc macro definition (code execution at compile time).
64 ProcMacro => "proc_macro",
65}