creator_simctl/
device.rs

1use std::ops::Deref;
2
3use super::list::DeviceInfo;
4use super::Simctl;
5
6/// Wrapper around a single device returned by `simctl`.
7#[derive(Clone, Debug)]
8pub struct Device {
9    simctl: Simctl,
10    info: DeviceInfo,
11}
12
13impl Device {
14    pub(crate) fn new(simctl: Simctl, info: DeviceInfo) -> Device {
15        Device { simctl, info }
16    }
17
18    /// Returns an instance to the Simctl wrapper that was used to retrieve this
19    /// device.
20    pub fn simctl(&self) -> &Simctl {
21        &self.simctl
22    }
23
24    /// Returns information about this device. This is also accessible through
25    /// [`Device::deref`].
26    pub fn info(&self) -> &DeviceInfo {
27        &self.info
28    }
29}
30
31impl Deref for Device {
32    type Target = DeviceInfo;
33
34    fn deref(&self) -> &Self::Target {
35        &self.info
36    }
37}
38
39/// Trait that makes it easy to filter an iterator over devices by availability
40/// or name.
41pub trait DeviceQuery<'a>: Iterator<Item = &'a Device> {
42    /// Filters this iterator down to only available devices.
43    fn available(self) -> Available<'a, Self>;
44
45    /// Filters this iterator down to only devices with a matching name. Note
46    /// that names are not necessarily unique. Trivially, they can be shared
47    /// among several devices of the same type but with different runtimes (e.g.
48    /// iOS 11.0 and iOS 12.0).
49    fn by_name<'b>(self, name: &'b str) -> ByName<'a, 'b, Self>;
50}
51
52pub struct Available<'a, I>(I)
53where
54    I: Iterator<Item = &'a Device> + ?Sized;
55
56impl<'a, I> Iterator for Available<'a, I>
57where
58    I: Iterator<Item = &'a Device> + ?Sized,
59{
60    type Item = &'a Device;
61
62    fn next(&mut self) -> Option<Self::Item> {
63        while let Some(next) = self.0.next() {
64            if next.is_available {
65                return Some(next);
66            }
67        }
68
69        None
70    }
71}
72
73pub struct ByName<'a, 'b, I>(&'b str, I)
74where
75    I: Iterator<Item = &'a Device> + ?Sized;
76
77impl<'a, I> Iterator for ByName<'a, '_, I>
78where
79    I: Iterator<Item = &'a Device> + ?Sized,
80{
81    type Item = &'a Device;
82
83    fn next(&mut self) -> Option<Self::Item> {
84        while let Some(next) = self.1.next() {
85            if next.name == self.0 {
86                return Some(next);
87            }
88        }
89
90        None
91    }
92}
93
94impl<'a, I> DeviceQuery<'a> for I
95where
96    I: Iterator<Item = &'a Device>,
97{
98    fn available(self) -> Available<'a, Self> {
99        Available(self)
100    }
101
102    fn by_name<'b>(self, name: &'b str) -> ByName<'a, 'b, Self> {
103        ByName(name, self)
104    }
105}