digitalocean_api/api/
mod.rs1mod account;
4mod action;
5mod certificate;
6mod custom_image;
7mod domain;
8mod domain_record;
9mod droplet;
10mod droplet_action;
11mod floating_ip;
12mod floating_ip_action;
13mod image;
14mod image_action;
15mod load_balancer;
16mod region;
17mod size;
18mod snapshot;
19mod ssh_key;
20mod tag;
21mod volume;
22mod volume_action;
23
24use serde::de::DeserializeOwned;
25use serde::{Deserialize, Serialize};
26use url::Url;
27
28mod url_option_serde {
29 use serde::{Deserialize, Deserializer, Serializer};
30 use url::Url;
31
32 pub fn serialize<S>(url: &Option<Url>, serializer: S) -> Result<S::Ok, S::Error>
33 where
34 S: Serializer,
35 {
36 match url {
37 Some(url) => serializer.serialize_some(&url.to_string()),
38 None => serializer.serialize_none(),
39 }
40 }
41
42 pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<Url>, D::Error>
43 where
44 D: Deserializer<'de>,
45 {
46 let url_str: Option<String> = Option::deserialize(deserializer)?;
47 match url_str {
48 Some(s) => {
49 let url = Url::parse(&s).map_err(serde::de::Error::custom)?;
50 Ok(Some(url))
51 }
52 None => Ok(None),
53 }
54 }
55}
56
57pub use self::account::Account;
58pub use self::action::Action;
59pub use self::certificate::Certificate;
60pub use self::custom_image::CustomImage;
61pub use self::domain::Domain;
62pub use self::domain_record::DomainRecord;
63pub use self::droplet::{droplet_fields, Droplet};
64pub use self::floating_ip::FloatingIp;
65pub use self::image::Image;
66pub use self::load_balancer::{load_balancer_fields, LoadBalancer};
67pub use self::region::Region;
68pub use self::size::Size;
69pub use self::snapshot::Snapshot;
70pub use self::ssh_key::SshKey;
71pub use self::tag::Tag;
72pub use self::volume::Volume;
73
74pub const MAX_PER_PAGE: usize = 200;
76
77#[derive(Deserialize, Serialize, Debug, Clone)]
78struct ApiLinks {
79 pages: Option<ApiPages>,
80}
81
82impl ApiLinks {
83 fn next(&self) -> Option<Url> {
84 match self.pages {
85 Some(ref pages) => pages.next.clone(),
86 None => None,
87 }
88 }
89}
90
91#[derive(Deserialize, Serialize, Debug, Clone)]
92struct ApiPages {
93 #[serde(with = "url_option_serde", default)]
94 prev: Option<Url>,
95
96 #[serde(with = "url_option_serde", default)]
97 first: Option<Url>,
98
99 #[serde(with = "url_option_serde", default)]
100 next: Option<Url>,
101
102 #[serde(with = "url_option_serde", default)]
103 last: Option<Url>,
104}
105
106#[derive(Deserialize, Serialize, Debug, Clone)]
107struct ApiMeta {
108 total: usize,
109}
110
111pub trait HasPagination {
112 fn next_page(&self) -> Option<Url>;
113}
114
115pub trait HasValue {
116 type Value: DeserializeOwned;
117 fn value(self) -> Self::Value;
118}
119
120impl HasValue for () {
121 type Value = ();
122
123 fn value(self) -> Self::Value {}
124}
125
126pub trait HasResponse: DeserializeOwned + Clone {
127 type Response: DeserializeOwned + Clone + HasValue<Value = Self>;
128}
129
130impl HasResponse for () {
131 type Response = ();
132}