1use reqwest::Method;
4
5use crate::error::{Error, Result};
6use crate::sandbox::SandboxCalls;
7
8pub struct Files {
10 calls: SandboxCalls,
11}
12
13impl Files {
14 pub(crate) fn new(calls: SandboxCalls) -> Self {
15 Self { calls }
16 }
17
18 pub async fn write(&self, path: &str, data: impl Into<Vec<u8>>) -> Result<()> {
21 self.put(path, data.into(), None).await
22 }
23
24 pub async fn write_with_mode(
27 &self,
28 path: &str,
29 data: impl Into<Vec<u8>>,
30 mode: u32,
31 ) -> Result<()> {
32 self.put(path, data.into(), Some(mode)).await
33 }
34
35 pub async fn read(&self, path: &str) -> Result<Vec<u8>> {
37 let calls = &self.calls;
38 let query = [("path", path.to_owned())];
39 let files = format!("{}/files", calls.path);
40 calls
41 .while_live(calls.client.bytes(Method::GET, &files, &query, None))
42 .await
43 }
44
45 pub async fn read_text(&self, path: &str) -> Result<String> {
47 String::from_utf8(self.read(path).await?)
48 .map_err(|_| Error::Unexpected(format!("{path} isn't UTF-8")))
49 }
50
51 async fn put(&self, path: &str, data: Vec<u8>, mode: Option<u32>) -> Result<()> {
52 let calls = &self.calls;
53 let mut query = vec![("path", path.to_owned())];
54 if let Some(mode) = mode {
55 query.push(("mode", format!("{mode:o}")));
56 }
57 let files = format!("{}/files", calls.path);
58 calls
59 .while_live(calls.client.bytes(Method::PUT, &files, &query, Some(data)))
60 .await
61 .map(drop)
62 }
63}