Skip to main content

rnp/
strconv.rs

1//! `FromStr` and `Display` for the crate's model enums.
2//!
3//! Each enum's `as_str()` returns the C-side string; the impls here
4//! provide the reverse mapping plus the standard Rust string-conversion
5//! traits. This unlocks config-file parsers, CLI arg libraries, and
6//! serde (via `#[serde(with = "...")]` patterns).
7//!
8//! Adding a new model enum: implement `as_str()` on it, then add a
9//! `from_str` match arm + blanket `FromStr`/`Display` impls. The trait
10//! is the same pattern for every enum — could be macro-generated, but
11//! the manual form is clearer and lets each enum document its variants.
12
13use crate::error::{Error, unknown_variant};
14use crate::{
15    Algorithm, ArmorType, Cipher, Compression, Curve, FeatureType, Hash, KeyUsage,
16    encrypt::AeadType,
17};
18use std::str::FromStr;
19
20// Helper: build an UnknownVariant error.
21fn unknown(kind: &'static str, value: &str) -> Error {
22    unknown_variant(kind, value)
23}
24
25// -----------------------------------------------------------------------
26// Algorithm
27// -----------------------------------------------------------------------
28
29impl std::fmt::Display for Algorithm {
30    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31        f.write_str(self.as_str())
32    }
33}
34
35impl FromStr for Algorithm {
36    type Err = Error;
37    fn from_str(s: &str) -> Result<Self, Self::Err> {
38        match s.to_ascii_uppercase().as_str() {
39            "RSA" => Ok(Algorithm::Rsa),
40            "ELGAMAL" => Ok(Algorithm::ElGamal),
41            "DSA" => Ok(Algorithm::Dsa),
42            "ECDH" => Ok(Algorithm::Ecdh),
43            "ECDSA" => Ok(Algorithm::Ecdsa),
44            "EDDSA" => Ok(Algorithm::Eddsa),
45            "SM2" => Ok(Algorithm::Sm2),
46            _ => Err(unknown("algorithm", s)),
47        }
48    }
49}
50
51// -----------------------------------------------------------------------
52// Curve
53// -----------------------------------------------------------------------
54
55impl std::fmt::Display for Curve {
56    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
57        f.write_str(self.as_str())
58    }
59}
60
61impl FromStr for Curve {
62    type Err = Error;
63    fn from_str(s: &str) -> Result<Self, Self::Err> {
64        match s {
65            "NIST P-256" => Ok(Curve::P256),
66            "NIST P-384" => Ok(Curve::P384),
67            "NIST P-521" => Ok(Curve::P521),
68            "Ed25519" => Ok(Curve::Ed25519),
69            "Curve25519" => Ok(Curve::Curve25519),
70            "brainpoolP256r1" => Ok(Curve::Bp256),
71            "brainpoolP384r1" => Ok(Curve::Bp384),
72            "brainpoolP512r1" => Ok(Curve::Bp512),
73            "secp256k1" => Ok(Curve::Secp256k1),
74            "SM2 P-256" => Ok(Curve::Sm2P256),
75            _ => Err(unknown("curve", s)),
76        }
77    }
78}
79
80// -----------------------------------------------------------------------
81// Hash
82// -----------------------------------------------------------------------
83
84impl std::fmt::Display for Hash {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        f.write_str(self.as_str())
87    }
88}
89
90impl FromStr for Hash {
91    type Err = Error;
92    fn from_str(s: &str) -> Result<Self, Self::Err> {
93        match s.to_ascii_uppercase().as_str() {
94            "SHA1" => Ok(Hash::Sha1),
95            "SHA224" => Ok(Hash::Sha224),
96            "SHA256" => Ok(Hash::Sha256),
97            "SHA384" => Ok(Hash::Sha384),
98            "SHA512" => Ok(Hash::Sha512),
99            "SHA3-256" => Ok(Hash::Sha3_256),
100            "SHA3-512" => Ok(Hash::Sha3_512),
101            "MD5" => Ok(Hash::Md5),
102            "RIPEMD160" => Ok(Hash::Ripemd160),
103            "SM3" => Ok(Hash::Sm3),
104            _ => Err(unknown("hash", s)),
105        }
106    }
107}
108
109// -----------------------------------------------------------------------
110// Cipher
111// -----------------------------------------------------------------------
112
113impl std::fmt::Display for Cipher {
114    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
115        f.write_str(self.as_str())
116    }
117}
118
119impl FromStr for Cipher {
120    type Err = Error;
121    fn from_str(s: &str) -> Result<Self, Self::Err> {
122        match s.to_ascii_uppercase().as_str() {
123            "IDEA" => Ok(Cipher::Idea),
124            "TRIPLEDES" => Ok(Cipher::Tripledes),
125            "CAST5" => Ok(Cipher::Cast5),
126            "BLOWFISH" => Ok(Cipher::Blowfish),
127            "AES128" => Ok(Cipher::Aes128),
128            "AES192" => Ok(Cipher::Aes192),
129            "AES256" => Ok(Cipher::Aes256),
130            "TWOFISH" => Ok(Cipher::Twofish),
131            "CAMELLIA128" => Ok(Cipher::Camellia128),
132            "CAMELLIA192" => Ok(Cipher::Camellia192),
133            "CAMELLIA256" => Ok(Cipher::Camellia256),
134            "SM4" => Ok(Cipher::Sm4),
135            _ => Err(unknown("cipher", s)),
136        }
137    }
138}
139
140// -----------------------------------------------------------------------
141// Compression
142// -----------------------------------------------------------------------
143
144impl std::fmt::Display for Compression {
145    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
146        f.write_str(self.as_str())
147    }
148}
149
150impl FromStr for Compression {
151    type Err = Error;
152    fn from_str(s: &str) -> Result<Self, Self::Err> {
153        match s.to_ascii_uppercase().as_str() {
154            "ZIP" => Ok(Compression::Zip),
155            "ZLIB" => Ok(Compression::Zlib),
156            "BZIP2" => Ok(Compression::Bzip2),
157            _ => Err(unknown("compression", s)),
158        }
159    }
160}
161
162// -----------------------------------------------------------------------
163// KeyUsage
164// -----------------------------------------------------------------------
165
166impl std::fmt::Display for KeyUsage {
167    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168        f.write_str(self.as_str())
169    }
170}
171
172impl FromStr for KeyUsage {
173    type Err = Error;
174    fn from_str(s: &str) -> Result<Self, Self::Err> {
175        match s {
176            "certify" => Ok(KeyUsage::Certify),
177            "sign" => Ok(KeyUsage::Sign),
178            "encrypt" => Ok(KeyUsage::EncryptComms),
179            _ => Err(unknown("key usage", s)),
180        }
181    }
182}
183
184// -----------------------------------------------------------------------
185// AeadType
186// -----------------------------------------------------------------------
187
188impl std::fmt::Display for AeadType {
189    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
190        f.write_str(self.as_str())
191    }
192}
193
194impl FromStr for AeadType {
195    type Err = Error;
196    fn from_str(s: &str) -> Result<Self, Self::Err> {
197        match s.to_ascii_uppercase().as_str() {
198            "OCB" => Ok(AeadType::Ocb),
199            "EAX" => Ok(AeadType::Eax),
200            "GCM" => Ok(AeadType::Gcm),
201            _ => Err(unknown("aead", s)),
202        }
203    }
204}
205
206// -----------------------------------------------------------------------
207// ArmorType
208// -----------------------------------------------------------------------
209
210impl std::fmt::Display for ArmorType {
211    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212        f.write_str(self.as_str())
213    }
214}
215
216impl FromStr for ArmorType {
217    type Err = Error;
218    fn from_str(s: &str) -> Result<Self, Self::Err> {
219        match s {
220            "message" => Ok(ArmorType::Message),
221            "public key" => Ok(ArmorType::PublicKey),
222            "secret key" => Ok(ArmorType::SecretKey),
223            "signature" => Ok(ArmorType::Signature),
224            "cleartext signed message" => Ok(ArmorType::Cleartext),
225            _ => Err(unknown("armor type", s)),
226        }
227    }
228}
229
230// -----------------------------------------------------------------------
231// FeatureType
232// -----------------------------------------------------------------------
233
234impl std::fmt::Display for FeatureType {
235    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
236        f.write_str(self.as_str())
237    }
238}
239
240impl FromStr for FeatureType {
241    type Err = Error;
242    fn from_str(s: &str) -> Result<Self, Self::Err> {
243        // The RNP_FEATURE_* constants are &[u8; N] with a trailing NUL.
244        // Strip the NUL before comparing.
245        let strip_nul = |b: &'static [u8]| -> &'static str {
246            let end = b.iter().position(|&x| x == 0).unwrap_or(b.len());
247            std::str::from_utf8(&b[..end]).expect("RNP_FEATURE_* is ASCII")
248        };
249        let symm = strip_nul(crate::ffi::RNP_FEATURE_SYMM_ALG);
250        let aead = strip_nul(crate::ffi::RNP_FEATURE_AEAD_ALG);
251        let prot = strip_nul(crate::ffi::RNP_FEATURE_PROT_MODE);
252        let pk = strip_nul(crate::ffi::RNP_FEATURE_PK_ALG);
253        let hash = strip_nul(crate::ffi::RNP_FEATURE_HASH_ALG);
254        let comp = strip_nul(crate::ffi::RNP_FEATURE_COMP_ALG);
255        let curve = strip_nul(crate::ffi::RNP_FEATURE_CURVE);
256        match s {
257            x if x == symm => Ok(FeatureType::SymmetricAlgorithm),
258            x if x == aead => Ok(FeatureType::AeadAlgorithm),
259            x if x == prot => Ok(FeatureType::ProtectionMode),
260            x if x == pk => Ok(FeatureType::PublicKeyAlgorithm),
261            x if x == hash => Ok(FeatureType::HashAlgorithm),
262            x if x == comp => Ok(FeatureType::CompressionAlgorithm),
263            x if x == curve => Ok(FeatureType::Curve),
264            _ => Err(unknown("feature type", s)),
265        }
266    }
267}
268
269// -----------------------------------------------------------------------
270// KeyringFormat (in context.rs)
271// -----------------------------------------------------------------------
272
273impl std::fmt::Display for crate::context::KeyringFormat {
274    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
275        f.write_str(self.as_str())
276    }
277}
278
279impl FromStr for crate::context::KeyringFormat {
280    type Err = Error;
281    fn from_str(s: &str) -> Result<Self, Self::Err> {
282        match s.to_ascii_uppercase().as_str() {
283            "GPG" => Ok(crate::context::KeyringFormat::Gpg),
284            "KBX" => Ok(crate::context::KeyringFormat::Kbx),
285            "G10" => Ok(crate::context::KeyringFormat::G10),
286            "JSON" => Ok(crate::context::KeyringFormat::Json),
287            _ => Err(unknown("keyring format", s)),
288        }
289    }
290}
291
292// Suppress unused warning for the trait import we use implicitly.
293#[allow(dead_code)]
294fn _silence() {}