backpak/blob.rs
1//! Defines [`Blob`], our fundamental unit of backup.
2
3use serde_derive::{Deserialize, Serialize};
4
5use crate::chunk::FileSpan;
6use crate::hashing::ObjectId;
7
8/// A chunk of a file or a tree to place in a pack.
9///
10/// Our fundamental unit of backup.
11#[derive(Debug, Clone)]
12pub struct Blob {
13 /// The bytes to back up
14 pub contents: Contents,
15 /// The ID of said bytes
16 pub id: ObjectId,
17 /// Is the blob a chunk or a tree?
18 pub kind: Type,
19}
20
21#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
22#[serde(rename_all = "lowercase")]
23pub enum Type {
24 /// A chunk of a file.
25 Chunk,
26 /// File and directory metadata
27 Tree,
28}
29
30/// Either part of a loaded file or [`Vec`] buffer.
31///
32/// Formerly this was some `Box<AsRef<u8> + Send + Sync>`,
33/// but let's cut down on the indirection where there's only a few choices.
34///
35/// We could _almost_ elminate [`Blob::kind`] and make this
36/// ```ignore
37/// pub enum Contents {
38/// Tree(Vec<u8>),
39/// Chunk(FileSpan),
40/// }
41/// ```
42/// since chunks are almost always / `FileSpan`s and trees are almost always `Buffer`s. Almost...
43/// Except for the fact that chunks read from an existing pack file (e.g., when repacking)
44/// are also `Buffer`s.
45#[derive(Debug, Clone)]
46pub enum Contents {
47 Buffer(Vec<u8>),
48 Span(FileSpan),
49}
50
51impl Blob {
52 /// Convenience method to get at the blob's contents as a byte slice
53 pub fn bytes(&self) -> &[u8] {
54 match &self.contents {
55 Contents::Buffer(v) => v,
56 Contents::Span(s) => s.as_ref(),
57 }
58 }
59}