modio/request/files/multipart/
add_multipart_upload_part.rs

1use std::fmt;
2use std::future::IntoFuture;
3
4use bytes::Bytes;
5use futures_util::TryStream;
6use http::header::CONTENT_RANGE;
7
8use crate::client::Client;
9use crate::request::{Output, RequestBuilder, Route};
10use crate::response::ResponseFuture;
11use crate::types::files::multipart::{UploadId, UploadPart};
12use crate::types::id::{GameId, ModId};
13
14pub struct AddMultipartUploadPart<'a, S> {
15    http: &'a Client,
16    game_id: GameId,
17    mod_id: ModId,
18    upload_id: UploadId,
19    range: ContentRange,
20    stream: S,
21}
22
23#[derive(Copy, Clone, Debug, PartialEq, Eq)]
24pub struct ContentRange {
25    pub start: u64,
26    pub end: u64,
27    pub total: u64,
28}
29
30impl<'a, S> AddMultipartUploadPart<'a, S> {
31    pub(crate) const fn new(
32        http: &'a Client,
33        game_id: GameId,
34        mod_id: ModId,
35        upload_id: UploadId,
36        range: ContentRange,
37        stream: S,
38    ) -> Self
39    where
40        S: TryStream + Send + 'static,
41        S::Ok: Into<Bytes>,
42        S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
43    {
44        Self {
45            http,
46            game_id,
47            mod_id,
48            upload_id,
49            range,
50            stream,
51        }
52    }
53}
54
55impl fmt::Display for ContentRange {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        write!(f, "bytes {}-{}/{}", self.start, self.end, self.total)
58    }
59}
60
61impl<S> IntoFuture for AddMultipartUploadPart<'_, S>
62where
63    S: TryStream + Send + 'static,
64    S::Ok: Into<Bytes>,
65    S::Error: Into<Box<dyn std::error::Error + Send + Sync>>,
66{
67    type Output = Output<UploadPart>;
68    type IntoFuture = ResponseFuture<UploadPart>;
69
70    fn into_future(self) -> Self::IntoFuture {
71        let route = Route::AddMultipartUploadPart {
72            game_id: self.game_id,
73            mod_id: self.mod_id,
74            upload_id: self.upload_id,
75        };
76
77        let range = self.range.to_string();
78        let builder = RequestBuilder::from_route(&route).header(CONTENT_RANGE, range);
79        match builder.stream(self.stream) {
80            Ok(req) => self.http.request(req),
81            Err(err) => ResponseFuture::failed(err),
82        }
83    }
84}