1macro_rules! calculated_doc {
3 (
4 $(
5 #[doc = $doc:expr]
6 $thing:item
7 )*
8 ) => {
9 $(
10 #[doc = $doc]
11 $thing
12 )*
13 };
14}
15
16macro_rules! impl_api_ty {
17 ($(#[doc = $docs:expr])* $name:ident => $name_field:ident) => {
18 paste::item! {
19
20 calculated_doc!{
21 #[doc = concat!("Interface for accessing and manipulating Docker ", stringify!($name), ".\n", $($docs,)* "\n", api_url!($name))]
22 #[derive(Debug)]
23 pub struct [< $name >] {
24 docker: crate::Docker,
25 $name_field: crate::Id,
26 }
27 }
28 impl [< $name >] {
29 calculated_doc!{
31 #[doc = concat!("Exports an interface exposing operations against a ", stringify!($name), " instance.")]
32 pub fn new(docker: crate::Docker, $name_field: impl Into<crate::Id>) -> Self
33 {
34 [< $name >] {
35 docker,
36 $name_field: $name_field.into(),
37 }
38 }
39 }
40
41 calculated_doc!{
42 #[doc = concat!("A getter for ", stringify!($name), " ", stringify!($name_field))]
43 pub fn $name_field(&self) -> &crate::Id {
44 &self.$name_field
45 }
46 }
47
48
49 }
50
51
52 calculated_doc!{
53 #[doc = concat!("Interface for Docker ", stringify!($name), "s.", stringify!($name), ">")]
54 #[derive(Debug)]
55 pub struct [< $name s >] {
56 docker: crate::Docker,
57 }
58 }
59
60 impl [< $name s >] {
61 calculated_doc!{
62 #[doc = concat!("Exports an interface for interacting with Docker ", stringify!($name), "s.")]
63 pub fn new(docker: crate::Docker) -> Self {
64 [< $name s >] { docker }
65 }
66 }
67
68 calculated_doc!{
69 #[doc = concat!("Returns a reference to a set of operations available to a specific ", stringify!($name), ".")]
70 pub fn get(&self, $name_field: impl Into<crate::Id>) -> [< $name >]
71 {
72 [< $name >]::new(self.docker.clone(), $name_field)
73 }
74 }
75 }
76
77 }
78 }
79}
80
81macro_rules! api_url {
82 () => {
83 concat!("https://docs.docker.com/engine/api/", version!())
84 };
85 (operation $ep:expr) => {
86 concat!("\n[Api Reference](", api_url!(), "/#operation/", $ep, ")")
87 };
88 (tag $ep:expr) => {
89 concat!("\n[Api Reference](", api_url!(), "/#tag/", $ep, ")")
90 };
91 ($base:ident) => {
92 api_url!(tag stringify!($base))
93 };
94 ($base:ident => $op:ident) => {
95 api_url!(operation concat!(stringify!($base), stringify!($op)))
96 };
97}
98
99macro_rules! api_doc {
100 (
101 $base:ident => $op:ident
102 $(#[doc = $doc:expr])*
103 |
104 $it:item
105 ) => {
106 calculated_doc!{
107 #[doc = concat!(api_url!($base => $op))]
108 #[doc = "\n"]
109 $(
110 #[doc = $doc]
111 )*
112 $it
113 }
114 };
115 (
116 $base:ident
117 $(#[doc = $doc:expr])*
118 |
119 $it:item
120 ) => {
121 calculated_doc!{
122 #[doc = concat!(api_url!($base))]
123 #[doc = "\n"]
124 $(
125 #[doc = $doc]
126 )*
127 $it
128 }
129 };
130}
131
132macro_rules! impl_api_ep {
133 (
134 $it:ident: $base:ident, $resp:ident
135 $(
136 $op:ident -> $ep:expr, $ret:expr $(,$extra:expr)*
137 )*
138 ) => {
139 $(
140 impl_api_ep! {$op $it: $base -> $resp $ep, $ret $(,$extra)* }
141 )*
142 };
143 (
144 Inspect $it:ident: $base:ident -> $resp:ident $ep:expr, $ret:expr $(,$extra:expr)*
145 ) => {
146 paste::item! {
147 api_doc! { $base => Inspect
148 |
149 #[doc = concat!("Inspect this ", stringify!($base), ".")]
150 pub async fn inspect(&self) -> Result<$ret> {
151 let $it = self;
152 self.docker.get_json($ep).await
153 }}
154 }
155 };
156 (
157 ForceDelete $it:ident: $base:ident -> $resp:ident $ep:expr, $ret:expr $(,$extra:expr)*
158 ) => {
159
160 paste::item! {
161 async fn _delete(&self, force: bool) -> Result<$ret> {
162 let query = if force {
163 Some(containers_api::url::encoded_pair("force", force))
164 } else {
165 None
166 };
167
168 let $it = self;
169 let ep = containers_api::url::construct_ep($ep, query);
170
171 self.docker
172 .delete_json(ep.as_ref())
173 .await
174 }
175 }
176 paste::item! {
177 api_doc! { $base => Delete
178 |
179 #[doc = concat!("Delete this ", stringify!($base), ".")]
180 pub async fn force_delete(&self) -> Result<$ret> {
181 self._delete(true).await
182 }}
183 }
184 paste::item! {
185 api_doc! { $base => Delete
186 |
187 #[doc = concat!("Delete this ", stringify!($base), ".")]
188 pub async fn delete(&self) -> Result<$ret> {
189 self._delete(false).await
190 }}
191 }
192 };
193 (
194 Delete $it:ident: $base:ident -> $resp:ident $ep:expr, $ret:expr $(,$extra:expr)*
195 ) => {
196 paste::item! {
197 api_doc! { $base => Delete
198 |
199 #[doc = concat!("Delete this ", stringify!($base), ".")]
200 pub async fn delete(&self) -> Result<()> {
201 let $it = self;
202 self.docker.delete($ep).await.map(|_| ())
203 }}
204 }
205 };
206 (
207 DeleteWithOpts $it:ident: $base:ident -> $resp:ident $ep:expr, $ret:expr $(,$extra:expr)*
208 ) => {
209 impl_api_ep! { DeleteWithOpts $it: $base -> $resp $ep, $ret => $($extra)* }
210 };
211 (
212 DeleteWithOpts $it:ident: $base:ident -> $resp:ident $ep:expr, $ret:expr => $fn:expr
213 ) => {
214 paste::item! {
215 api_doc! { $base => Delete
216 |
217 #[doc = concat!("Delete this ", stringify!($base), ".")]
218 #[doc = concat!("Use [`delete`](", stringify!($base), "::delete) to delete without options.")]
219 pub async fn remove(&self, opts: &[< $base RemoveOpts >]) -> Result<$ret> {
220 let $it = self;
221 let ep = containers_api::url::construct_ep($ep, opts.serialize());
222 self.docker.$fn(ep.as_ref()).await
223 }}
224 }
225 paste::item! {
226 api_doc! { $base => Delete
227 |
228 #[doc = concat!("Delete this ", stringify!($base), ".")]
229 #[doc = concat!("Use [`remove`](", stringify!($base), "::remove) to customize options.")]
230 pub async fn delete(&self) -> Result<[< $ret >]> {
231 let $it = self;
232 self.docker.$fn($ep).await
233 }}
234 }
235 };
236 (
237 List $it:ident: $base:ident -> $resp:ident $ep:expr, $ret:expr $(, $extra:expr)*
238 ) => {
239 paste::item! {
240 api_doc! { $base => List
241 |
242 #[doc = concat!("List available ", stringify!($base), "s.")]
243 pub async fn list(&self, opts: &[< $base ListOpts >]) -> Result<Vec<$ret>> {
244 let ep = containers_api::url::construct_ep($ep, opts.serialize());
245 self.docker.get_json(&ep).await
246 }}
247 }
248 };
249 (
250 Create $it:ident: $base:ident -> $resp:ident $ep:expr, $ret:expr $(, $extra:expr)*
251 ) => {
252 paste::item! {
253 api_doc! { $base => Create
254 |
255 #[doc = concat!("Create a new ", stringify!($base), ".")]
256 pub async fn create(&self, opts: &[< $base CreateOpts >]) -> Result<[< $base >]> {
257 self.docker.post_json(&$ep, Payload::Json(opts.serialize_vec()?), Headers::none()).await
258 .map(|$resp: [< $ret >]| [< $base >]::new(self.docker.clone(), $($extra)*))
259 }}
260 }
261 };
262 (
263 Prune $it:ident: $base:ident -> $resp:ident $ep:expr, $ret:expr $(, $extra:expr)*
264 ) => {
265 paste::item! {
266 api_doc! { $base => Prune
267 |
268 #[doc = concat!("Delete stopped/unused ", stringify!($base), "s.")]
269 pub async fn prune(&self, opts: &[< $base PruneOpts >]) -> Result<$ret> {
270 self.docker
271 .post_json(
272 &containers_api::url::construct_ep($ep, opts.serialize()),
273 crate::conn::Payload::empty(),
274 crate::conn::Headers::none(),
275 ).await
276 }}
277 }
278 };
279 (
280 Logs $it:ident: $base:ident -> $resp:ident $ep:expr, $ret:expr $(, $extra:expr)*
281 ) => {
282 paste::item! {
283 api_doc! { $base => Logs
284 |
285 #[doc = concat!("Returns a stream of logs from a ", stringify!($base), ".")]
286 pub fn logs<'docker>(
287 &'docker self,
288 opts: &crate::opts::LogsOpts
289 ) -> impl futures_util::Stream<Item = crate::Result<containers_api::conn::TtyChunk>> + Unpin + 'docker {
290 use containers_api::conn::tty;
291 use futures_util::TryStreamExt;
292 let $it = self;
293 let ep = containers_api::url::construct_ep($ep, opts.serialize());
294
295 let stream = Box::pin(self.docker.get_stream(ep).map_err(|e| containers_api::conn::Error::Any(Box::new(e))));
296
297 Box::pin(tty::decode(stream).map_err(crate::Error::Error))
298 }
299 }}
300 };
301}