pact_ffi/models/
iterators.rs

1//! FFI wrapper code for iterating over Pact interactions
2
3use std::panic::RefUnwindSafe;
4
5use tracing::trace;
6
7use pact_models::message::Message;
8use pact_models::message_pact::MessagePact;
9use pact_models::v4::pact::V4Pact;
10use pact_models::v4::async_message::AsynchronousMessage;
11use pact_models::v4::sync_message::SynchronousMessage;
12use pact_models::v4::synch_http::SynchronousHttp;
13use pact_models::v4::V4InteractionType;
14
15use crate::{as_mut, ffi_fn};
16use crate::models::PactInteraction;
17use crate::ptr;
18
19ffi_fn! {
20    /// Free the iterator when you're done using it.
21    fn pactffi_pact_message_iter_delete(iter: *mut PactMessageIterator) {
22        ptr::drop_raw(iter);
23    }
24}
25
26/// An iterator over messages in a pact.
27#[derive(Debug)]
28#[allow(missing_copy_implementations)]
29pub struct PactMessageIterator {
30  current: usize,
31  message_pact: MessagePact,
32}
33
34impl PactMessageIterator {
35  /// Create a new iterator given a message pact
36  pub fn new(message_pact: MessagePact) -> Self {
37    PactMessageIterator {
38      current: 0,
39      message_pact
40    }
41  }
42
43  /// Get the next message in the message pact.
44  fn next(&mut self) -> Option<&mut Message> {
45    let idx = self.current;
46    self.current += 1;
47    self.message_pact.messages.get_mut(idx)
48  }
49}
50
51ffi_fn! {
52    /// Get the next message from the message pact. As the messages returned are owned by the
53    /// iterator, they do not need to be deleted but will be cleaned up when the iterator is
54    /// deleted.
55    ///
56    /// Will return a NULL pointer when the iterator has advanced past the end of the list.
57    ///
58    /// # Safety
59    ///
60    /// This function is safe.
61    ///
62    /// Deleting a message returned by the iterator can lead to undefined behaviour.
63    ///
64    /// # Error Handling
65    ///
66    /// This function will return a NULL pointer if passed a NULL pointer or if an error occurs.
67    fn pactffi_pact_message_iter_next(iter: *mut PactMessageIterator) -> *mut Message {
68        let iter = as_mut!(iter);
69        match iter.next() {
70          Some(message) => message as *mut Message,
71          None => {
72            trace!("iter past the end of messages");
73            std::ptr::null_mut()
74          }
75      }
76    } {
77        std::ptr::null_mut()
78    }
79}
80
81/// An iterator over asynchronous messages in a V4 pact.
82#[derive(Debug)]
83#[allow(missing_copy_implementations)]
84pub struct PactAsyncMessageIterator {
85  current: usize,
86  messages: Vec<AsynchronousMessage>
87}
88
89impl PactAsyncMessageIterator {
90  /// Create a new iterator over all asynchronous messages in the pact
91  pub fn new(pact: V4Pact) -> Self {
92    PactAsyncMessageIterator {
93      current: 0,
94      messages: pact.filter_interactions(V4InteractionType::Asynchronous_Messages)
95        .iter()
96        .map(|i| i.as_v4_async_message().unwrap())
97        .collect()
98    }
99  }
100
101  /// Get the next message in the pact.
102  fn next(&mut self) -> Option<&mut AsynchronousMessage> {
103    let idx = self.current;
104    self.current += 1;
105    self.messages.get_mut(idx)
106  }
107}
108
109ffi_fn! {
110    /// Get the next asynchronous from the V4 pact. As the messages returned are
111    /// owned by the iterator, they do not need to be deleted but will be
112    /// cleaned up when the iterator is deleted.
113    ///
114    /// Will return a NULL pointer when the iterator has advanced past the end
115    /// of the list.
116    ///
117    /// # Safety
118    ///
119    /// This function is safe.
120    ///
121    /// Deleting a message returned by the iterator can lead to undefined
122    /// behaviour.
123    ///
124    /// # Error Handling
125    ///
126    /// This function will return a NULL pointer if passed a NULL pointer or if
127    /// an error occurs.
128    fn pactffi_pact_async_message_iter_next(iter: *mut PactAsyncMessageIterator) -> *mut AsynchronousMessage {
129        let iter = as_mut!(iter);
130        match iter.next() {
131          Some(message) => message as *mut AsynchronousMessage,
132          None => {
133            trace!("iter past the end of messages");
134            std::ptr::null_mut()
135          }
136      }
137    } {
138        std::ptr::null_mut()
139    }
140}
141
142ffi_fn! {
143    /// Free the iterator when you're done using it.
144    fn pactffi_pact_async_message_iter_delete(iter: *mut PactAsyncMessageIterator) {
145        ptr::drop_raw(iter);
146    }
147}
148
149/// An iterator over synchronous request/response messages in a V4 pact.
150#[derive(Debug)]
151#[allow(missing_copy_implementations)]
152pub struct PactSyncMessageIterator {
153  current: usize,
154  messages: Vec<SynchronousMessage>
155}
156
157impl PactSyncMessageIterator {
158  /// Create a new iterator over all synchronous request/response messages in the pact
159  pub fn new(pact: V4Pact) -> Self {
160    PactSyncMessageIterator {
161      current: 0,
162      messages: pact.filter_interactions(V4InteractionType::Synchronous_Messages)
163        .iter()
164        .map(|i| i.as_v4_sync_message().unwrap())
165        .collect()
166    }
167  }
168
169  /// Get the next message in the pact.
170  fn next(&mut self) -> Option<&mut SynchronousMessage> {
171    let idx = self.current;
172    self.current += 1;
173    self.messages.get_mut(idx)
174  }
175}
176
177ffi_fn! {
178    /// Get the next synchronous request/response message from the V4 pact. As the messages returned are owned by the
179    /// iterator, they do not need to be deleted but will be cleaned up when the iterator is
180    /// deleted.
181    ///
182    /// Will return a NULL pointer when the iterator has advanced past the end of the list.
183    ///
184    /// # Safety
185    ///
186    /// This function is safe.
187    ///
188    /// Deleting a message returned by the iterator can lead to undefined behaviour.
189    ///
190    /// # Error Handling
191    ///
192    /// This function will return a NULL pointer if passed a NULL pointer or if an error occurs.
193    fn pactffi_pact_sync_message_iter_next(iter: *mut PactSyncMessageIterator) -> *mut SynchronousMessage {
194        let iter = as_mut!(iter);
195        match iter.next() {
196          Some(message) => message as *mut SynchronousMessage,
197          None => {
198            trace!("iter past the end of messages");
199            std::ptr::null_mut()
200          }
201      }
202    } {
203        std::ptr::null_mut()
204    }
205}
206
207ffi_fn! {
208    /// Free the iterator when you're done using it.
209    fn pactffi_pact_sync_message_iter_delete(iter: *mut PactSyncMessageIterator) {
210        ptr::drop_raw(iter);
211    }
212}
213
214/// An iterator over synchronous HTTP request/response interactions in a V4 pact.
215#[derive(Debug)]
216#[allow(missing_copy_implementations)]
217pub struct PactSyncHttpIterator {
218  current: usize,
219  interactions: Vec<SynchronousHttp>
220}
221
222impl PactSyncHttpIterator {
223  /// Create a new iterator over all synchronous HTTP request/response interactions in the V4 pact
224  pub fn new(pact: V4Pact) -> Self {
225    PactSyncHttpIterator {
226      current: 0,
227      interactions: pact.filter_interactions(V4InteractionType::Synchronous_HTTP)
228        .iter()
229        .map(|i| i.as_v4_http().unwrap())
230        .collect()
231    }
232  }
233
234  /// Get the next interaction in the pact.
235  fn next(&mut self) -> Option<&mut SynchronousHttp> {
236    let idx = self.current;
237    self.current += 1;
238    self.interactions.get_mut(idx)
239  }
240}
241
242ffi_fn! {
243    /// Get the next synchronous HTTP request/response interaction from the V4 pact. As the
244    /// interactions returned are owned by the iterator, they do not need to be deleted but
245    /// will be cleaned up when the iterator is deleted.
246    ///
247    /// Will return a NULL pointer when the iterator has advanced past the end of the list.
248    ///
249    /// # Safety
250    ///
251    /// This function is safe.
252    ///
253    /// Deleting an interaction returned by the iterator can lead to undefined behaviour.
254    ///
255    /// # Error Handling
256    ///
257    /// This function will return a NULL pointer if passed a NULL pointer or if an error occurs.
258    fn pactffi_pact_sync_http_iter_next(iter: *mut PactSyncHttpIterator) -> *mut SynchronousHttp {
259        let iter = as_mut!(iter);
260        match iter.next() {
261          Some(interaction) => interaction as *mut SynchronousHttp,
262          None => {
263            trace!("iter past the end of the list");
264            std::ptr::null_mut()
265          }
266        }
267    } {
268        std::ptr::null_mut()
269    }
270}
271
272ffi_fn! {
273    /// Free the iterator when you're done using it.
274    fn pactffi_pact_sync_http_iter_delete(iter: *mut PactSyncHttpIterator) {
275        ptr::drop_raw(iter);
276    }
277}
278
279/// An iterator over the interactions in a pact.
280#[derive(Debug)]
281#[allow(missing_copy_implementations)]
282pub struct PactInteractionIterator {
283  current: usize,
284  interactions: Vec<PactInteraction>
285}
286
287impl PactInteractionIterator {
288  /// Create a new iterator over all the interactions in the pact
289  pub fn new(pact: Box<dyn pact_models::pact::Pact + Send + Sync + RefUnwindSafe>) -> Self {
290    PactInteractionIterator {
291      current: 0,
292      interactions: pact.interactions().iter()
293        .map(|i| PactInteraction::new(i))
294        .collect()
295    }
296  }
297
298  /// Get the next interaction in the pact.
299  fn next(&mut self) -> Option<&PactInteraction> {
300    let idx = self.current;
301    self.current += 1;
302    self.interactions.get(idx)
303  }
304}
305
306ffi_fn! {
307    /// Get the next interaction from the pact. As the interactions returned are owned by the
308    /// iterator, they do not need to be deleted but will be cleaned up when the iterator is
309    /// deleted.
310    ///
311    /// Will return a NULL pointer when the iterator has advanced past the end of the list.
312    ///
313    /// # Safety
314    ///
315    /// This function is safe.
316    ///
317    /// Deleting an interaction returned by the iterator can lead to undefined behaviour.
318    ///
319    /// # Error Handling
320    ///
321    /// This function will return a NULL pointer if passed a NULL pointer or if an error occurs.
322    fn pactffi_pact_interaction_iter_next(iter: *mut PactInteractionIterator) -> *const PactInteraction {
323        let iter = as_mut!(iter);
324        match iter.next() {
325          Some(interaction) => interaction as *const PactInteraction,
326          None => {
327            trace!("iter past the end of messages");
328            std::ptr::null()
329          }
330        }
331    } {
332        std::ptr::null()
333    }
334}
335
336ffi_fn! {
337    /// Free the iterator when you're done using it.
338    fn pactffi_pact_interaction_iter_delete(iter: *mut PactInteractionIterator) {
339        ptr::drop_raw(iter);
340    }
341}