tower_http_cache/
codec.rs1use bytes::Bytes;
2use http::{StatusCode, Version};
3use serde::{Deserialize, Serialize};
4
5use crate::backend::CacheEntry;
6use crate::error::CacheError;
7
8pub trait CacheCodec: Send + Sync + Clone + 'static {
10 fn encode(&self, entry: &CacheEntry) -> Result<Vec<u8>, CacheError>;
11 fn decode(&self, bytes: &[u8]) -> Result<CacheEntry, CacheError>;
12}
13
14#[derive(Clone, Default)]
16pub struct BincodeCodec;
17
18#[derive(Serialize, Deserialize)]
19struct StoredEntry {
20 status: u16,
21 version: u8,
22 headers: Vec<(String, Vec<u8>)>,
23 body: Vec<u8>,
24}
25
26impl CacheCodec for BincodeCodec {
27 fn encode(&self, entry: &CacheEntry) -> Result<Vec<u8>, CacheError> {
28 let stored = StoredEntry {
29 status: entry.status.as_u16(),
30 version: version_to_u8(entry.version),
31 headers: entry.headers.clone(),
32 body: entry.body.to_vec(),
33 };
34
35 bincode::serialize(&stored).map_err(|err| CacheError::Backend(err.to_string()))
36 }
37
38 fn decode(&self, bytes: &[u8]) -> Result<CacheEntry, CacheError> {
39 let stored: StoredEntry =
40 bincode::deserialize(bytes).map_err(|err| CacheError::Backend(err.to_string()))?;
41 let entry = CacheEntry::new(
42 StatusCode::from_u16(stored.status)
43 .map_err(|err| CacheError::Backend(err.to_string()))?,
44 version_from_u8(stored.version)?,
45 stored.headers,
46 Bytes::from(stored.body),
47 );
48 Ok(entry)
49 }
50}
51
52fn version_to_u8(version: Version) -> u8 {
53 match version {
54 Version::HTTP_09 => 0,
55 Version::HTTP_10 => 1,
56 Version::HTTP_11 => 2,
57 Version::HTTP_2 => 3,
58 Version::HTTP_3 => 4,
59 _ => 2,
60 }
61}
62
63fn version_from_u8(value: u8) -> Result<Version, CacheError> {
64 match value {
65 0 => Ok(Version::HTTP_09),
66 1 => Ok(Version::HTTP_10),
67 2 => Ok(Version::HTTP_11),
68 3 => Ok(Version::HTTP_2),
69 4 => Ok(Version::HTTP_3),
70 _ => Err(CacheError::Backend("unknown HTTP version".into())),
71 }
72}