opendal/services/gdrive/
backend.rs1use std::fmt::Debug;
19use std::sync::Arc;
20
21use bytes::Buf;
22use chrono::Utc;
23use http::Response;
24use http::StatusCode;
25
26use super::core::GdriveCore;
27use super::core::GdriveFile;
28use super::delete::GdriveDeleter;
29use super::error::parse_error;
30use super::lister::GdriveLister;
31use super::writer::GdriveWriter;
32use crate::raw::*;
33use crate::*;
34
35#[derive(Clone, Debug)]
36pub struct GdriveBackend {
37 pub core: Arc<GdriveCore>,
38}
39
40impl Access for GdriveBackend {
41 type Reader = HttpBody;
42 type Writer = oio::OneShotWriter<GdriveWriter>;
43 type Lister = oio::PageLister<GdriveLister>;
44 type Deleter = oio::OneShotDeleter<GdriveDeleter>;
45 type BlockingReader = ();
46 type BlockingWriter = ();
47 type BlockingLister = ();
48 type BlockingDeleter = ();
49
50 fn info(&self) -> Arc<AccessorInfo> {
51 self.core.info.clone()
52 }
53
54 async fn create_dir(&self, path: &str, _args: OpCreateDir) -> Result<RpCreateDir> {
55 let path = build_abs_path(&self.core.root, path);
56 let _ = self.core.path_cache.ensure_dir(&path).await?;
57
58 Ok(RpCreateDir::default())
59 }
60
61 async fn stat(&self, path: &str, _args: OpStat) -> Result<RpStat> {
62 let resp = self.core.gdrive_stat(path).await?;
63
64 if resp.status() != StatusCode::OK {
65 return Err(parse_error(resp));
66 }
67
68 let bs = resp.into_body();
69 let gdrive_file: GdriveFile =
70 serde_json::from_reader(bs.reader()).map_err(new_json_deserialize_error)?;
71
72 let file_type = if gdrive_file.mime_type == "application/vnd.google-apps.folder" {
73 EntryMode::DIR
74 } else {
75 EntryMode::FILE
76 };
77 let mut meta = Metadata::new(file_type).with_content_type(gdrive_file.mime_type);
78 if let Some(v) = gdrive_file.size {
79 meta = meta.with_content_length(v.parse::<u64>().map_err(|e| {
80 Error::new(ErrorKind::Unexpected, "parse content length").set_source(e)
81 })?);
82 }
83 if let Some(v) = gdrive_file.modified_time {
84 meta = meta.with_last_modified(v.parse::<chrono::DateTime<Utc>>().map_err(|e| {
85 Error::new(ErrorKind::Unexpected, "parse last modified time").set_source(e)
86 })?);
87 }
88 Ok(RpStat::new(meta))
89 }
90
91 async fn read(&self, path: &str, args: OpRead) -> Result<(RpRead, Self::Reader)> {
92 let resp = self.core.gdrive_get(path, args.range()).await?;
93
94 let status = resp.status();
95 match status {
96 StatusCode::OK | StatusCode::PARTIAL_CONTENT => Ok((RpRead::new(), resp.into_body())),
97 _ => {
98 let (part, mut body) = resp.into_parts();
99 let buf = body.to_buffer().await?;
100 Err(parse_error(Response::from_parts(part, buf)))
101 }
102 }
103 }
104
105 async fn write(&self, path: &str, _: OpWrite) -> Result<(RpWrite, Self::Writer)> {
106 let path = build_abs_path(&self.core.root, path);
107
108 let file_id = self.core.path_cache.get(&path).await?;
111
112 Ok((
113 RpWrite::default(),
114 oio::OneShotWriter::new(GdriveWriter::new(self.core.clone(), path, file_id)),
115 ))
116 }
117
118 async fn delete(&self) -> Result<(RpDelete, Self::Deleter)> {
119 Ok((
120 RpDelete::default(),
121 oio::OneShotDeleter::new(GdriveDeleter::new(self.core.clone())),
122 ))
123 }
124
125 async fn list(&self, path: &str, _args: OpList) -> Result<(RpList, Self::Lister)> {
126 let path = build_abs_path(&self.core.root, path);
127 let l = GdriveLister::new(path, self.core.clone());
128 Ok((RpList::default(), oio::PageLister::new(l)))
129 }
130
131 async fn copy(&self, from: &str, to: &str, _args: OpCopy) -> Result<RpCopy> {
132 let resp = self.core.gdrive_copy(from, to).await?;
133
134 match resp.status() {
135 StatusCode::OK => Ok(RpCopy::default()),
136 _ => Err(parse_error(resp)),
137 }
138 }
139
140 async fn rename(&self, from: &str, to: &str, _args: OpRename) -> Result<RpRename> {
141 let source = build_abs_path(&self.core.root, from);
142 let target = build_abs_path(&self.core.root, to);
143
144 if let Some(id) = self.core.path_cache.get(&target).await? {
146 let resp = self.core.gdrive_trash(&id).await?;
147 let status = resp.status();
148 if status != StatusCode::OK {
149 return Err(parse_error(resp));
150 }
151
152 self.core.path_cache.remove(&target).await;
153 }
154
155 let resp = self
156 .core
157 .gdrive_patch_metadata_request(&source, &target)
158 .await?;
159
160 let status = resp.status();
161
162 match status {
163 StatusCode::OK => {
164 let body = resp.into_body();
165 let meta: GdriveFile =
166 serde_json::from_reader(body.reader()).map_err(new_json_deserialize_error)?;
167
168 let cache = &self.core.path_cache;
169
170 cache.remove(&build_abs_path(&self.core.root, from)).await;
171 cache
172 .insert(&build_abs_path(&self.core.root, to), &meta.id)
173 .await;
174
175 Ok(RpRename::default())
176 }
177 _ => Err(parse_error(resp)),
178 }
179 }
180}