modio/util/
data_from_request.rs1use std::fmt;
2use std::future::{Future, IntoFuture};
3use std::pin::Pin;
4use std::task::{ready, Context, Poll};
5
6use futures_util::future::Either;
7use serde::de::DeserializeOwned;
8
9use crate::response::{self, BodyError, ResponseFuture};
10use crate::Error;
11
12pub trait DataFromRequest<T: DeserializeOwned + Unpin>: private::Sealed {
17 fn data(self) -> DataFuture<T>;
35}
36
37#[derive(Debug)]
39pub enum DataError {
40 Request(Error),
41 Body(BodyError),
42}
43
44impl fmt::Display for DataError {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 match self {
47 Self::Request(err) => err.fmt(f),
48 Self::Body(err) => err.fmt(f),
49 }
50 }
51}
52
53impl std::error::Error for DataError {}
54
55pin_project_lite::pin_project! {
56 pub struct DataFuture<T> where T: Unpin {
58 #[pin]
59 future: Either<ResponseFuture<T>, response::DataFuture<T>>,
60 }
61}
62
63impl<Builder, Data> DataFromRequest<Data> for Builder
64where
65 Builder: IntoFuture<IntoFuture = ResponseFuture<Data>> + private::Sealed,
66 Data: DeserializeOwned + Unpin,
67{
68 fn data(self) -> DataFuture<Data> {
69 DataFuture {
70 future: Either::Left(self.into_future()),
71 }
72 }
73}
74
75impl<T: DeserializeOwned + Unpin> Future for DataFuture<T> {
76 type Output = Result<T, DataError>;
77
78 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
79 let mut this = self.project();
80 loop {
81 match this.future.as_mut().as_pin_mut() {
82 Either::Left(fut) => {
83 let resp = ready!(fut.poll(cx).map_err(DataError::Request))?;
84 this.future.set(Either::Right(resp.data()));
85 }
86 Either::Right(fut) => {
87 return fut.poll(cx).map_err(DataError::Body);
88 }
89 }
90 }
91 }
92}
93
94mod private {
95 use crate::request::{auth, files, games, mods, user};
96
97 pub trait Sealed {}
98
99 impl Sealed for auth::EmailRequest<'_> {}
100 impl Sealed for auth::EmailExchange<'_> {}
101 impl<T> Sealed for auth::ExternalAuth<'_, T> {}
102 impl Sealed for auth::GetTerms<'_> {}
103
104 impl Sealed for games::AddGameMedia<'_> {}
105 impl Sealed for games::GetGame<'_> {}
106 impl Sealed for games::GetGameStats<'_> {}
107 impl Sealed for games::GetGames<'_> {}
108 impl Sealed for games::tags::AddGameTags<'_> {}
109 impl Sealed for games::tags::GetGameTags<'_> {}
110 impl Sealed for games::tags::RenameGameTag<'_> {}
111
112 impl Sealed for mods::AddMod<'_> {}
113 impl Sealed for mods::EditMod<'_> {}
114 impl Sealed for mods::GetMod<'_> {}
115 impl Sealed for mods::GetModTeamMembers<'_> {}
116 impl Sealed for mods::GetMods<'_> {}
117 impl Sealed for mods::SubmitModRating<'_> {}
118 impl Sealed for mods::comments::AddModComment<'_> {}
119 impl Sealed for mods::comments::EditModComment<'_> {}
120 impl Sealed for mods::comments::GetModComment<'_> {}
121 impl Sealed for mods::comments::GetModComments<'_> {}
122 impl Sealed for mods::comments::UpdateModCommentKarma<'_> {}
123 impl Sealed for mods::dependencies::AddModDependencies<'_> {}
124 impl Sealed for mods::dependencies::GetModDependencies<'_> {}
125 impl Sealed for mods::events::GetModEvents<'_> {}
126 impl Sealed for mods::events::GetModsEvents<'_> {}
127 impl Sealed for mods::media::AddModMedia<'_> {}
128 impl Sealed for mods::metadata::AddModMetadata<'_> {}
129 impl Sealed for mods::metadata::GetModMetadata<'_> {}
130 impl Sealed for mods::stats::GetModStats<'_> {}
131 impl Sealed for mods::stats::GetModsStats<'_> {}
132 impl Sealed for mods::subscribe::SubscribeToMod<'_> {}
133 impl Sealed for mods::tags::AddModTags<'_> {}
134 impl Sealed for mods::tags::GetModTags<'_> {}
135
136 impl Sealed for files::AddFile<'_> {}
137 impl Sealed for files::EditFile<'_> {}
138 impl Sealed for files::GetFile<'_> {}
139 impl Sealed for files::GetFiles<'_> {}
140 impl Sealed for files::ManagePlatformStatus<'_> {}
141 impl Sealed for files::multipart::AddMultipartUploadFile<'_> {}
142 impl<S> Sealed for files::multipart::AddMultipartUploadPart<'_, S> {}
143 impl Sealed for files::multipart::CompleteMultipartUploadSession<'_> {}
144 impl Sealed for files::multipart::CreateMultipartUploadSession<'_> {}
145 impl Sealed for files::multipart::GetMultipartUploadParts<'_> {}
146 impl Sealed for files::multipart::GetMultipartUploadSessions<'_> {}
147
148 impl Sealed for user::GetAuthenticatedUser<'_> {}
149 impl Sealed for user::GetMutedUsers<'_> {}
150 impl Sealed for user::GetUserEvents<'_> {}
151 impl Sealed for user::GetUserFiles<'_> {}
152 impl Sealed for user::GetUserGames<'_> {}
153 impl Sealed for user::GetUserMods<'_> {}
154 impl Sealed for user::GetUserRatings<'_> {}
155 impl Sealed for user::GetUserSubscriptions<'_> {}
156}