Skip to main content

xmtp_archive/
lib.rs

1use crate::archive_options::{ArchiveOptions, BackupElementSelection};
2pub use importer::ArchiveImporter;
3use thiserror::Error;
4use xmtp_common::time::now_ns;
5use xmtp_proto::xmtp::device_sync::{
6    BackupElementSelection as BackupElementSelectionProto, BackupMetadataSave,
7};
8
9pub const ENC_KEY_SIZE: usize = 32; // 256-bit key
10pub const NONCE_SIZE: usize = 12; // 96-bit nonce
11
12// Increment on breaking changes
13pub const BACKUP_VERSION: u16 = 0;
14
15pub mod archive_options;
16mod export_stream;
17pub mod exporter;
18pub mod importer;
19mod util;
20
21#[derive(Debug, Error)]
22pub enum ArchiveError {
23    #[error("Missing metadata")]
24    MissingMetadata,
25    #[error("AES-GCM encryption error")]
26    AesGcm(#[from] aes_gcm::Error),
27    #[error("IO error: {0}")]
28    IO(#[from] std::io::Error),
29    #[error(transparent)]
30    Decode(#[from] prost::DecodeError),
31}
32
33#[derive(Default)]
34pub struct BackupMetadata {
35    pub backup_version: u16,
36    pub elements: Vec<BackupElementSelection>,
37    pub exported_at_ns: i64,
38    pub start_ns: Option<i64>,
39    pub end_ns: Option<i64>,
40}
41
42impl BackupMetadata {
43    pub fn from_metadata_save(save: BackupMetadataSave, backup_version: u16) -> Self {
44        Self {
45            elements: save.elements().map(Into::into).collect(),
46            end_ns: save.end_ns,
47            start_ns: save.start_ns,
48            exported_at_ns: save.exported_at_ns,
49            backup_version,
50        }
51    }
52
53    pub fn from_metadata_version_unknown(save: BackupMetadataSave) -> Self {
54        Self::from_metadata_save(save, u16::MAX)
55    }
56}
57
58pub(crate) trait OptionsToSave {
59    fn from_options(options: ArchiveOptions) -> BackupMetadataSave;
60}
61impl OptionsToSave for BackupMetadataSave {
62    fn from_options(options: ArchiveOptions) -> BackupMetadataSave {
63        Self {
64            end_ns: options.end_ns,
65            start_ns: options.start_ns,
66            elements: options
67                .elements
68                .into_iter()
69                .map(|e| {
70                    let e: BackupElementSelectionProto = e.into();
71                    e as i32
72                })
73                .collect(),
74            exported_at_ns: now_ns(),
75        }
76    }
77}