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; pub const NONCE_SIZE: usize = 12; pub 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}