1use crate::{field::metadata::map::record, uri::Error};
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq)]
4#[repr(u8)]
5pub enum Scheme {
6 None,
7 Http,
8 Https,
9 Other,
10}
11
12impl Scheme {
13 pub(crate) fn validate(value: &[u8]) -> Result<(), Error> {
14 Self::check_span(record::Span::from_slice(value))
15 }
16
17 pub fn parse(value: &[u8]) -> Result<Self, Error> {
18 Self::parse_span(record::Span::from_slice(value))
19 }
20
21 pub fn parse_span(value: record::Span<'_>) -> Result<Self, Error> {
22 if value.eq_ascii(b"http") {
23 Ok(Self::Http)
24 } else if value.eq_ascii(b"https") {
25 Ok(Self::Https)
26 } else {
27 Self::check_span(value)?;
28 Ok(Self::Other)
29 }
30 }
31
32 fn check_span(value: record::Span<'_>) -> Result<(), Error> {
33 if !value.get(0).is_some_and(|byte| byte.is_ascii_alphabetic())
34 || !value
35 .iter()
36 .skip(1)
37 .all(|byte| byte.is_ascii_alphanumeric() || matches!(*byte, b'+' | b'-' | b'.'))
38 {
39 return Err(Error::InvalidScheme);
40 }
41 Ok(())
42 }
43}