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}
25
26#[derive(Debug, Deserialize)]
27pub struct RetainRequest {
28 pub oids: Vec<String>,
29 #[serde(default)]
30 pub dry_run: bool,
31}
32
33#[derive(Debug, Deserialize)]
34pub struct CompressRequest {
35 #[serde(default)]
36 pub dry_run: bool,
37}
38
39#[derive(Debug, Deserialize)]
40pub struct DedupeRequest {
41 #[serde(default)]
42 pub dry_run: bool,
43}
44
45#[derive(Debug, Serialize)]
46pub struct BatchResponse {
47 pub transfer: &'static str,
48 pub objects: Vec<ObjectSpec>,
49}
50
51#[derive(Debug, Serialize)]
52pub struct ObjectSpec {
53 #[serde(flatten)]
54 pub id: ObjectId,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub actions: Option<Actions>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub error: Option<ObjectError>,
59}
60
61#[derive(Debug, Default, Serialize)]
62pub struct Actions {
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub upload: Option<Action>,
65 #[serde(skip_serializing_if = "Option::is_none")]
66 pub download: Option<Action>,
67 #[serde(skip_serializing_if = "Option::is_none")]
68 pub verify: Option<Action>,
69}
70
71#[derive(Debug, Serialize)]
72pub struct Action {
73 pub href: String,
74 pub expires_in: u32,
75}
76
77#[derive(Debug, Serialize)]
78pub struct ObjectError {
79 pub code: u16,
80 pub message: String,
81}
82
83impl ObjectSpec {
84 pub fn missing(id: ObjectId) -> Self {
85 Self {
86 id,
87 actions: None,
88 error: Some(ObjectError {
89 code: 404,
90 message: "object not found".into(),
91 }),
92 }
93 }
94
95 pub fn too_large(id: ObjectId, limit: u64) -> Self {
96 Self {
97 error: Some(ObjectError {
98 code: 413,
99 message: format!(
100 "object is {} bytes, over the {limit} byte limit this server accepts",
101 id.size
102 ),
103 }),
104 id,
105 actions: None,
106 }
107 }
108
109 pub fn over_quota(id: ObjectId, used: u64, limit: u64) -> Self {
110 Self {
111 id,
112 actions: None,
113 error: Some(ObjectError {
114 code: 507,
115 message: format!(
116 "this repository holds {used} bytes of its {limit} byte budget — collect what \
117 it no longer references, or ask for more room"
118 ),
119 }),
120 }
121 }
122}
123
124#[derive(Debug, Deserialize)]
125pub struct CreateLockRequest {
126 pub path: String,
127}
128
129#[derive(Debug, Deserialize)]
130pub struct ListLocksQuery {
131 pub path: Option<String>,
132 pub id: Option<String>,
133}
134
135#[derive(Debug, Default, Deserialize)]
136pub struct VerifyLocksRequest {}
137
138#[derive(Debug, Deserialize)]
139pub struct UnlockRequest {
140 #[serde(default)]
141 pub force: bool,
142}
143
144#[derive(Debug, Serialize)]
145pub struct LockResponse {
146 pub lock: Lock,
147}
148
149#[derive(Debug, Serialize)]
150pub struct ListLocksResponse {
151 pub locks: Vec<Lock>,
152 pub next_cursor: &'static str,
153}
154
155#[derive(Debug, Serialize)]
156pub struct VerifyLocksResponse {
157 pub ours: Vec<Lock>,
158 pub theirs: Vec<Lock>,
159 pub next_cursor: &'static str,
160}
161
162#[derive(Debug, Serialize)]
163pub struct StatsResponse {
164 pub objects: u64,
165 pub bytes: u64,
166 pub locks: usize,
167}