1use std::path::{Path, PathBuf};
2
3use anyhow::Result;
4use serde::{Deserialize, Serialize};
5use uuid::Uuid;
6
7use crate::Hashes;
8use crate::audit::AuditEntry;
9use crate::config::Compression;
10use crate::paths::ProjectPath;
11
12pub mod local;
13pub mod server;
14
15use local::LocalBackend;
16use server::ServerBackend;
17
18pub struct StoreRequest<'a> {
20 pub hashes: &'a Hashes,
21 pub source: &'a Path,
22 pub compression: Compression,
25 pub path: ProjectPath,
26 pub operation_id: Uuid,
27 pub message: Option<&'a str>,
28 pub on_bytes: Option<&'a (dyn Fn(u64) + Send + Sync)>,
29}
30
31impl<'a> StoreRequest<'a> {
32 pub fn new_local(
33 hashes: &'a Hashes,
34 source: &'a Path,
35 path: ProjectPath,
36 compression: Compression,
37 ) -> Self {
38 Self {
39 hashes,
40 source,
41 compression,
42 path,
43 operation_id: Uuid::nil(),
44 message: None,
45 on_bytes: None,
46 }
47 }
48}
49
50#[derive(Debug)]
52pub struct StoreResult {
53 pub stored_size: u64,
55 pub compression: Compression,
57 pub created: bool,
59}
60
61pub struct RetrieveRequest<'a> {
63 pub hashes: &'a Hashes,
64 pub target: &'a Path,
65 pub compression: Compression,
66 pub path: ProjectPath,
67 pub operation_id: Uuid,
68 pub on_bytes: Option<&'a (dyn Fn(u64) + Send + Sync)>,
69}
70
71impl<'a> RetrieveRequest<'a> {
72 pub fn new_local(
73 hashes: &'a Hashes,
74 target: &'a Path,
75 path: ProjectPath,
76 compression: Compression,
77 ) -> Self {
78 Self {
79 hashes,
80 target,
81 compression,
82 path,
83 operation_id: Uuid::nil(),
84 on_bytes: None,
85 }
86 }
87}
88
89#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
90#[serde(untagged)]
91pub enum Backend {
92 Local(LocalBackend),
93 Server(ServerBackend),
94}
95
96impl Backend {
97 pub fn init(&self, compression: Compression) -> Result<bool> {
100 match self {
101 Backend::Local(b) => b.init(compression),
102 Backend::Server(s) => s.init(compression),
103 }
104 }
105
106 pub fn check_access(&self) -> Result<()> {
110 match self {
111 Backend::Local(_) => Ok(()),
113 Backend::Server(s) => s.check_access(),
114 }
115 }
116
117 pub fn store(&self, req: StoreRequest<'_>) -> Result<StoreResult> {
121 match self {
122 Backend::Local(b) => b.store(req),
123 Backend::Server(s) => s.store(req),
124 }
125 }
126
127 pub fn retrieve(&self, req: RetrieveRequest<'_>) -> Result<bool> {
130 match self {
131 Backend::Local(b) => b.retrieve(req),
132 Backend::Server(s) => s.retrieve(req),
133 }
134 }
135
136 pub fn exists(&self, hash: &Hashes) -> Result<bool> {
138 match self {
139 Backend::Local(b) => b.exists(hash),
140 Backend::Server(s) => s.exists(hash),
141 }
142 }
143
144 pub fn remove(&self, hash: &Hashes) -> Result<()> {
146 match self {
147 Backend::Local(b) => b.remove(hash),
148 Backend::Server(s) => s.remove(hash),
149 }
150 }
151
152 pub fn get_audit_entries(&self, files: &[PathBuf]) -> Result<Vec<AuditEntry>> {
155 match self {
156 Backend::Local(b) => b.get_audit_entries(files),
157 Backend::Server(s) => s.get_audit_entries(files),
158 }
159 }
160}