1mod known;
2
3use std::{num::NonZero, str};
4
5pub use known::Known;
6use o3::alloc::{self, BoxSliceExt as _};
7
8use crate::field;
9
10#[derive(Debug, PartialEq, Eq, Hash)]
12pub struct Method(Kind);
13
14#[derive(Debug, PartialEq, Eq, Hash)]
15enum Kind {
16 Known(Known),
17 Trace,
18 Query,
19 Inline { bytes: [u8; 15], len: NonZero<u8> },
20 Owned(Box<[u8]>),
21}
22
23impl Method {
24 pub const GET: Self = Self(Kind::Known(Known::Get));
25 pub const POST: Self = Self(Kind::Known(Known::Post));
26 pub const PUT: Self = Self(Kind::Known(Known::Put));
27 pub const PATCH: Self = Self(Kind::Known(Known::Patch));
28 pub const DELETE: Self = Self(Kind::Known(Known::Delete));
29 pub const HEAD: Self = Self(Kind::Known(Known::Head));
30 pub const OPTIONS: Self = Self(Kind::Known(Known::Options));
31 pub const CONNECT: Self = Self(Kind::Known(Known::Connect));
32 pub const TRACE: Self = Self(Kind::Trace);
33 pub const QUERY: Self = Self(Kind::Query);
34
35 pub fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
36 if let Some(known) = Known::from_bytes(bytes) {
37 return Ok(known.into());
38 }
39 if bytes == b"TRACE" {
40 return Ok(Self::TRACE);
41 }
42 if bytes == b"QUERY" {
43 return Ok(Self::QUERY);
44 }
45 field::Error::name(bytes).map_err(Error::Syntax)?;
46 if bytes.len() <= 15 {
47 let mut inline = [0; 15];
48 inline[..bytes.len()].copy_from_slice(bytes);
49 Ok(Self(Kind::Inline {
50 bytes: inline,
51 len: NonZero::<u8>::MIN.saturating_add(bytes.len() as u8 - 1),
52 }))
53 } else {
54 Ok(Self(Kind::Owned(
55 Box::try_copy(bytes).map_err(Error::Allocation)?,
56 )))
57 }
58 }
59
60 pub fn as_str(&self) -> &str {
61 unsafe { str::from_utf8_unchecked(self.as_bytes()) }
64 }
65
66 pub fn as_bytes(&self) -> &[u8] {
67 match &self.0 {
68 Kind::Known(known) => known.as_str().as_bytes(),
69 Kind::Trace => b"TRACE",
70 Kind::Query => b"QUERY",
71 Kind::Inline { bytes, len } => {
72 unsafe { bytes.get_unchecked(..usize::from(len.get())) }
74 }
75 Kind::Owned(bytes) => bytes,
76 }
77 }
78}
79
80impl Default for Method {
81 fn default() -> Self {
82 Self::GET
83 }
84}
85
86impl AsRef<str> for Method {
87 fn as_ref(&self) -> &str {
88 self.as_str()
89 }
90}
91
92const _: () = assert!(size_of::<Method>() <= 3 * size_of::<usize>());
93
94impl From<Known> for Method {
95 fn from(method: Known) -> Self {
96 Self(Kind::Known(method))
97 }
98}
99
100#[derive(Clone, Copy, Debug, PartialEq, Eq)]
102pub enum Error {
103 Syntax(field::Error),
104 Allocation(alloc::Exhausted),
105}