1use bytes::Bytes;
4use reqwest::Method;
5use serde::Deserialize;
6
7use crate::api::{
8 DownloadOptions, RedundantUploadOptions, UploadResult, prepare_download_headers,
9 prepare_redundant_upload_headers,
10};
11use crate::client::{Inner, request};
12use crate::swarm::{BatchId, Error, Reference};
13
14use super::FileApi;
15
16#[derive(Clone, Debug, PartialEq, Eq)]
19pub struct ReferenceInformation {
20 pub content_length: u64,
22}
23
24#[derive(Deserialize)]
25struct UploadBody {
26 reference: String,
27}
28
29impl FileApi {
30 pub async fn upload_data(
35 &self,
36 batch_id: &BatchId,
37 data: impl Into<Bytes>,
38 opts: Option<&RedundantUploadOptions>,
39 ) -> Result<UploadResult, Error> {
40 let builder = request(&self.inner, Method::POST, "bytes")?
41 .header("Content-Type", "application/octet-stream")
42 .body(data.into());
43 let builder =
44 Inner::apply_headers(builder, prepare_redundant_upload_headers(batch_id, opts));
45 let resp = self.inner.send(builder).await?;
46 let headers = resp.headers().clone();
47 let body: UploadBody = serde_json::from_slice(&resp.bytes().await?)?;
48 UploadResult::from_response(&body.reference, &headers)
49 }
50
51 pub async fn download_data(
55 &self,
56 reference: &Reference,
57 opts: Option<&DownloadOptions>,
58 ) -> Result<Bytes, Error> {
59 let resp = self.download_data_response(reference, opts).await?;
60 Ok(resp.bytes().await?)
61 }
62
63 pub async fn download_data_response(
67 &self,
68 reference: &Reference,
69 opts: Option<&DownloadOptions>,
70 ) -> Result<reqwest::Response, Error> {
71 let path = format!("bytes/{}", reference.to_hex());
72 let builder = request(&self.inner, Method::GET, &path)?;
73 let builder = Inner::apply_headers(builder, prepare_download_headers(opts));
74 self.inner.send(builder).await
75 }
76
77 pub async fn probe_data(&self, reference: &Reference) -> Result<ReferenceInformation, Error> {
80 let path = format!("bytes/{}", reference.to_hex());
81 let builder = request(&self.inner, Method::HEAD, &path)?;
82 let resp = self.inner.send(builder).await?;
83 let content_length = resp
84 .headers()
85 .get(reqwest::header::CONTENT_LENGTH)
86 .and_then(|v| v.to_str().ok())
87 .and_then(|s| s.parse::<u64>().ok())
88 .or_else(|| resp.content_length())
89 .ok_or_else(|| Error::argument("missing Content-Length"))?;
90 Ok(ReferenceInformation { content_length })
91 }
92}