use cllw_ore::{OpeCllw8VariableV1, OreCllw8VariableV1};
use hex::{FromHex, FromHexError};
use serde::{Deserialize, Serialize};
#[derive(Debug, PartialEq, Eq, PartialOrd, Serialize, Deserialize)]
#[serde(untagged)]
#[non_exhaustive]
pub enum EncryptedSteVecTerm {
Compat(EncryptedSteVecTermCompat),
Standard(EncryptedSteVecTermStandard),
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Serialize, Deserialize)]
#[non_exhaustive]
pub enum EncryptedSteVecTermCompat {
#[serde(with = "hex::serde", rename = "hm")]
Mac(Mac),
#[serde(with = "hex::serde", rename = "op")]
Ope(OpeCllw8VariableV1),
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Serialize, Deserialize)]
#[non_exhaustive]
pub enum EncryptedSteVecTermStandard {
#[serde(with = "hex::serde", rename = "hm")]
Mac(Mac),
#[serde(with = "hex::serde", rename = "oc")]
Ore(OreCllw8VariableV1),
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Mac(Vec<u8>);
impl AsRef<[u8]> for Mac {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl FromHex for Mac {
type Error = FromHexError;
fn from_hex<T: AsRef<[u8]>>(hex: T) -> Result<Self, Self::Error> {
Ok(Self(Vec::from_hex(hex.as_ref())?))
}
}
impl Mac {
pub(crate) fn new(bytes: Vec<u8>) -> Self {
Self(bytes)
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn compat_mac_serializes_as_hm() {
let term = EncryptedSteVecTermCompat::Mac(Mac::new(vec![0xab, 0xcd]));
assert_eq!(serde_json::to_value(&term).unwrap(), json!({"hm": "abcd"}));
}
#[test]
fn compat_ope_serializes_as_op() {
let term = EncryptedSteVecTermCompat::Ope(OpeCllw8VariableV1::from_bytes(vec![1, 2, 3]));
assert_eq!(
serde_json::to_value(&term).unwrap(),
json!({"op": "010203"})
);
}
#[test]
fn compat_ope_roundtrips_through_serde() {
let term = EncryptedSteVecTermCompat::Ope(OpeCllw8VariableV1::from_bytes(vec![0xde, 0xad]));
let s = serde_json::to_string(&term).unwrap();
let back: EncryptedSteVecTermCompat = serde_json::from_str(&s).unwrap();
assert_eq!(back, term);
}
#[test]
fn standard_ore_serializes_as_oc() {
let term = EncryptedSteVecTermStandard::Ore(OreCllw8VariableV1::from(vec![0x42, 0x43]));
assert_eq!(serde_json::to_value(&term).unwrap(), json!({"oc": "4243"}));
}
#[test]
fn standard_ore_roundtrips_through_serde() {
let term = EncryptedSteVecTermStandard::Ore(OreCllw8VariableV1::from(vec![0x99]));
let s = serde_json::to_string(&term).unwrap();
let back: EncryptedSteVecTermStandard = serde_json::from_str(&s).unwrap();
assert_eq!(back, term);
}
#[test]
fn compat_and_standard_mac_share_hm_tag() {
let compat = EncryptedSteVecTermCompat::Mac(Mac::new(vec![1, 2]));
let standard = EncryptedSteVecTermStandard::Mac(Mac::new(vec![1, 2]));
assert_eq!(
serde_json::to_value(&compat).unwrap(),
serde_json::to_value(&standard).unwrap()
);
}
}