jsonwebkey/
key_ops.rs

1use serde::{
2    de::{self, Deserialize, Deserializer},
3    ser::{Serialize, SerializeSeq, Serializer},
4};
5
6macro_rules! impl_key_ops {
7    ($(($key_op:ident, $const_name:ident, $i:literal)),+,) => {
8        bitflags::bitflags! {
9            #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)]
10            pub struct KeyOps: u16 {
11                $(const $const_name = $i;)*
12            }
13        }
14
15        impl Serialize for KeyOps {
16            fn serialize<S: Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
17                let mut seq = s.serialize_seq(Some(self.bits().count_ones() as usize))?;
18                $(
19                    if self.contains(KeyOps::$const_name) {
20                        seq.serialize_element(stringify!($key_op))?;
21                    }
22                )+
23                seq.end()
24            }
25        }
26
27        impl<'de> Deserialize<'de> for KeyOps {
28            fn deserialize<D: Deserializer<'de>>(d: D) -> Result<KeyOps, D::Error> {
29                let op_strs: Vec<String> = Deserialize::deserialize(d)?;
30                let mut ops = KeyOps::default();
31                for op_str in op_strs {
32                    $(
33                        if op_str == stringify!($key_op) {
34                            ops |= KeyOps::$const_name;
35                            continue;
36                        }
37                    )+
38                        return Err(de::Error::custom(&format!("invalid key op: `{}`", op_str)));
39                }
40                Ok(ops)
41            }
42        }
43    };
44}
45
46#[rustfmt::skip]
47impl_key_ops!(
48    (sign,       SIGN,        0b00000001),
49    (verify,     VERIFY,      0b00000010),
50    (encrypt,    ENCRYPT,     0b00000100),
51    (decrypt,    DECRYPT,     0b00001000),
52    (wrapKey,    WRAP_KEY,    0b00010000),
53    (unwrapKey,  UNWRAP_KEY,  0b00100000),
54    (deriveKey,  DERIVE_KEY,  0b01000000),
55    (deriveBits, DERIVE_BITS, 0b10000000),
56);
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn deserialize_invalid() {
64        let result: Result<KeyOps, _> = serde_json::from_str(r#"["unknown"]"#);
65        assert!(result.is_err());
66    }
67
68    #[test]
69    fn serialize() {
70        let ops = KeyOps::SIGN | KeyOps::DERIVE_BITS;
71        let json = serde_json::to_string(&ops).unwrap();
72        assert_eq!(json, r#"["sign","deriveBits"]"#)
73    }
74}