1use std::{
2 error::Error,
3 fmt::{self, Display},
4 str::FromStr,
5};
6
7#[derive(Debug, PartialEq, Eq, Clone, Copy)]
9pub enum Scheme {
10 File,
12 Ftp,
14 Ftps,
16 Git,
18 GitSsh,
20 Http,
22 Https,
24 Ssh,
26 Unspecified,
28}
29
30impl Display for Scheme {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 match self {
33 Scheme::File => write!(f, "file"),
34 Scheme::Ftp => write!(f, "ftp"),
35 Scheme::Ftps => write!(f, "ftps"),
36 Scheme::Git => write!(f, "git"),
37 Scheme::GitSsh => write!(f, "git+ssh"),
38 Scheme::Http => write!(f, "http"),
39 Scheme::Https => write!(f, "https"),
40 Scheme::Ssh => write!(f, "ssh"),
41 Scheme::Unspecified => write!(f, "unspecified"),
42 }
43 }
44}
45
46#[derive(Debug)]
47#[non_exhaustive]
48pub struct FromStrError {
49 kind: FromStrErrorKind,
50}
51
52impl Display for FromStrError {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 match &self.kind {
55 FromStrErrorKind::UnsupportedScheme(scheme) => {
56 write!(f, "unsupported scheme `{}`", scheme)
57 }
58 }
59 }
60}
61
62impl Error for FromStrError {
63 fn source(&self) -> Option<&(dyn Error + 'static)> {
64 match &self.kind {
65 FromStrErrorKind::UnsupportedScheme(_) => None,
66 }
67 }
68}
69
70#[derive(Debug)]
71pub enum FromStrErrorKind {
72 #[non_exhaustive]
73 UnsupportedScheme(String),
74}
75
76impl FromStr for Scheme {
77 type Err = FromStrError;
78
79 fn from_str(s: &str) -> Result<Self, Self::Err> {
80 match s {
81 "file" => Ok(Scheme::File),
82 "ftp" => Ok(Scheme::Ftp),
83 "ftps" => Ok(Scheme::Ftps),
84 "git" => Ok(Scheme::Git),
85 "git+ssh" => Ok(Scheme::GitSsh),
86 "http" => Ok(Scheme::Http),
87 "https" => Ok(Scheme::Https),
88 "ssh" => Ok(Scheme::Ssh),
89 "unspecified" => Ok(Scheme::Unspecified),
90 _ => Err(FromStrError {
91 kind: FromStrErrorKind::UnsupportedScheme(s.to_owned()),
92 }),
93 }
94 }
95}