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}