1use serde::{Deserialize, Serialize};
2
3use crate::locks::Lock;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
6#[serde(rename_all = "lowercase")]
7pub enum Operation {
8 Upload,
9 Download,
10}
11
12#[derive(Debug, Clone, Deserialize, Serialize)]
13pub struct ObjectId {
14 pub oid: String,
15 pub size: u64,
16}
17
18#[derive(Debug, Deserialize)]
19pub struct BatchRequest {
20 pub operation: Operation,
21 #[serde(default)]
22 pub transfers: Vec<String>,
23 pub objects: Vec<ObjectId>,
24 #[serde(rename = "ref")]
25 pub reference: Option<Reference>,
26}
27
28#[derive(Debug, Deserialize)]
29pub struct RetainRequest {
30 pub oids: Vec<String>,
31 #[serde(default)]
32 pub dry_run: bool,
33}
34
35#[derive(Debug, Deserialize)]
36pub struct CompressRequest {
37 #[serde(default)]
38 pub dry_run: bool,
39}
40
41#[derive(Debug, Deserialize)]
42pub struct DedupeRequest {
43 #[serde(default)]
44 pub dry_run: bool,
45}
46
47#[derive(Debug, Serialize)]
48pub struct BatchResponse {
49 pub transfer: &'static str,
50 pub objects: Vec<ObjectSpec>,
51}
52
53#[derive(Debug, Serialize)]
54pub struct ObjectSpec {
55 #[serde(flatten)]
56 pub id: ObjectId,
57 #[serde(skip_serializing_if = "Option::is_none")]
62 pub authenticated: Option<bool>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub actions: Option<Actions>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub error: Option<ObjectError>,
67}
68
69#[derive(Debug, Default, Serialize)]
70pub struct Actions {
71 #[serde(skip_serializing_if = "Option::is_none")]
72 pub upload: Option<Action>,
73 #[serde(skip_serializing_if = "Option::is_none")]
74 pub download: Option<Action>,
75 #[serde(skip_serializing_if = "Option::is_none")]
76 pub verify: Option<Action>,
77}
78
79#[derive(Debug, Serialize)]
80pub struct Action {
81 pub href: String,
82 #[serde(skip_serializing_if = "Option::is_none")]
86 pub header: Option<std::collections::BTreeMap<String, String>>,
87 pub expires_in: u32,
88}
89
90#[derive(Debug, Serialize)]
91pub struct ObjectError {
92 pub code: u16,
93 pub message: String,
94}
95
96impl ObjectSpec {
97 pub fn missing(id: ObjectId) -> Self {
98 Self {
99 id,
100 authenticated: None,
101 actions: None,
102 error: Some(ObjectError {
103 code: 404,
104 message: "object not found".into(),
105 }),
106 }
107 }
108
109 pub fn malformed(id: ObjectId) -> Self {
113 Self {
114 id,
115 authenticated: None,
116 actions: None,
117 error: Some(ObjectError {
118 code: 422,
119 message: crate::error::Error::MalformedOid.to_string(),
120 }),
121 }
122 }
123
124 pub fn too_large(id: ObjectId, limit: u64) -> Self {
125 Self {
126 error: Some(ObjectError {
127 code: 413,
128 message: format!(
129 "object is {} bytes, over the {limit} byte limit this server accepts",
130 id.size
131 ),
132 }),
133 id,
134 authenticated: None,
135 actions: None,
136 }
137 }
138
139 pub fn over_quota(id: ObjectId, used: u64, limit: u64) -> Self {
140 Self {
141 id,
142 authenticated: None,
143 actions: None,
144 error: Some(ObjectError {
145 code: 507,
146 message: format!(
147 "this repository holds {used} bytes of its {limit} byte budget: collect what \
148 it no longer references, or ask for more room"
149 ),
150 }),
151 }
152 }
153}
154
155#[derive(Debug, Deserialize)]
156pub struct CreateLockRequest {
157 pub path: String,
158}
159
160#[derive(Debug, Deserialize)]
161pub struct ListLocksQuery {
162 pub path: Option<String>,
163 pub id: Option<String>,
164 pub cursor: Option<String>,
165 pub limit: Option<usize>,
166 #[serde(rename = "refspec")]
169 pub refspec: Option<String>,
170}
171
172#[derive(Debug, Default, Deserialize)]
173pub struct VerifyLocksRequest {
174 pub cursor: Option<String>,
175 pub limit: Option<usize>,
176 #[serde(rename = "ref")]
177 pub reference: Option<Reference>,
178}
179
180#[derive(Debug, Deserialize)]
181pub struct Reference {
182 pub name: String,
183}
184
185#[derive(Debug, Deserialize)]
186pub struct UnlockRequest {
187 #[serde(default)]
188 pub force: bool,
189}
190
191#[derive(Debug, Serialize)]
192pub struct LockResponse {
193 pub lock: Lock,
194}
195
196#[derive(Debug, Serialize)]
197pub struct ListLocksResponse {
198 pub locks: Vec<Lock>,
199 #[serde(skip_serializing_if = "String::is_empty")]
200 pub next_cursor: String,
201}
202
203#[derive(Debug, Serialize)]
204pub struct VerifyLocksResponse {
205 pub ours: Vec<Lock>,
206 pub theirs: Vec<Lock>,
207 #[serde(skip_serializing_if = "String::is_empty")]
208 pub next_cursor: String,
209}
210
211#[derive(Debug, Serialize)]
212pub struct StatsResponse {
213 pub objects: u64,
214 pub bytes: u64,
215 pub locks: usize,
216}