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 too_large(id: ObjectId, limit: u64) -> Self {
110 Self {
111 error: Some(ObjectError {
112 code: 413,
113 message: format!(
114 "object is {} bytes, over the {limit} byte limit this server accepts",
115 id.size
116 ),
117 }),
118 id,
119 authenticated: None,
120 actions: None,
121 }
122 }
123
124 pub fn over_quota(id: ObjectId, used: u64, limit: u64) -> Self {
125 Self {
126 id,
127 authenticated: None,
128 actions: None,
129 error: Some(ObjectError {
130 code: 507,
131 message: format!(
132 "this repository holds {used} bytes of its {limit} byte budget — collect what \
133 it no longer references, or ask for more room"
134 ),
135 }),
136 }
137 }
138}
139
140#[derive(Debug, Deserialize)]
141pub struct CreateLockRequest {
142 pub path: String,
143}
144
145#[derive(Debug, Deserialize)]
146pub struct ListLocksQuery {
147 pub path: Option<String>,
148 pub id: Option<String>,
149 pub cursor: Option<String>,
150 pub limit: Option<usize>,
151 #[serde(rename = "refspec")]
154 pub refspec: Option<String>,
155}
156
157#[derive(Debug, Default, Deserialize)]
158pub struct VerifyLocksRequest {
159 pub cursor: Option<String>,
160 pub limit: Option<usize>,
161 #[serde(rename = "ref")]
162 pub reference: Option<Reference>,
163}
164
165#[derive(Debug, Deserialize)]
166pub struct Reference {
167 pub name: String,
168}
169
170#[derive(Debug, Deserialize)]
171pub struct UnlockRequest {
172 #[serde(default)]
173 pub force: bool,
174}
175
176#[derive(Debug, Serialize)]
177pub struct LockResponse {
178 pub lock: Lock,
179}
180
181#[derive(Debug, Serialize)]
182pub struct ListLocksResponse {
183 pub locks: Vec<Lock>,
184 #[serde(skip_serializing_if = "String::is_empty")]
185 pub next_cursor: String,
186}
187
188#[derive(Debug, Serialize)]
189pub struct VerifyLocksResponse {
190 pub ours: Vec<Lock>,
191 pub theirs: Vec<Lock>,
192 #[serde(skip_serializing_if = "String::is_empty")]
193 pub next_cursor: String,
194}
195
196#[derive(Debug, Serialize)]
197pub struct StatsResponse {
198 pub objects: u64,
199 pub bytes: u64,
200 pub locks: usize,
201}