modio/util/download/info/
mod.rs1use std::fmt;
2use std::future::Future;
3use std::pin::Pin;
4use std::task::{ready, Context, Poll};
5
6use pin_project_lite::pin_project;
7use url::Url;
8
9use crate::types::files::File;
10use crate::types::id::FileId;
11use crate::Client;
12
13use super::{DownloadAction, Error};
14
15mod get_file;
16mod get_file_by_version;
17mod get_primary_file;
18
19use self::get_file::GetFile;
20use self::get_file_by_version::GetFileByVersion;
21use self::get_primary_file::GetPrimaryFile;
22
23#[non_exhaustive]
24pub struct Info {
25 pub file_id: FileId,
26 pub download_url: Url,
27 pub filesize: u64,
28 pub filesize_uncompressed: u64,
29 pub filehash: String,
30}
31
32impl fmt::Debug for Info {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 f.debug_struct("Info")
35 .field("file_id", &self.file_id)
36 .field("download_url", &self.download_url.as_str())
37 .field("filesize", &self.filesize)
38 .field("filesize_uncompressed", &self.filesize_uncompressed)
39 .field("filehash", &self.filehash)
40 .finish_non_exhaustive()
41 }
42}
43
44pin_project! {
45 pub struct GetInfo {
46 #[pin]
47 future: FileFuture,
48 }
49}
50
51pin_project! {
52 #[project = FileFutureProj]
53 enum FileFuture {
54 Primary {
55 #[pin]
56 future: GetPrimaryFile,
57 },
58 File {
59 #[pin]
60 future: GetFile,
61 },
62 FileObj {
63 file: Option<Box<File>>,
64 },
65 Version {
66 #[pin]
67 future: GetFileByVersion,
68 }
69 }
70}
71
72impl Future for FileFuture {
73 type Output = Result<File, Error>;
74
75 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
76 match self.project() {
77 FileFutureProj::Primary { future } => future.poll(cx),
78 FileFutureProj::File { future } => future.poll(cx),
79 FileFutureProj::FileObj { file } => {
80 Poll::Ready(Ok(*file.take().expect("polled after completion")))
81 }
82 FileFutureProj::Version { future } => future.poll(cx),
83 }
84 }
85}
86
87impl GetInfo {
88 pub(crate) fn new(http: &Client, action: DownloadAction) -> Self {
89 let future = match action {
90 DownloadAction::Primary { game_id, mod_id } => FileFuture::Primary {
91 future: GetPrimaryFile::new(http, game_id, mod_id),
92 },
93 DownloadAction::File {
94 game_id,
95 mod_id,
96 file_id,
97 } => FileFuture::File {
98 future: GetFile::new(http, game_id, mod_id, file_id),
99 },
100 DownloadAction::FileObj(file) => FileFuture::FileObj { file: Some(file) },
101 DownloadAction::Version {
102 game_id,
103 mod_id,
104 version,
105 policy,
106 } => FileFuture::Version {
107 future: GetFileByVersion::new(http, game_id, mod_id, version, policy),
108 },
109 };
110 Self { future }
111 }
112}
113
114impl Future for GetInfo {
115 type Output = Result<Info, Error>;
116
117 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
118 let file = ready!(self.project().future.poll(cx))?;
119
120 Poll::Ready(Ok(Info {
121 file_id: file.id,
122 download_url: file.download.binary_url,
123 filesize: file.filesize,
124 filesize_uncompressed: file.filesize_uncompressed,
125 filehash: file.filehash.md5,
126 }))
127 }
128}
129
130pub fn download_info(http: &Client, action: DownloadAction) -> GetInfo {
131 GetInfo::new(http, action)
132}