1use std::collections::HashMap;
2
3use derive_more::{Display, Error, From};
4use serde::{Deserialize, Serialize};
5
6#[derive(Clone, Debug, From, PartialEq, Eq, Serialize, Deserialize)]
9#[serde(rename_all = "snake_case", tag = "type")]
10pub enum Authentication {
11 #[serde(rename = "auth_initialization")]
13 Initialization(Initialization),
14
15 #[serde(rename = "auth_start_method")]
17 StartMethod(StartMethod),
18
19 #[serde(rename = "auth_challenge")]
21 Challenge(Challenge),
22
23 #[serde(rename = "auth_verification")]
25 Verification(Verification),
26
27 #[serde(rename = "auth_info")]
29 Info(Info),
30
31 #[serde(rename = "auth_error")]
33 Error(Error),
34
35 #[serde(rename = "auth_finished")]
37 Finished,
38}
39
40#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
42pub struct Initialization {
43 pub methods: Vec<String>,
45}
46
47#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
49pub struct StartMethod {
50 pub method: String,
51}
52
53#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
55pub struct Challenge {
56 pub questions: Vec<Question>,
57 pub options: HashMap<String, String>,
58}
59
60#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
62pub struct Verification {
63 pub kind: VerificationKind,
64 pub text: String,
65}
66
67#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
69pub struct Info {
70 pub text: String,
71}
72
73#[derive(Clone, Debug, From, PartialEq, Eq, Serialize, Deserialize)]
76#[serde(rename_all = "snake_case", tag = "type")]
77pub enum AuthenticationResponse {
78 #[serde(rename = "auth_initialization_response")]
80 Initialization(InitializationResponse),
81
82 #[serde(rename = "auth_challenge_response")]
84 Challenge(ChallengeResponse),
85
86 #[serde(rename = "auth_verification_response")]
88 Verification(VerificationResponse),
89}
90
91#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
93pub struct InitializationResponse {
94 pub methods: Vec<String>,
96}
97
98#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
100pub struct ChallengeResponse {
101 pub answers: Vec<String>,
103}
104
105#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
107pub struct VerificationResponse {
108 pub valid: bool,
110}
111
112#[derive(Copy, Clone, Debug, Display, PartialEq, Eq, Serialize, Deserialize)]
114#[serde(rename_all = "snake_case")]
115pub enum VerificationKind {
116 #[display(fmt = "host")]
118 Host,
119
120 #[display(fmt = "unknown")]
122 #[serde(other)]
123 Unknown,
124}
125
126impl VerificationKind {
127 pub const fn known_variants() -> &'static [Self] {
129 &[Self::Host]
130 }
131}
132
133#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
135pub struct Question {
136 pub label: String,
138
139 pub text: String,
141
142 pub options: HashMap<String, String>,
145}
146
147impl Question {
148 pub fn new(text: impl Into<String>) -> Self {
150 let text = text.into();
151
152 Self {
153 label: text.clone(),
154 text,
155 options: HashMap::new(),
156 }
157 }
158}
159
160#[derive(Clone, Debug, Display, Error, PartialEq, Eq, Serialize, Deserialize)]
162#[display(fmt = "{kind}: {text}")]
163pub struct Error {
164 pub kind: ErrorKind,
166
167 pub text: String,
169}
170
171impl Error {
172 pub fn fatal(text: impl Into<String>) -> Self {
174 Self {
175 kind: ErrorKind::Fatal,
176 text: text.into(),
177 }
178 }
179
180 pub fn non_fatal(text: impl Into<String>) -> Self {
182 Self {
183 kind: ErrorKind::Error,
184 text: text.into(),
185 }
186 }
187
188 pub fn is_fatal(&self) -> bool {
191 self.kind.is_fatal()
192 }
193
194 pub fn into_io_permission_denied(self) -> std::io::Error {
196 std::io::Error::new(std::io::ErrorKind::PermissionDenied, self)
197 }
198}
199
200#[derive(Copy, Clone, Debug, Display, PartialEq, Eq, Serialize, Deserialize)]
202#[serde(rename_all = "snake_case")]
203pub enum ErrorKind {
204 Fatal,
206
207 Error,
209}
210
211impl ErrorKind {
212 pub fn is_fatal(self) -> bool {
215 matches!(self, Self::Fatal)
216 }
217}