pub mod envelope;
#[cfg(feature = "legacy-bincode1-read")]
pub mod legacy;
use bytes::Bytes;
use http::{StatusCode, Version};
use serde::{Deserialize, Serialize};
use crate::backend::CacheEntry;
use crate::error::CacheError;
pub trait CacheCodec: Send + Sync + Clone + 'static {
const CODEC_ID: u8 = envelope::CODEC_USER;
fn encode(&self, entry: &CacheEntry) -> Result<Vec<u8>, CacheError>;
fn decode(&self, bytes: &[u8]) -> Result<CacheEntry, CacheError>;
}
#[derive(Clone, Default)]
pub struct PostcardCodec;
#[deprecated(
since = "0.6.0",
note = "renamed to PostcardCodec; the default wire format is now postcard inside a versioned envelope, not bare bincode"
)]
pub type BincodeCodec = PostcardCodec;
#[derive(Serialize, Deserialize)]
struct StoredEntry {
status: u16,
version: u8,
headers: Vec<(String, Vec<u8>)>,
body: Vec<u8>,
tags: Option<Vec<String>>,
}
impl CacheCodec for PostcardCodec {
const CODEC_ID: u8 = envelope::CODEC_POSTCARD;
fn encode(&self, entry: &CacheEntry) -> Result<Vec<u8>, CacheError> {
let stored = StoredEntry {
status: entry.status.as_u16(),
version: version_to_u8(entry.version),
headers: entry.headers.clone(),
body: entry.body.to_vec(),
tags: entry.tags.clone(),
};
postcard::to_allocvec(&stored).map_err(|err| CacheError::Backend(err.to_string()))
}
fn decode(&self, bytes: &[u8]) -> Result<CacheEntry, CacheError> {
let stored: StoredEntry =
postcard::from_bytes(bytes).map_err(|err| CacheError::Backend(err.to_string()))?;
Ok(CacheEntry {
status: StatusCode::from_u16(stored.status)
.map_err(|err| CacheError::Backend(err.to_string()))?,
version: version_from_u8(stored.version)?,
headers: stored.headers,
body: Bytes::from(stored.body),
tags: stored.tags,
})
}
}
pub(crate) fn version_to_u8(version: Version) -> u8 {
match version {
Version::HTTP_09 => 0,
Version::HTTP_10 => 1,
Version::HTTP_11 => 2,
Version::HTTP_2 => 3,
Version::HTTP_3 => 4,
_ => 2,
}
}
pub(crate) fn version_from_u8(value: u8) -> Result<Version, CacheError> {
match value {
0 => Ok(Version::HTTP_09),
1 => Ok(Version::HTTP_10),
2 => Ok(Version::HTTP_11),
3 => Ok(Version::HTTP_2),
4 => Ok(Version::HTTP_3),
_ => Err(CacheError::Backend("unknown HTTP version".into())),
}
}