coven_database/
file_ref.rs1use crate::{
6 file_location::{FileLocation, Place},
7 file_table::Record,
8 sqlite::DatabaseConnection,
9 DbError,
10};
11use coven_crypto::ContentHash;
12use coven_foundation::id_source::{DeviceId, FileId};
13use coven_merge::Audience;
14
15#[path = "local_file.rs"]
16mod local_file;
17pub(crate) use local_file::{device_only_source, open_source, queued_source, LocalSource};
18pub use local_file::{LocalFileError, LocalFileStream};
19
20#[derive(Clone, Debug, PartialEq)]
22pub struct FileRef {
23 id: FileId,
24 audience: Audience,
25 namespace: String,
26 size: u64,
27 place: Stored,
28}
29
30#[derive(Clone, Debug, PartialEq)]
31enum Stored {
32 Cloud { location: FileLocation, hash: ContentHash },
33 DeviceOnly(DeviceId),
34}
35
36#[derive(Clone, Copy, Debug, PartialEq)]
38pub enum FilePlace<'a> {
39 Cloud {
41 location: &'a FileLocation,
43 uploader: DeviceId,
45 content_hash: &'a ContentHash,
47 },
48 DeviceOnly {
51 device: DeviceId,
53 },
54}
55
56impl FileRef {
57 pub fn id(&self) -> FileId {
59 self.id
60 }
61 pub fn size(&self) -> u64 {
63 self.size
64 }
65 pub fn namespace(&self) -> &str {
68 &self.namespace
69 }
70 pub fn audience(&self) -> Audience {
73 self.audience.clone()
74 }
75 pub fn place(&self) -> FilePlace<'_> {
77 match &self.place {
78 Stored::Cloud { location, hash } => {
79 FilePlace::Cloud { location, uploader: location.uploader(), content_hash: hash }
80 }
81 Stored::DeviceOnly(device) => FilePlace::DeviceOnly { device: *device },
82 }
83 }
84
85 pub(crate) fn of(record: Record) -> Result<Self, DbError> {
86 let place = match (record.place, record.hash) {
87 (Place::Cloud(location), Some(hash)) => Stored::Cloud { location, hash },
88 (Place::DeviceOnly(device), None) => Stored::DeviceOnly(device),
89 _ => return Err(DbError::DamagedDatabase),
90 };
91 Ok(Self {
92 id: record.id,
93 audience: record.audience,
94 namespace: record.namespace,
95 size: record.size,
96 place,
97 })
98 }
99}
100
101pub(crate) fn read(db: &DatabaseConnection, file: FileId) -> Result<FileRef, DbError> {
103 FileRef::of(Record::read(db, file)?.ok_or(DbError::FileAbsent { file })?)
104}
105
106#[cfg(test)]
107#[path = "file_ref_tests.rs"]
108mod tests;