tower_http_cache_plus/cache/
body.rs1use super::{configuration::*, weight::*};
2
3use {
4 kutil::{
5 std::{collections::*, immutable::*},
6 transcoding::{transcode::*, *},
7 },
8 std::io,
9};
10
11#[derive(Clone, Debug, Default)]
17pub struct CachedBody {
18 pub representations: FastHashMap<Encoding, ImmutableBytes>,
20}
21
22impl CachedBody {
23 pub async fn new_with(
30 bytes: ImmutableBytes,
31 encoding: Encoding,
32 preferred_encoding: Encoding,
33 configuration: &EncodingConfiguration,
34 ) -> io::Result<Self> {
35 let mut representations = FastHashMap::default();
36
37 if preferred_encoding == encoding {
38 representations.insert(preferred_encoding, bytes);
40 } else if encoding == Encoding::Identity {
41 tracing::debug!("encoding to {}", preferred_encoding);
42
43 let encoded_bytes = bytes.encode(&preferred_encoding).await?;
44
45 representations.insert(preferred_encoding, encoded_bytes);
46 if configuration.keep_identity_encoding {
47 representations.insert(Encoding::Identity, bytes);
48 }
49 } else if preferred_encoding == Encoding::Identity {
50 tracing::debug!("decoding from {}", encoding);
51
52 let identity_bytes = bytes.decode(&encoding).await?;
53
54 representations.insert(Encoding::Identity, identity_bytes);
55 } else {
56 tracing::debug!("reencoding from {} to {}", encoding, preferred_encoding);
57
58 let identity_bytes = bytes.decode(&encoding).await?;
59 let encoded_bytes = identity_bytes.encode(&preferred_encoding).await?;
60
61 representations.insert(preferred_encoding, encoded_bytes);
62 if configuration.keep_identity_encoding {
63 representations.insert(Encoding::Identity, identity_bytes);
64 }
65 }
66
67 Ok(Self { representations })
68 }
69
70 pub async fn get(
81 &self,
82 encoding: &Encoding,
83 configuration: &EncodingConfiguration,
84 ) -> io::Result<(ImmutableBytes, Option<Self>)> {
85 match (self.representations.get(encoding), encoding) {
86 (Some(bytes), _) => Ok((bytes.clone(), None)),
87
88 (None, Encoding::Identity) => {
89 for from_encoding in ENCODINGS_BY_DECODING_COST {
91 if let Some(bytes) = self.representations.get(from_encoding) {
92 tracing::debug!("decoding from {}", from_encoding);
93
94 let identity_bytes = bytes.decode(from_encoding).await?;
95
96 let mut modified = self.clone();
97 modified
98 .representations
99 .insert(Encoding::Identity, identity_bytes.clone());
100
101 return Ok((identity_bytes, Some(modified)));
102 }
103 }
104
105 tracing::error!("no encodings");
107 Ok((Default::default(), None))
108 }
109
110 (None, to_encoding) => {
111 if let Some(identity_bytes) = self.representations.get(&Encoding::Identity) {
113 tracing::debug!("encoding to {}", to_encoding);
114
115 let bytes = identity_bytes.encode(to_encoding).await?;
116
117 let mut modified = self.clone();
118 modified
119 .representations
120 .insert(to_encoding.clone(), bytes.clone());
121
122 Ok((bytes, Some(modified)))
123 } else {
124 for from_encoding in ENCODINGS_BY_DECODING_COST {
125 if let Some(bytes) = self.representations.get(from_encoding) {
126 tracing::debug!("reencoding from {} to {}", from_encoding, to_encoding);
127
128 let identity_bytes = bytes.decode(from_encoding).await?;
129 let bytes = identity_bytes.encode(to_encoding).await?;
130
131 let mut modified = self.clone();
132 if configuration.keep_identity_encoding {
133 modified
134 .representations
135 .insert(Encoding::Identity, identity_bytes);
136 }
137 modified
138 .representations
139 .insert(to_encoding.clone(), bytes.clone());
140
141 return Ok((bytes, Some(modified)));
142 }
143 }
144
145 tracing::error!("no encodings");
147 Ok((Default::default(), None))
148 }
149 }
150 }
151 }
152}
153
154impl CacheWeight for CachedBody {
155 fn cache_weight(&self) -> usize {
156 const SELF_SIZE: usize = size_of::<CachedBody>();
157 const ENTRY_SIZE: usize = size_of::<Encoding>() + size_of::<ImmutableBytes>();
158
159 let mut size = SELF_SIZE;
160
161 for bytes in self.representations.values() {
162 size += ENTRY_SIZE + bytes.len();
163 }
164
165 size
166 }
167}