opendal/services/koofr/
writer.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 std::sync::Arc;
19
20use bytes::Buf;
21use http::StatusCode;
22
23use super::core::File;
24use super::core::KoofrCore;
25use super::error::parse_error;
26use crate::raw::*;
27use crate::*;
28
29pub type KoofrWriters = oio::OneShotWriter<KoofrWriter>;
30
31pub struct KoofrWriter {
32    core: Arc<KoofrCore>,
33    path: String,
34}
35
36impl KoofrWriter {
37    pub fn new(core: Arc<KoofrCore>, path: String) -> Self {
38        KoofrWriter { core, path }
39    }
40
41    fn parse_metadata(file: &File) -> Result<Metadata> {
42        let mode = if file.ty == "dir" {
43            EntryMode::DIR
44        } else {
45            EntryMode::FILE
46        };
47
48        let mut meta = Metadata::new(mode);
49        meta.set_content_length(file.size);
50        meta.set_content_type(&file.content_type);
51        meta.set_last_modified(Timestamp::from_millisecond(file.modified)?);
52
53        Ok(meta)
54    }
55}
56
57impl oio::OneShotWrite for KoofrWriter {
58    async fn write_once(&self, bs: Buffer) -> Result<Metadata> {
59        self.core.ensure_dir_exists(&self.path).await?;
60
61        let resp = self.core.put(&self.path, bs).await?;
62
63        let status = resp.status();
64
65        match status {
66            StatusCode::OK | StatusCode::CREATED => {
67                let body = resp.into_body();
68                let file: File =
69                    serde_json::from_reader(body.reader()).map_err(new_json_deserialize_error)?;
70                let metadata = Self::parse_metadata(&file)?;
71                Ok(metadata)
72            }
73            _ => Err(parse_error(resp)),
74        }
75    }
76}