1use std::{iter::FusedIterator, ops::Range};
2
3use crate::{Compression, Config, Error, FORMAT_VERSION, Framing, Lengths, Result};
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub struct FrameSizes {
8 pub(crate) raw: u64,
9 pub(crate) payload: u64,
10}
11
12impl FrameSizes {
13 pub fn new(raw: u64, payload: u64) -> Result<Self> {
15 if raw == 0 || payload == 0 || payload > raw {
16 return Err(Error::InvalidMetadata);
17 }
18 Ok(Self { raw, payload })
19 }
20 pub const fn raw_len(self) -> u64 {
22 self.raw
23 }
24 pub const fn payload_len(self) -> u64 {
26 self.payload
27 }
28}
29
30#[derive(Clone, Copy, Debug, Eq, PartialEq)]
32pub struct FrameSpec {
33 pub(crate) config: Config,
34 pub(crate) index: u64,
35 pub(crate) sizes: FrameSizes,
36}
37
38impl FrameSpec {
39 pub const fn index(self) -> u64 {
41 self.index
42 }
43 pub fn raw_len(self) -> usize {
45 self.sizes.raw as usize
46 }
47 pub fn stored_len(self) -> usize {
49 self.sizes.payload as usize + self.config.encryption().tag_len()
50 }
51 pub fn payload_len(self) -> usize {
53 self.sizes.payload as usize
54 }
55}
56
57#[derive(Clone, Debug, Eq, PartialEq)]
59pub struct FrameRead {
60 pub spec: FrameSpec,
62 pub selected: Range<usize>,
64}
65
66#[derive(Clone, Debug, Eq, PartialEq)]
69#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
70pub struct MetadataParts {
71 pub version: u8,
73 pub config: Config,
75 pub frame_count: u64,
77 pub last_frame_len: Option<u64>,
79 pub raw_lengths: Option<Lengths>,
81 pub payload_lengths: Option<Lengths>,
83}
84
85#[derive(Clone, Debug, Eq, PartialEq)]
88pub struct Metadata {
89 parts: MetadataParts,
90 logical_len: u64,
91 stored_len: u64,
92}
93
94#[cfg(feature = "serde")]
95impl serde::Serialize for Metadata {
96 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
97 where
98 S: serde::Serializer,
99 {
100 serde::Serialize::serialize(&self.parts, serializer)
101 }
102}
103
104#[cfg(feature = "serde")]
105impl<'de> serde::Deserialize<'de> for Metadata {
106 fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
107 where
108 D: serde::Deserializer<'de>,
109 {
110 let parts = <MetadataParts as serde::Deserialize>::deserialize(deserializer)?;
111 Self::from_parts(parts).map_err(serde::de::Error::custom)
112 }
113}
114
115impl Metadata {
116 pub fn new(config: Config) -> Self {
118 let table = || Lengths::new(config.max_frame_len()).expect("validated maximum");
119 Self {
120 parts: MetadataParts {
121 version: FORMAT_VERSION,
122 config,
123 frame_count: 0,
124 last_frame_len: None,
125 raw_lengths: matches!(config.framing(), Framing::Variable(_)).then(table),
126 payload_lengths: (config.compression() != Compression::None).then(table),
127 },
128 logical_len: 0,
129 stored_len: 0,
130 }
131 }
132
133 pub fn from_parts(parts: MetadataParts) -> Result<Self> {
136 if parts.version != FORMAT_VERSION {
137 return Err(Error::UnsupportedVersion);
138 }
139 let config = parts.config;
140 let count = parts.frame_count;
141 if count > config.max_frames() {
142 return Err(Error::UsageLimit);
143 }
144 let width = Lengths::new(config.max_frame_len())?.width();
145 let check_table = |table: &Option<Lengths>, required: bool| -> Result<()> {
146 match (table, required) {
147 (None, false) => Ok(()),
148 (Some(table), true) if table.len() as u64 == count && table.width() == width => {
149 Ok(())
150 }
151 _ => Err(Error::InvalidMetadata),
152 }
153 };
154 check_table(
155 &parts.raw_lengths,
156 matches!(config.framing(), Framing::Variable(_)),
157 )?;
158 check_table(
159 &parts.payload_lengths,
160 config.compression() != Compression::None,
161 )?;
162 match (config.framing(), count, parts.last_frame_len) {
163 (Framing::Fixed(max), 1.., Some(last)) if last > 0 && last <= max => {}
164 (Framing::Fixed(_), 0, None) | (Framing::Variable(_), _, None) => {}
165 _ => return Err(Error::InvalidMetadata),
166 }
167 let mut result = Self {
168 parts,
169 logical_len: 0,
170 stored_len: 0,
171 };
172 if let Framing::Fixed(size) = config.framing() {
173 if config.compression() == Compression::None {
174 let logical = if count == 0 {
175 0
176 } else {
177 (count - 1)
178 .checked_mul(size)
179 .and_then(|n| n.checked_add(result.parts.last_frame_len.unwrap()))
180 .ok_or(Error::Overflow)?
181 };
182 result.logical_len = logical;
183 result.stored_len = count
184 .checked_mul(config.encryption().tag_len() as u64)
185 .and_then(|tags| logical.checked_add(tags))
186 .ok_or(Error::Overflow)?;
187 return Ok(result);
188 }
189 }
190 for i in 0..count {
191 let raw = match config.framing() {
192 Framing::Fixed(size) if i + 1 < count => size,
193 Framing::Fixed(_) => result.parts.last_frame_len.unwrap(),
194 Framing::Variable(_) => result
195 .parts
196 .raw_lengths
197 .as_ref()
198 .unwrap()
199 .get(i as usize)
200 .ok_or(Error::InvalidMetadata)?,
201 };
202 let payload = match &result.parts.payload_lengths {
203 Some(table) => table.get(i as usize).ok_or(Error::InvalidMetadata)?,
204 None => raw,
205 };
206 config.validate_frame(i, raw, payload)?;
207 result.logical_len = result.logical_len.checked_add(raw).ok_or(Error::Overflow)?;
208 result.stored_len = result
209 .stored_len
210 .checked_add(payload)
211 .and_then(|n| n.checked_add(config.encryption().tag_len() as u64))
212 .ok_or(Error::Overflow)?;
213 }
214 Ok(result)
215 }
216
217 pub fn parts(&self) -> &MetadataParts {
219 &self.parts
220 }
221 pub fn into_parts(self) -> MetadataParts {
223 self.parts
224 }
225 pub fn config(&self) -> Config {
227 self.parts.config
228 }
229 pub fn frame_count(&self) -> u64 {
231 self.parts.frame_count
232 }
233 pub fn logical_len(&self) -> u64 {
235 self.logical_len
236 }
237 pub fn stored_len(&self) -> u64 {
239 self.stored_len
240 }
241 pub fn last_frame_len(&self) -> Option<u64> {
243 self.frame_count().checked_sub(1).map(|i| self.sizes(i).raw)
244 }
245
246 pub fn push(&mut self, sizes: FrameSizes) -> Result<()> {
249 let config = self.config();
250 config.validate_frame(self.frame_count(), sizes.raw, sizes.payload)?;
251 if let Framing::Fixed(size) = config.framing() {
252 if self.parts.last_frame_len.is_some_and(|last| last != size) {
253 return Err(Error::FrameAfterFinal);
254 }
255 }
256 let count = self.frame_count().checked_add(1).ok_or(Error::Overflow)?;
257 let logical = self
258 .logical_len
259 .checked_add(sizes.raw)
260 .ok_or(Error::Overflow)?;
261 let stored = self
262 .stored_len
263 .checked_add(sizes.payload)
264 .and_then(|n| n.checked_add(config.encryption().tag_len() as u64))
265 .ok_or(Error::Overflow)?;
266 if let Some(table) = &mut self.parts.raw_lengths {
268 table.reserve_one()?;
269 }
270 if let Some(table) = &mut self.parts.payload_lengths {
271 table.reserve_one()?;
272 }
273 if let Some(table) = &mut self.parts.raw_lengths {
274 table.push(sizes.raw)?;
275 }
276 if let Some(table) = &mut self.parts.payload_lengths {
277 table.push(sizes.payload)?;
278 }
279 if matches!(config.framing(), Framing::Fixed(_)) {
280 self.parts.last_frame_len = Some(sizes.raw);
281 }
282 self.parts.frame_count = count;
283 self.logical_len = logical;
284 self.stored_len = stored;
285 Ok(())
286 }
287
288 pub fn frame(&self, index: u64) -> Option<FrameSpec> {
290 (index < self.frame_count()).then(|| FrameSpec {
291 config: self.config(),
292 index,
293 sizes: self.sizes(index),
294 })
295 }
296
297 fn sizes(&self, index: u64) -> FrameSizes {
298 let raw = match self.config().framing() {
299 Framing::Fixed(size) if index + 1 < self.frame_count() => size,
300 Framing::Fixed(_) => self.parts.last_frame_len.unwrap(),
301 Framing::Variable(_) => self
302 .parts
303 .raw_lengths
304 .as_ref()
305 .unwrap()
306 .get(index as usize)
307 .unwrap(),
308 };
309 let payload = self
310 .parts
311 .payload_lengths
312 .as_ref()
313 .map_or(raw, |v| v.get(index as usize).unwrap());
314 FrameSizes { raw, payload }
315 }
316
317 pub fn range(&self, start: u64, end: Option<u64>) -> Result<(Range<u64>, FrameIter<'_>)> {
322 let end = end.unwrap_or(self.logical_len);
323 if start > end || end > self.logical_len {
324 return Err(Error::InvalidRange);
325 }
326 let iter = |first, stop, logical| FrameIter {
327 metadata: self,
328 next: first,
329 stop,
330 logical,
331 selection: start..end,
332 };
333 if start == end {
334 return Ok((0..0, iter(0, 0, 0)));
335 }
336 if let Framing::Fixed(size) = self.config().framing() {
337 let first = start / size;
338 let stop = (end - 1) / size + 1;
339 if self.config().compression() == Compression::None {
340 let stride = size + self.config().encryption().tag_len() as u64;
341 let physical_start = first * stride;
342 let physical_end = if stop == self.frame_count() {
343 self.stored_len
344 } else {
345 stop * stride
346 };
347 return Ok((
348 physical_start..physical_end,
349 iter(first, stop, first * size),
350 ));
351 }
352 let mut physical = 0;
353 for i in 0..first {
354 physical += self.sizes(i).payload + self.config().encryption().tag_len() as u64;
355 }
356 let physical_start = physical;
357 if stop == self.frame_count() {
358 physical = self.stored_len;
359 } else {
360 for i in first..stop {
361 physical += self.sizes(i).payload + self.config().encryption().tag_len() as u64;
362 }
363 }
364 return Ok((physical_start..physical, iter(first, stop, first * size)));
365 }
366 let mut logical = 0;
367 let mut physical = 0;
368 let mut first = 0;
369 while logical + self.sizes(first).raw <= start {
370 let sizes = self.sizes(first);
371 logical += sizes.raw;
372 physical += sizes.payload + self.config().encryption().tag_len() as u64;
373 first += 1;
374 }
375 let logical_start = logical;
376 let physical_start = physical;
377 let mut stop = first;
378 if end == self.logical_len {
379 stop = self.frame_count();
380 physical = self.stored_len;
381 } else {
382 while logical < end {
383 let sizes = self.sizes(stop);
384 logical += sizes.raw;
385 physical += sizes.payload + self.config().encryption().tag_len() as u64;
386 stop += 1;
387 }
388 }
389 Ok((physical_start..physical, iter(first, stop, logical_start)))
390 }
391}
392
393#[derive(Clone, Debug)]
395pub struct FrameIter<'a> {
396 metadata: &'a Metadata,
397 next: u64,
398 stop: u64,
399 logical: u64,
400 selection: Range<u64>,
401}
402
403impl FrameIter<'_> {
404 pub fn remaining(&self) -> u64 {
406 self.stop - self.next
407 }
408}
409
410impl Iterator for FrameIter<'_> {
411 type Item = FrameRead;
412
413 fn next(&mut self) -> Option<Self::Item> {
414 if self.next == self.stop {
415 return None;
416 }
417 let spec = self.metadata.frame(self.next).unwrap();
418 let logical_end = self.logical + spec.sizes.raw;
419 let selected = (self.selection.start.saturating_sub(self.logical) as usize)
420 ..((self.selection.end.min(logical_end) - self.logical) as usize);
421 self.logical = logical_end;
422 self.next += 1;
423 Some(FrameRead { spec, selected })
424 }
425
426 fn size_hint(&self) -> (usize, Option<usize>) {
427 match usize::try_from(self.remaining()) {
428 Ok(n) => (n, Some(n)),
429 Err(_) => (usize::MAX, None),
430 }
431 }
432}
433
434impl FusedIterator for FrameIter<'_> {}