opendal_core/raw/
rps.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use http::Request;
19
20use crate::*;
21
22/// Reply for `create_dir` operation
23#[derive(Debug, Clone, Default)]
24pub struct RpCreateDir {}
25
26/// Reply for `delete` operation
27#[derive(Debug, Clone, Default)]
28pub struct RpDelete {}
29
30/// Reply for `list` operation.
31#[derive(Debug, Clone, Default)]
32pub struct RpList {}
33
34/// Reply for `presign` operation.
35#[derive(Debug, Clone)]
36pub struct RpPresign {
37    req: PresignedRequest,
38}
39
40impl RpPresign {
41    /// Create a new reply for `presign`.
42    pub fn new(req: PresignedRequest) -> Self {
43        RpPresign { req }
44    }
45
46    /// Consume reply to build a presigned request.
47    pub fn into_presigned_request(self) -> PresignedRequest {
48        self.req
49    }
50}
51
52/// PresignedRequest is a presigned request return by `presign`.
53#[derive(Debug, Clone)]
54pub struct PresignedRequest {
55    method: http::Method,
56    uri: http::Uri,
57    headers: http::HeaderMap,
58}
59
60impl PresignedRequest {
61    /// Create a new PresignedRequest
62    pub fn new(method: http::Method, uri: http::Uri, headers: http::HeaderMap) -> Self {
63        Self {
64            method,
65            uri,
66            headers,
67        }
68    }
69
70    /// Return request's method.
71    pub fn method(&self) -> &http::Method {
72        &self.method
73    }
74
75    /// Return request's uri.
76    pub fn uri(&self) -> &http::Uri {
77        &self.uri
78    }
79
80    /// Return request's header.
81    pub fn header(&self) -> &http::HeaderMap {
82        &self.headers
83    }
84}
85
86impl<T: Default> From<PresignedRequest> for Request<T> {
87    fn from(v: PresignedRequest) -> Self {
88        let mut builder = Request::builder().method(v.method).uri(v.uri);
89
90        let headers = builder.headers_mut().expect("header map must be valid");
91        headers.extend(v.headers);
92
93        builder
94            .body(T::default())
95            .expect("request must build succeed")
96    }
97}
98
99/// Reply for `read` operation.
100///
101/// `RpRead` can carry metadata observed while opening this read operation.
102/// Services should set it only when the metadata is returned natively by the
103/// read operation. In particular, `metadata.content_length()` is the full
104/// object size, even if this read only returns a range of the object.
105#[derive(Debug, Clone, Default)]
106pub struct RpRead {
107    metadata: Option<Metadata>,
108}
109
110impl RpRead {
111    /// Create a new reply for `read`.
112    pub fn new(metadata: Metadata) -> Self {
113        Self {
114            metadata: Some(metadata),
115        }
116    }
117
118    /// Get metadata returned by this read operation.
119    pub fn metadata(&self) -> Option<&Metadata> {
120        self.metadata.as_ref()
121    }
122
123    /// Consume RpRead to get the inner metadata.
124    pub fn into_metadata(self) -> Option<Metadata> {
125        self.metadata
126    }
127}
128
129/// Reply for `stat` operation.
130#[derive(Debug, Clone)]
131pub struct RpStat {
132    meta: Metadata,
133}
134
135impl RpStat {
136    /// Create a new reply for `stat`.
137    pub fn new(meta: Metadata) -> Self {
138        RpStat { meta }
139    }
140
141    /// Operate on inner metadata.
142    pub fn map_metadata(mut self, f: impl FnOnce(Metadata) -> Metadata) -> Self {
143        self.meta = f(self.meta);
144        self
145    }
146
147    /// Consume RpStat to get the inner metadata.
148    pub fn into_metadata(self) -> Metadata {
149        self.meta
150    }
151}
152
153/// Reply for `write` operation.
154#[derive(Debug, Clone, Default)]
155pub struct RpWrite {}
156
157impl RpWrite {
158    /// Create a new reply for `write`.
159    pub fn new() -> Self {
160        Self {}
161    }
162}
163
164/// Reply for `copy` operation.
165#[derive(Debug, Clone, Default)]
166pub struct RpCopy {}
167
168impl RpCopy {
169    /// Create a new reply for `copy`.
170    pub fn new() -> Self {
171        Self {}
172    }
173}
174
175/// Reply for `rename` operation.
176#[derive(Debug, Clone, Default)]
177pub struct RpRename {}
178
179impl RpRename {
180    /// Create a new reply for `rename`.
181    pub fn new() -> Self {
182        Self {}
183    }
184}
185
186#[cfg(test)]
187mod tests {
188    use anyhow::Result;
189    use http::HeaderMap;
190    use http::Method;
191    use http::Uri;
192    use http::header::CONTENT_LENGTH;
193    use http::header::CONTENT_TYPE;
194
195    use super::*;
196
197    #[test]
198    fn test_presigned_request_convert() -> Result<()> {
199        let pr = PresignedRequest {
200            method: Method::PATCH,
201            uri: Uri::from_static("https://opendal.apache.org/path/to/file"),
202            headers: {
203                let mut headers = HeaderMap::new();
204                headers.insert(CONTENT_LENGTH, "123".parse()?);
205                headers.insert(CONTENT_TYPE, "application/json".parse()?);
206
207                headers
208            },
209        };
210
211        let req: Request<Buffer> = pr.into();
212        assert_eq!(Method::PATCH, req.method());
213        assert_eq!(
214            "https://opendal.apache.org/path/to/file",
215            req.uri().to_string()
216        );
217        assert_eq!("123", req.headers().get(CONTENT_LENGTH).unwrap());
218        assert_eq!("application/json", req.headers().get(CONTENT_TYPE).unwrap());
219
220        Ok(())
221    }
222}