1use std::{iter::once, str::from_utf8};
14
15use hitbox_core::{CacheKey, KeyPart};
16
17use crate::format::FormatError;
18
19const PREFIX_KEY: &str = "_prefix";
20const VERSION_KEY: &str = "_version";
21
22#[derive(Default, Clone, Copy, Debug, PartialEq, Eq)]
26pub enum CacheKeyFormat {
27 #[default]
31 Bitcode,
32
33 UrlEncoded,
38}
39
40impl CacheKeyFormat {
41 pub fn serialize(&self, key: &CacheKey) -> Result<Vec<u8>, FormatError> {
43 match self {
44 CacheKeyFormat::Bitcode => Ok(bitcode::encode(key)),
45 CacheKeyFormat::UrlEncoded => {
46 let pairs = once((PREFIX_KEY, key.prefix().to_string()))
47 .chain(once((VERSION_KEY, key.version().to_string())))
48 .chain(
49 key.parts()
50 .map(|p| (p.key(), p.value().unwrap_or_default().to_string())),
51 )
52 .collect::<Vec<_>>();
53
54 serde_urlencoded::to_string(pairs)
55 .map(String::into_bytes)
56 .map_err(|err| FormatError::Serialize(Box::new(err)))
57 }
58 }
59 }
60
61 pub fn deserialize(&self, data: &[u8]) -> Result<CacheKey, FormatError> {
63 match self {
64 CacheKeyFormat::Bitcode => {
65 bitcode::decode(data).map_err(|err| FormatError::Deserialize(Box::new(err)))
66 }
67 CacheKeyFormat::UrlEncoded => {
68 let input =
69 from_utf8(data).map_err(|err| FormatError::Deserialize(Box::new(err)))?;
70
71 let pairs: Vec<(String, String)> = serde_urlencoded::from_str(input)
72 .map_err(|err| FormatError::Deserialize(Box::new(err)))?;
73
74 let (mut prefix, mut version, mut parts) = (String::new(), 0u32, Vec::new());
75
76 for (key, value) in pairs {
77 match key.as_str() {
78 PREFIX_KEY => prefix = value,
79 VERSION_KEY => {
80 version = value
81 .parse()
82 .map_err(|err| FormatError::Deserialize(Box::new(err)))?;
83 }
84 _ => {
85 let v = if value.is_empty() { None } else { Some(value) };
86 parts.push(KeyPart::new(key, v));
87 }
88 }
89 }
90
91 Ok(CacheKey::new(prefix, version, parts))
92 }
93 }
94 }
95}