elicitation/verification/types/
tuples.rs1use crate::{ElicitClient, ElicitResult, Elicitation, Prompt};
7
8#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14pub struct Tuple2<C1, C2>(pub C1, pub C2);
15
16impl<C1, C2> Tuple2<C1, C2> {
17 pub fn new(first: C1, second: C2) -> Self {
19 Self(first, second)
20 }
21
22 pub fn first(&self) -> &C1 {
24 &self.0
25 }
26
27 pub fn second(&self) -> &C2 {
29 &self.1
30 }
31
32 pub fn into_inner(self) -> (C1, C2) {
34 (self.0, self.1)
35 }
36}
37
38impl<C1, C2> Prompt for Tuple2<C1, C2>
39where
40 C1: Elicitation + Send,
41 C2: Elicitation + Send,
42{
43 fn prompt() -> Option<&'static str> {
44 Some("Eliciting tuple with 2 elements:")
45 }
46}
47
48impl<C1, C2> Elicitation for Tuple2<C1, C2>
49where
50 C1: Elicitation + Send,
51 C2: Elicitation + Send,
52{
53 type Style = <(C1, C2) as Elicitation>::Style;
54
55 #[tracing::instrument(skip(client))]
56 async fn elicit(client: &ElicitClient) -> ElicitResult<Self> {
57 tracing::debug!("Eliciting Tuple2");
58 let first = C1::elicit(client).await?; let second = C2::elicit(client).await?; Ok(Self::new(first, second)) }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq, Hash)]
67pub struct Tuple3<C1, C2, C3>(pub C1, pub C2, pub C3);
68
69impl<C1, C2, C3> Tuple3<C1, C2, C3> {
70 pub fn new(first: C1, second: C2, third: C3) -> Self {
72 Self(first, second, third)
73 }
74
75 pub fn into_inner(self) -> (C1, C2, C3) {
77 (self.0, self.1, self.2)
78 }
79}
80
81impl<C1, C2, C3> Prompt for Tuple3<C1, C2, C3>
82where
83 C1: Elicitation + Send,
84 C2: Elicitation + Send,
85 C3: Elicitation + Send,
86{
87 fn prompt() -> Option<&'static str> {
88 Some("Eliciting tuple with 3 elements:")
89 }
90}
91
92impl<C1, C2, C3> Elicitation for Tuple3<C1, C2, C3>
93where
94 C1: Elicitation + Send,
95 C2: Elicitation + Send,
96 C3: Elicitation + Send,
97{
98 type Style = <(C1, C2, C3) as Elicitation>::Style;
99
100 #[tracing::instrument(skip(client))]
101 async fn elicit(client: &ElicitClient) -> ElicitResult<Self> {
102 tracing::debug!("Eliciting Tuple3");
103 let first = C1::elicit(client).await?;
104 let second = C2::elicit(client).await?;
105 let third = C3::elicit(client).await?;
106 Ok(Self::new(first, second, third))
107 }
108}
109
110#[derive(Debug, Clone, PartialEq, Eq, Hash)]
113pub struct Tuple4<C1, C2, C3, C4>(pub C1, pub C2, pub C3, pub C4);
114
115impl<C1, C2, C3, C4> Tuple4<C1, C2, C3, C4> {
116 pub fn new(first: C1, second: C2, third: C3, fourth: C4) -> Self {
118 Self(first, second, third, fourth)
119 }
120
121 pub fn into_inner(self) -> (C1, C2, C3, C4) {
123 (self.0, self.1, self.2, self.3)
124 }
125}
126
127impl<C1, C2, C3, C4> Prompt for Tuple4<C1, C2, C3, C4>
128where
129 C1: Elicitation + Send,
130 C2: Elicitation + Send,
131 C3: Elicitation + Send,
132 C4: Elicitation + Send,
133{
134 fn prompt() -> Option<&'static str> {
135 Some("Eliciting tuple with 4 elements:")
136 }
137}
138
139impl<C1, C2, C3, C4> Elicitation for Tuple4<C1, C2, C3, C4>
140where
141 C1: Elicitation + Send,
142 C2: Elicitation + Send,
143 C3: Elicitation + Send,
144 C4: Elicitation + Send,
145{
146 type Style = <(C1, C2, C3, C4) as Elicitation>::Style;
147
148 #[tracing::instrument(skip(client))]
149 async fn elicit(client: &ElicitClient) -> ElicitResult<Self> {
150 tracing::debug!("Eliciting Tuple4");
151 let first = C1::elicit(client).await?;
152 let second = C2::elicit(client).await?;
153 let third = C3::elicit(client).await?;
154 let fourth = C4::elicit(client).await?;
155 Ok(Self::new(first, second, third, fourth))
156 }
157}
158
159#[cfg(test)]
160mod tests {
161 use super::*;
162 use crate::verification::types::{BoolTrue, I8Positive, StringNonEmpty};
163
164 #[test]
165 fn test_tuple2_new() {
166 let s: StringNonEmpty = StringNonEmpty::new("test".to_string()).unwrap();
167 let t = Tuple2::new(I8Positive::new(5).unwrap(), s);
168 assert_eq!(t.first().get(), 5);
169 assert_eq!(t.second().get(), "test");
170 }
171
172 #[test]
173 fn test_tuple2_into_inner() {
174 let s: StringNonEmpty = StringNonEmpty::new("test".to_string()).unwrap();
175 let t = Tuple2::new(I8Positive::new(5).unwrap(), s);
176 let (first, second) = t.into_inner();
177 assert_eq!(first.get(), 5);
178 assert_eq!(second.get(), "test");
179 }
180
181 #[test]
182 fn test_tuple3_new() {
183 let s: StringNonEmpty = StringNonEmpty::new("test".to_string()).unwrap();
184 let t = Tuple3::new(I8Positive::new(5).unwrap(), s, BoolTrue::new(true).unwrap());
185 let (first, second, third) = t.into_inner();
186 assert_eq!(first.get(), 5);
187 assert_eq!(second.get(), "test");
188 assert!(third.get());
189 }
190
191 #[test]
192 fn test_tuple4_new() {
193 let t = Tuple4::new(
194 I8Positive::new(1).unwrap(),
195 I8Positive::new(2).unwrap(),
196 I8Positive::new(3).unwrap(),
197 I8Positive::new(4).unwrap(),
198 );
199 let (a, b, c, d) = t.into_inner();
200 assert_eq!(a.get(), 1);
201 assert_eq!(b.get(), 2);
202 assert_eq!(c.get(), 3);
203 assert_eq!(d.get(), 4);
204 }
205}