diff --git a/Cargo.lock b/Cargo.lock index bdef83f9..ca359685 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -116,7 +116,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.74", + "syn", "which", ] @@ -447,17 +447,6 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" -[[package]] -name = "enum-repr" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad30c9c0fa1aaf1ae5010dab11f1117b15d35faf62cda4bbbc53b9987950f18" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "enumflags2" version = "0.7.10" @@ -475,7 +464,7 @@ checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn", ] [[package]] @@ -572,7 +561,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn", ] [[package]] @@ -1068,7 +1057,6 @@ version = "0.3.0" dependencies = [ "buffet", "byteorder", - "enum-repr", "enumflags2", "nom", "thiserror", @@ -1229,7 +1217,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.74", + "syn", ] [[package]] @@ -1363,7 +1351,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.74", + "syn", ] [[package]] @@ -1595,7 +1583,7 @@ checksum = "fabfb6138d2383ea8208cf98ccf69cdfb1aff4088460681d84189aa259762f97" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn", ] [[package]] @@ -1671,17 +1659,6 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" -[[package]] -name = "syn" -version = "1.0.109" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - [[package]] name = "syn" version = "2.0.74" @@ -1710,7 +1687,7 @@ checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn", ] [[package]] @@ -1778,7 +1755,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn", ] [[package]] @@ -1852,7 +1829,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn", ] [[package]] @@ -1981,7 +1958,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.74", + "syn", "wasm-bindgen-shared", ] @@ -2003,7 +1980,7 @@ checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2247,5 +2224,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.74", + "syn", ] diff --git a/crates/loona-h2/Cargo.toml b/crates/loona-h2/Cargo.toml index e88f9776..a218b92e 100644 --- a/crates/loona-h2/Cargo.toml +++ b/crates/loona-h2/Cargo.toml @@ -12,7 +12,6 @@ HTTP/2 parser and base types rust-version = "1.75" [dependencies] -enum-repr = "0.2.6" enumflags2 = "0.7.10" nom = { version = "7.1.3", default-features = false } buffet = { version = "0.3.0", path = "../buffet" } diff --git a/crates/loona-h2/src/lib.rs b/crates/loona-h2/src/lib.rs index bfd3e81a..4ee45fe3 100644 --- a/crates/loona-h2/src/lib.rs +++ b/crates/loona-h2/src/lib.rs @@ -6,7 +6,6 @@ use std::{fmt, io::Write, ops::RangeInclusive}; use byteorder::{BigEndian, WriteBytesExt}; -use enum_repr::EnumRepr; pub use enumflags2; use enumflags2::{bitflags, BitFlags}; @@ -35,8 +34,7 @@ pub trait IntoPiece { } /// See -#[EnumRepr(type = "u8")] -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum RawFrameType { Data = 0x00, Headers = 0x01, @@ -50,6 +48,53 @@ pub enum RawFrameType { Continuation = 0x09, } +impl RawFrameType { + pub fn repr(&self) -> u8 { + *self as u8 + } + + pub fn from_repr(value: u8) -> Option { + match value { + 0x00 => Some(RawFrameType::Data), + 0x01 => Some(RawFrameType::Headers), + 0x02 => Some(RawFrameType::Priority), + 0x03 => Some(RawFrameType::RstStream), + 0x04 => Some(RawFrameType::Settings), + 0x05 => Some(RawFrameType::PushPromise), + 0x06 => Some(RawFrameType::Ping), + 0x07 => Some(RawFrameType::GoAway), + 0x08 => Some(RawFrameType::WindowUpdate), + 0x09 => Some(RawFrameType::Continuation), + _ => None, + } + } +} + +#[test] +fn test_raw_frame_type_roundtrip() { + let variants = [ + RawFrameType::Data, + RawFrameType::Headers, + RawFrameType::Priority, + RawFrameType::RstStream, + RawFrameType::Settings, + RawFrameType::PushPromise, + RawFrameType::Ping, + RawFrameType::GoAway, + RawFrameType::WindowUpdate, + RawFrameType::Continuation, + ]; + + for &variant in &variants { + let repr = variant as u8; + let roundtripped = RawFrameType::from_repr(repr).unwrap(); + assert_eq!(variant, roundtripped, "Failed to roundtrip {:?}", variant); + } + + // Test that an invalid repr returns None + assert_eq!(RawFrameType::from_repr(0xFF), None); +} + /// Typed flags for various frame types #[derive(Debug, Clone, Copy)] pub enum FrameType { @@ -551,7 +596,6 @@ impl From for ErrorCode { } } -#[EnumRepr(type = "u32")] #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum KnownErrorCode { /// The associated condition is not a result of an error. For example, a @@ -611,6 +655,61 @@ pub enum KnownErrorCode { Http1_1Required = 0x0d, } +impl KnownErrorCode { + pub fn from_repr(value: u32) -> Option { + match value { + 0x00 => Some(KnownErrorCode::NoError), + 0x01 => Some(KnownErrorCode::ProtocolError), + 0x02 => Some(KnownErrorCode::InternalError), + 0x03 => Some(KnownErrorCode::FlowControlError), + 0x04 => Some(KnownErrorCode::SettingsTimeout), + 0x05 => Some(KnownErrorCode::StreamClosed), + 0x06 => Some(KnownErrorCode::FrameSizeError), + 0x07 => Some(KnownErrorCode::RefusedStream), + 0x08 => Some(KnownErrorCode::Cancel), + 0x09 => Some(KnownErrorCode::CompressionError), + 0x0a => Some(KnownErrorCode::ConnectError), + 0x0b => Some(KnownErrorCode::EnhanceYourCalm), + 0x0c => Some(KnownErrorCode::InadequateSecurity), + 0x0d => Some(KnownErrorCode::Http1_1Required), + _ => None, + } + } + + pub fn repr(&self) -> u32 { + *self as u32 + } +} + +#[test] +fn test_known_error_code_roundtrip() { + let error_codes = [ + KnownErrorCode::NoError, + KnownErrorCode::ProtocolError, + KnownErrorCode::InternalError, + KnownErrorCode::FlowControlError, + KnownErrorCode::SettingsTimeout, + KnownErrorCode::StreamClosed, + KnownErrorCode::FrameSizeError, + KnownErrorCode::RefusedStream, + KnownErrorCode::Cancel, + KnownErrorCode::CompressionError, + KnownErrorCode::ConnectError, + KnownErrorCode::EnhanceYourCalm, + KnownErrorCode::InadequateSecurity, + KnownErrorCode::Http1_1Required, + ]; + + for &original in &error_codes { + let repr = original.repr(); + let roundtripped = KnownErrorCode::from_repr(repr).unwrap(); + assert_eq!(original, roundtripped, "Failed to roundtrip {:?}", original); + } + + // Test that an invalid repr returns None + assert_eq!(KnownErrorCode::from_repr(0xFF), None); +} + impl TryFrom for KnownErrorCode { type Error = (); @@ -761,8 +860,7 @@ pub enum SettingsError { SettingsMaxFrameSizeInvalid { actual: u32 }, } -#[EnumRepr(type = "u16")] -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Setting { HeaderTableSize = 0x01, EnablePush = 0x02, @@ -772,6 +870,45 @@ pub enum Setting { MaxHeaderListSize = 0x06, } +impl Setting { + pub fn repr(&self) -> u16 { + *self as u16 + } + + pub fn from_repr(value: u16) -> Option { + match value { + 0x01 => Some(Setting::HeaderTableSize), + 0x02 => Some(Setting::EnablePush), + 0x03 => Some(Setting::MaxConcurrentStreams), + 0x04 => Some(Setting::InitialWindowSize), + 0x05 => Some(Setting::MaxFrameSize), + 0x06 => Some(Setting::MaxHeaderListSize), + _ => None, + } + } +} + +#[test] +fn test_setting_roundtrip() { + let settings = [ + Setting::HeaderTableSize, + Setting::EnablePush, + Setting::MaxConcurrentStreams, + Setting::InitialWindowSize, + Setting::MaxFrameSize, + Setting::MaxHeaderListSize, + ]; + + for &setting in &settings { + let repr = setting.repr(); + let roundtripped = Setting::from_repr(repr).unwrap(); + assert_eq!(setting, roundtripped, "Failed to roundtrip {:?}", setting); + } + + // Test that an invalid repr returns None + assert_eq!(Setting::from_repr(0x07), None); +} + impl Settings { pub const MAX_INITIAL_WINDOW_SIZE: u32 = (1 << 31) - 1; pub const MAX_FRAME_SIZE_ALLOWED_RANGE: RangeInclusive = (1 << 14)..=((1 << 24) - 1);