mirror of
https://github.com/Noratrieb/icefun.git
synced 2026-03-15 08:36:04 +01:00
loop
This commit is contained in:
parent
7af1274587
commit
189f24e53b
58 changed files with 1489 additions and 12529 deletions
|
|
@ -35,71 +35,52 @@ pub(crate) struct ReasonPhrase(Bytes);
|
|||
impl ReasonPhrase {
|
||||
/// Gets the reason phrase as bytes.
|
||||
pub(crate) fn as_bytes(&self) -> &[u8] {
|
||||
&self.0
|
||||
loop {}
|
||||
}
|
||||
/// Converts a static byte slice to a reason phrase.
|
||||
pub(crate) fn from_static(reason: &'static [u8]) -> Self {
|
||||
if find_invalid_byte(reason).is_some() {
|
||||
panic!("invalid byte in static reason phrase");
|
||||
}
|
||||
Self(Bytes::from_static(reason))
|
||||
loop {}
|
||||
}
|
||||
/// Converts a `Bytes` directly into a `ReasonPhrase` without validating.
|
||||
///
|
||||
/// Use with care; invalid bytes in a reason phrase can cause serious security problems if
|
||||
/// emitted in a response.
|
||||
pub(crate) unsafe fn from_bytes_unchecked(reason: Bytes) -> Self {
|
||||
Self(reason)
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
impl TryFrom<&[u8]> for ReasonPhrase {
|
||||
type Error = InvalidReasonPhrase;
|
||||
fn try_from(reason: &[u8]) -> Result<Self, Self::Error> {
|
||||
if let Some(bad_byte) = find_invalid_byte(reason) {
|
||||
Err(InvalidReasonPhrase { bad_byte })
|
||||
} else {
|
||||
Ok(Self(Bytes::copy_from_slice(reason)))
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
impl TryFrom<Vec<u8>> for ReasonPhrase {
|
||||
type Error = InvalidReasonPhrase;
|
||||
fn try_from(reason: Vec<u8>) -> Result<Self, Self::Error> {
|
||||
if let Some(bad_byte) = find_invalid_byte(&reason) {
|
||||
Err(InvalidReasonPhrase { bad_byte })
|
||||
} else {
|
||||
Ok(Self(Bytes::from(reason)))
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
impl TryFrom<String> for ReasonPhrase {
|
||||
type Error = InvalidReasonPhrase;
|
||||
fn try_from(reason: String) -> Result<Self, Self::Error> {
|
||||
if let Some(bad_byte) = find_invalid_byte(reason.as_bytes()) {
|
||||
Err(InvalidReasonPhrase { bad_byte })
|
||||
} else {
|
||||
Ok(Self(Bytes::from(reason)))
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
impl TryFrom<Bytes> for ReasonPhrase {
|
||||
type Error = InvalidReasonPhrase;
|
||||
fn try_from(reason: Bytes) -> Result<Self, Self::Error> {
|
||||
if let Some(bad_byte) = find_invalid_byte(&reason) {
|
||||
Err(InvalidReasonPhrase { bad_byte })
|
||||
} else {
|
||||
Ok(Self(reason))
|
||||
}
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
impl Into<Bytes> for ReasonPhrase {
|
||||
fn into(self) -> Bytes {
|
||||
self.0
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
impl AsRef<[u8]> for ReasonPhrase {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
&self.0
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
/// Error indicating an invalid byte when constructing a `ReasonPhrase`.
|
||||
|
|
@ -113,70 +94,49 @@ pub(crate) struct InvalidReasonPhrase {
|
|||
}
|
||||
impl std::fmt::Display for InvalidReasonPhrase {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "Invalid byte in reason phrase: {}", self.bad_byte)
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
impl std::error::Error for InvalidReasonPhrase {}
|
||||
const fn is_valid_byte(b: u8) -> bool {
|
||||
const fn is_vchar(b: u8) -> bool {
|
||||
0x21 <= b && b <= 0x7E
|
||||
}
|
||||
#[allow(unused_comparisons)]
|
||||
const fn is_obs_text(b: u8) -> bool {
|
||||
0x80 <= b && b <= 0xFF
|
||||
}
|
||||
b == b'\t' || b == b' ' || is_vchar(b) || is_obs_text(b)
|
||||
loop {}
|
||||
}
|
||||
const fn find_invalid_byte(bytes: &[u8]) -> Option<u8> {
|
||||
let mut i = 0;
|
||||
while i < bytes.len() {
|
||||
let b = bytes[i];
|
||||
if !is_valid_byte(b) {
|
||||
return Some(b);
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
None
|
||||
loop {}
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn basic_valid() {
|
||||
const PHRASE: &'static [u8] = b"OK";
|
||||
assert_eq!(ReasonPhrase::from_static(PHRASE).as_bytes(), PHRASE);
|
||||
assert_eq!(ReasonPhrase::try_from(PHRASE).unwrap().as_bytes(), PHRASE);
|
||||
loop {}
|
||||
}
|
||||
#[test]
|
||||
fn empty_valid() {
|
||||
const PHRASE: &'static [u8] = b"";
|
||||
assert_eq!(ReasonPhrase::from_static(PHRASE).as_bytes(), PHRASE);
|
||||
assert_eq!(ReasonPhrase::try_from(PHRASE).unwrap().as_bytes(), PHRASE);
|
||||
loop {}
|
||||
}
|
||||
#[test]
|
||||
fn obs_text_valid() {
|
||||
const PHRASE: &'static [u8] = b"hyp\xe9r";
|
||||
assert_eq!(ReasonPhrase::from_static(PHRASE).as_bytes(), PHRASE);
|
||||
assert_eq!(ReasonPhrase::try_from(PHRASE).unwrap().as_bytes(), PHRASE);
|
||||
loop {}
|
||||
}
|
||||
const NEWLINE_PHRASE: &'static [u8] = b"hyp\ner";
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn newline_invalid_panic() {
|
||||
ReasonPhrase::from_static(NEWLINE_PHRASE);
|
||||
loop {}
|
||||
}
|
||||
#[test]
|
||||
fn newline_invalid_err() {
|
||||
assert!(ReasonPhrase::try_from(NEWLINE_PHRASE).is_err());
|
||||
loop {}
|
||||
}
|
||||
const CR_PHRASE: &'static [u8] = b"hyp\rer";
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn cr_invalid_panic() {
|
||||
ReasonPhrase::from_static(CR_PHRASE);
|
||||
loop {}
|
||||
}
|
||||
#[test]
|
||||
fn cr_invalid_err() {
|
||||
assert!(ReasonPhrase::try_from(CR_PHRASE).is_err());
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue