modio/request/mods/metadata/
add_mod_metadata.rs1use std::collections::BTreeMap;
2use std::future::IntoFuture;
3
4use crate::client::Client;
5use crate::request::{ArrayParams, Output, RequestBuilder, Route};
6use crate::response::ResponseFuture;
7use crate::types::id::{GameId, ModId};
8use crate::types::mods::MetadataMap;
9use crate::types::Message;
10
11pub struct AddModMetadata<'a> {
13 http: &'a Client,
14 game_id: GameId,
15 mod_id: ModId,
16 fields: AddModMetadataFields,
17}
18
19struct AddModMetadataFields {
20 metadata: MetadataMap,
21}
22
23impl AddModMetadataFields {
24 fn flatten(&self) -> Vec<String> {
25 let sorted = self.metadata.iter().collect::<BTreeMap<_, _>>();
26 let mut metadata = Vec::new();
27 for (key, values) in sorted {
28 for value in values {
29 let mut v = key.clone();
30 v.push(':');
31 v.push_str(value);
32 metadata.push(v);
33 }
34 }
35 metadata
36 }
37}
38
39impl<'a> AddModMetadata<'a> {
40 pub(crate) const fn new(
41 http: &'a Client,
42 game_id: GameId,
43 mod_id: ModId,
44 metadata: MetadataMap,
45 ) -> Self {
46 Self {
47 http,
48 game_id,
49 mod_id,
50 fields: AddModMetadataFields { metadata },
51 }
52 }
53}
54
55impl IntoFuture for AddModMetadata<'_> {
56 type Output = Output<Message>;
57 type IntoFuture = ResponseFuture<Message>;
58
59 fn into_future(self) -> Self::IntoFuture {
60 let route = Route::AddModMetadata {
61 game_id: self.game_id,
62 mod_id: self.mod_id,
63 };
64 let metadata = self.fields.flatten();
65 let form = ArrayParams::new("metadata[]", &metadata);
66 match RequestBuilder::from_route(&route).form(&form) {
67 Ok(req) => self.http.request(req),
68 Err(err) => ResponseFuture::failed(err),
69 }
70 }
71}
72
73#[cfg(test)]
74mod tests {
75 use serde_test::{assert_ser_tokens, Token};
76
77 use super::{AddModMetadataFields, ArrayParams, MetadataMap};
78
79 #[test]
80 pub fn serialize_fields() {
81 let mut metadata = MetadataMap::new();
82 metadata.insert(
83 String::from("aaa"),
84 vec![String::from("bbb"), String::from("ccc")],
85 );
86 metadata.insert(
87 String::from("ddd"),
88 vec![String::from("eee"), String::from("fff")],
89 );
90 let fields = AddModMetadataFields { metadata };
91 let flatten = fields.flatten();
92 let params = ArrayParams::new("metadata[]", &flatten);
93
94 assert_ser_tokens(
95 ¶ms,
96 &[
97 Token::Map { len: Some(4) },
98 Token::Str("metadata[]"),
99 Token::Str("aaa:bbb"),
100 Token::Str("metadata[]"),
101 Token::Str("aaa:ccc"),
102 Token::Str("metadata[]"),
103 Token::Str("ddd:eee"),
104 Token::Str("metadata[]"),
105 Token::Str("ddd:fff"),
106 Token::MapEnd,
107 ],
108 );
109
110 let qs = serde_urlencoded::to_string(¶ms).unwrap();
111 assert_eq!(
112 "metadata%5B%5D=aaa%3Abbb&metadata%5B%5D=aaa%3Accc&metadata%5B%5D=ddd%3Aeee&metadata%5B%5D=ddd%3Afff",
113 qs
114 );
115 }
116}