apple_clis/shared/identifiers/device_name/
ipad.rs1use crate::prelude::*;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, EnumDiscriminants, PartialOrd, Ord)]
6pub enum IPadVariant {
7 Air {
8 screen_size: MaybeScreenSize,
9 generation: Generation,
10 },
11 Mini {
12 generation: Generation,
13 },
14 Plain {
15 generation: Generation,
16 },
17 Pro {
18 size: ScreenSize,
19 generation: Generation,
20 size_before_generation: bool,
22 },
23}
24
25impl NomFromStr for IPadVariant {
26 #[tracing::instrument(level = "trace")]
27 fn nom_from_str(input: &str) -> IResult<&str, Self> {
28 let (remaining, discriminate) = preceded(
29 ws(tag("iPad")),
30 cut(alt((
31 value(IPadVariantDiscriminants::Mini, ws(tag("mini"))),
32 value(IPadVariantDiscriminants::Air, ws(tag("Air"))),
33 value(IPadVariantDiscriminants::Pro, ws(tag("Pro"))),
34 success(IPadVariantDiscriminants::Plain),
35 ))),
36 )(input)?;
37
38 #[cfg(test)]
39 trace!(
40 ?discriminate,
41 remaining,
42 input,
43 "Discriminant found for parsing [IPadVariant]"
44 );
45
46 match discriminate {
47 IPadVariantDiscriminants::Air => {
48 let (remaining, screen_size) = MaybeScreenSize::nom_from_str(remaining)?;
49 let (remaining, generation) = Generation::nom_from_str(remaining)?;
50 Ok((
51 remaining,
52 IPadVariant::Air {
53 screen_size,
54 generation,
55 },
56 ))
57 }
58 IPadVariantDiscriminants::Mini => {
59 let (remaining, generation) = Generation::nom_from_str(remaining)?;
60 Ok((remaining, IPadVariant::Mini { generation }))
61 }
62 IPadVariantDiscriminants::Plain => {
63 let (remaining, generation) = Generation::nom_from_str(remaining)?;
64 Ok((remaining, IPadVariant::Plain { generation }))
65 }
66 IPadVariantDiscriminants::Pro => {
67 let (remaining, (size_before_generation, (size, generation))) = alt((
68 map(
69 pair(ws(ScreenSize::nom_from_str), ws(Generation::nom_from_str)),
70 |v| (true, v),
71 ),
72 map(
73 pair(ws(Generation::nom_from_str), ws(ScreenSize::nom_from_str)),
74 |(gen, ss)| (false, (ss, gen)),
75 ),
76 ))(remaining)?;
77 Ok((
78 remaining,
79 IPadVariant::Pro {
80 size,
81 generation,
82 size_before_generation,
83 },
84 ))
85 }
86 }
87 }
88}
89
90impl Display for IPadVariant {
91 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92 match self {
93 IPadVariant::Pro {
94 size,
95 generation,
96 size_before_generation: true,
97 } => write!(f, "iPad Pro {} {}", size, generation),
98 IPadVariant::Pro {
99 size,
100 generation,
101 size_before_generation: false,
102 } => write!(f, "iPad Pro {} {}", generation, size,),
103 IPadVariant::Mini { generation } => write!(f, "iPad mini {}", generation),
104 IPadVariant::Air {
105 screen_size,
106 generation,
107 } => write!(f, "iPad Air{} {}", screen_size, generation),
108 IPadVariant::Plain { generation } => write!(f, "iPad {}", generation),
109 }
110 }
111}
112
113#[cfg(test)]
114mod test {
115 use crate::shared::assert_nom_parses;
116
117 use super::*;
118
119 #[test]
120 fn ipad_ordering() {
121 let old = IPadVariant::Plain {
122 generation: Generation::testing_num(NonZeroU8::new(1).unwrap()),
123 };
124 let new = IPadVariant::Pro {
125 size: ScreenSize::long_brackets(12.9),
126 generation: Generation::testing_num(NonZeroU8::new(2).unwrap()),
127 size_before_generation: false,
128 };
129 assert!(new > old);
130 }
131
132 #[test]
133 fn hard_coded_parsing() {
134 let examples = [
135 "iPad Pro 13-inch (M4)",
144 ];
145 assert_nom_parses::<IPadVariant>(examples, |_| true)
146 }
147}