1#![forbid(unsafe_code)]
4
5use secrecy::{ExposeSecret, SecretString};
6use std::fmt;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct DomainError {
11 pub code: &'static str,
13 pub message: String,
15}
16
17impl DomainError {
18 #[must_use]
20 pub fn new(code: &'static str, message: impl Into<String>) -> Self {
21 Self {
22 code,
23 message: message.into(),
24 }
25 }
26}
27
28impl fmt::Display for DomainError {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 write!(f, "{}: {}", self.code, self.message)
31 }
32}
33
34impl std::error::Error for DomainError {}
35
36#[inline]
38pub fn domain_err(e: DomainError) -> crate::errors::SshCliError {
39 e.into()
40}
41
42#[must_use]
44pub fn secret_nonempty(s: &SecretString) -> bool {
45 !s.expose_secret().is_empty()
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 #[test]
53 fn secret_nonempty_helper() {
54 assert!(!secret_nonempty(&SecretString::from(String::new())));
55 assert!(secret_nonempty(&SecretString::from("x".to_string())));
56 }
57
58 #[test]
59 fn domain_into_ssh_cli_error() {
60 let e: crate::errors::SshCliError =
61 DomainError::new("host", "empty").into();
62 assert!(matches!(e, crate::errors::SshCliError::Domain(_)));
63 }
64}