Repository: rustls/rustls (language: rust)

Issue:
Don't use Debug representation that much
Currently this innocent looking line may not be that much:

https://github.com/rustls/rustls/blob/211eabfa61d8af7643300e1e81dc33ce598e15f8/rustls/src/builder.rs#L245

But this needs the entire enum to implement Debug, and its representation can be huge, especially with CipherSuite:
https://github.com/rustls/rustls/blob/211eabfa61d8af7643300e1e81dc33ce598e15f8/rustls/src/enums.rs#L116-L491

I added a simple hack to suite_name:
```rust
            let suite_name = cs.common().suite;
            let suite_name: u16 = suite_name.into();
            return Err(Error::General(alloc::format!(
                "Ciphersuite {suite_name:?} requires {cs_kx:?} key exchange, but no {cs_kx:?}-compatible \
                key exchange groups were present in `CryptoProvider`'s `kx_groups` field",
            )));
```
This immediately shaved 7KB off the binary. 

Unfortunately, not all code can be eliminated like this, such as unwrap() calls which needs `Debug` as well, and this kind of hack might also lost its original (friendly-named) context. We should let the user to control this behavior, for example, we can just print the hex value of the suite name, so that the user can look it up themselves rather than adding this tax to the embedded device.


Discussion / hints:
Thanks for raising this - I think my ideal solution involves https://github.com/rust-lang/rust/issues/129709 but I also think the ciphersuite enum is bloated and would be a quick and widely-applicable win.

Fix patch:
diff --git a/rustls/src/client/handy.rs b/rustls/src/client/handy.rs
index c8b1836b945..9276b264c38 100644
--- a/rustls/src/client/handy.rs
+++ b/rustls/src/client/handy.rs
@@ -277,20 +277,21 @@ impl client::ResolvesClientCert for AlwaysResolvesClientRawPublicKeys {
 }
 
 test_for_each_provider! {
-    use std::prelude::v1::*;
     use alloc::sync::Arc;
+    use std::prelude::v1::*;
+
+    use pki_types::{ServerName, UnixTime};
+    use provider::cipher_suite;
+
     use super::NoClientSessionStorage;
     use crate::client::ClientSessionStore;
+    use crate::msgs::base::PayloadU16;
     use crate::msgs::enums::NamedGroup;
     use crate::msgs::handshake::CertificateChain;
     #[cfg(feature = "tls12")]
     use crate::msgs::handshake::SessionId;
     use crate::msgs::persist::Tls13ClientSessionValue;
     use crate::suites::SupportedCipherSuite;
-    use crate::msgs::base::PayloadU16;
-    use provider::cipher_suite;
-
-    use pki_types::{ServerName, UnixTime};
 
     #[test]
     fn test_noclientsessionstorage_does_nothing() {
diff --git a/rustls/src/crypto/ring/quic.rs b/rustls/src/crypto/ring/quic.rs
index 13c25ba2805..d900d989d1a 100644
--- a/rustls/src/crypto/ring/quic.rs
+++ b/rustls/src/crypto/ring/quic.rs
@@ -214,13 +214,15 @@ impl quic::Algorithm for KeyBuilder {
 
 test_for_each_provider! {
     use std::dbg;
-    use crate::common_state::Side;
-    use crate::crypto::tls13::OkmBlock;
-    use crate::quic::*;
+
     use provider::tls13::{
         TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL,
     };
 
+    use crate::common_state::Side;
+    use crate::crypto::tls13::OkmBlock;
+    use crate::quic::*;
+
     fn test_short_packet(version: Version, expected: &[u8]) {
         const PN: u64 = 654360564;
         const SECRET: &[u8] = &[
diff --git a/rustls/src/enums.rs b/rustls/src/enums.rs
index 41b28d64bad..4b48a03bec9 100644
--- a/rustls/src/enums.rs
+++ b/rustls/src/enums.rs
@@ -6,7 +6,7 @@ enum_builder! {
     /// The `AlertDescription` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub enum AlertDescription {
         CloseNotify => 0x00,
         UnexpectedMessage => 0x0a,
@@ -50,7 +50,7 @@ enum_builder! {
     /// The `HandshakeType` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub enum HandshakeType {
         HelloRequest => 0x00,
         ClientHello => 0x01,
@@ -79,7 +79,7 @@ enum_builder! {
     /// The `ContentType` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub enum ContentType {
         ChangeCipherSpec => 0x14,
         Alert => 0x15,
@@ -93,7 +93,7 @@ enum_builder! {
     /// The `ProtocolVersion` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U16
+    #[repr(u16)]
     pub enum ProtocolVersion {
         SSLv2 => 0x0200,
         SSLv3 => 0x0300,
@@ -111,9 +111,33 @@ enum_builder! {
     /// The `CipherSuite` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U16
+    #[repr(u16)]
     pub enum CipherSuite {
         TLS_NULL_WITH_NULL_NULL => 0x0000,
+        TLS_PSK_WITH_AES_128_GCM_SHA256 => 0x00a8,
+        TLS_PSK_WITH_AES_256_GCM_SHA384 => 0x00a9,
+        TLS_EMPTY_RENEGOTIATION_INFO_SCSV => 0x00ff,
+        TLS13_AES_128_GCM_SHA256 => 0x1301,
+        TLS13_AES_256_GCM_SHA384 => 0x1302,
+        TLS13_CHACHA20_POLY1305_SHA256 => 0x1303,
+        TLS13_AES_128_CCM_SHA256 => 0x1304,
+        TLS13_AES_128_CCM_8_SHA256 => 0x1305,
+        TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA => 0xc009,
+        TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA => 0xc00a,
+        TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA => 0xc013,
+        TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA => 0xc014,
+        TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 => 0xc023,
+        TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 => 0xc024,
+        TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 => 0xc027,
+        TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 => 0xc028,
+        TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 => 0xc02b,
+        TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 => 0xc02c,
+        TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 => 0xc02f,
+        TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 => 0xc030,
+        TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 => 0xcca8,
+        TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 => 0xcca9,
+
+    !Debug:
         TLS_RSA_WITH_NULL_MD5 => 0x0001,
         TLS_RSA_WITH_NULL_SHA => 0x0002,
         TLS_RSA_EXPORT_WITH_RC4_40_MD5 => 0x0003,
@@ -269,8 +293,6 @@ enum_builder! {
         TLS_DH_DSS_WITH_AES_256_GCM_SHA384 => 0x00a5,
         TLS_DH_anon_WITH_AES_128_GCM_SHA256 => 0x00a6,
         TLS_DH_anon_WITH_AES_256_GCM_SHA384 => 0x00a7,
-        TLS_PSK_WITH_AES_128_GCM_SHA256 => 0x00a8,
-        TLS_PSK_WITH_AES_256_GCM_SHA384 => 0x00a9,
         TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 => 0x00aa,
         TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 => 0x00ab,
         TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 => 0x00ac,
@@ -299,12 +321,6 @@ enum_builder! {
         TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA256 => 0x00c3,
         TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 => 0x00c4,
         TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA256 => 0x00c5,
-        TLS_EMPTY_RENEGOTIATION_INFO_SCSV => 0x00ff,
-        TLS13_AES_128_GCM_SHA256 => 0x1301,
-        TLS13_AES_256_GCM_SHA384 => 0x1302,
-        TLS13_CHACHA20_POLY1305_SHA256 => 0x1303,
-        TLS13_AES_128_CCM_SHA256 => 0x1304,
-        TLS13_AES_128_CCM_8_SHA256 => 0x1305,
         TLS_ECDH_ECDSA_WITH_NULL_SHA => 0xc001,
         TLS_ECDH_ECDSA_WITH_RC4_128_SHA => 0xc002,
         TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA => 0xc003,
@@ -313,8 +329,6 @@ enum_builder! {
         TLS_ECDHE_ECDSA_WITH_NULL_SHA => 0xc006,
         TLS_ECDHE_ECDSA_WITH_RC4_128_SHA => 0xc007,
         TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA => 0xc008,
-        TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA => 0xc009,
-        TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA => 0xc00a,
         TLS_ECDH_RSA_WITH_NULL_SHA => 0xc00b,
         TLS_ECDH_RSA_WITH_RC4_128_SHA => 0xc00c,
         TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA => 0xc00d,
@@ -323,8 +337,6 @@ enum_builder! {
         TLS_ECDHE_RSA_WITH_NULL_SHA => 0xc010,
         TLS_ECDHE_RSA_WITH_RC4_128_SHA => 0xc011,
         TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA => 0xc012,
-        TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA => 0xc013,
-        TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA => 0xc014,
         TLS_ECDH_anon_WITH_NULL_SHA => 0xc015,
         TLS_ECDH_anon_WITH_RC4_128_SHA => 0xc016,
         TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA => 0xc017,
@@ -339,20 +351,12 @@ enum_builder! {
         TLS_SRP_SHA_WITH_AES_256_CBC_SHA => 0xc020,
         TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA => 0xc021,
         TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA => 0xc022,
-        TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 => 0xc023,
-        TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 => 0xc024,
         TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 => 0xc025,
         TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 => 0xc026,
-        TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 => 0xc027,
-        TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 => 0xc028,
         TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 => 0xc029,
         TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 => 0xc02a,
-        TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 => 0xc02b,
-        TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 => 0xc02c,
         TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 => 0xc02d,
         TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 => 0xc02e,
-        TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 => 0xc02f,
-        TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 => 0xc030,
         TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 => 0xc031,
         TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 => 0xc032,
         TLS_ECDHE_PSK_WITH_RC4_128_SHA => 0xc033,
@@ -480,8 +484,6 @@ enum_builder! {
         TLS_ECDHE_ECDSA_WITH_AES_256_CCM => 0xc0ad,
         TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 => 0xc0ae,
         TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 => 0xc0af,
-        TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 => 0xcca8,
-        TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 => 0xcca9,
         TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 => 0xccaa,
         TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 => 0xccab,
         TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 => 0xccac,
@@ -496,7 +498,7 @@ enum_builder! {
     /// The `SignatureScheme` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U16
+    #[repr(u16)]
     pub enum SignatureScheme {
         RSA_PKCS1_SHA1 => 0x0201,
         ECDSA_SHA1_Legacy => 0x0203,
@@ -559,7 +561,7 @@ enum_builder! {
     /// The `SignatureAlgorithm` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub enum SignatureAlgorithm {
         Anonymous => 0x00,
         RSA => 0x01,
@@ -575,7 +577,7 @@ enum_builder! {
     /// Values in this enum are taken from [RFC8879].
     ///
     /// [RFC8879]: https://www.rfc-editor.org/rfc/rfc8879.html#section-7.3
-    @U16
+    #[repr(u16)]
     pub enum CertificateCompressionAlgorithm {
         Zlib => 1,
         Brotli => 2,
@@ -589,7 +591,7 @@ enum_builder! {
     /// Specified in [draft-ietf-tls-esni Section 5].
     ///
     /// [draft-ietf-tls-esni Section 5]: <https://www.ietf.org/archive/id/draft-ietf-tls-esni-18.html#section-5>
-    @U8
+    #[repr(u8)]
     pub enum EchClientHelloType {
         ClientHelloOuter => 0,
         ClientHelloInner => 1
diff --git a/rustls/src/hash_hs.rs b/rustls/src/hash_hs.rs
index 0e802879137..4cbde43f669 100644
--- a/rustls/src/hash_hs.rs
+++ b/rustls/src/hash_hs.rs
@@ -184,12 +184,13 @@ impl Clone for HandshakeHash {
 }
 
 test_for_each_provider! {
+    use provider::hash::SHA256;
+
     use super::*;
-    use crate::msgs::handshake::{HandshakeMessagePayload, HandshakePayload};
     use crate::crypto::hash::Hash;
+    use crate::enums::{HandshakeType, ProtocolVersion};
     use crate::msgs::base::Payload;
-    use crate::enums::{ProtocolVersion, HandshakeType};
-    use provider::hash::SHA256;
+    use crate::msgs::handshake::{HandshakeMessagePayload, HandshakePayload};
 
     #[test]
     fn hashes_correctly() {
@@ -213,9 +214,10 @@ test_for_each_provider! {
         let server_hello_done_message = Message {
             version: ProtocolVersion::TLSv1_2,
             payload: MessagePayload::handshake(HandshakeMessagePayload {
-                        typ: HandshakeType::ServerHelloDone,
-                        payload: HandshakePayload::ServerHelloDone,
-                        }) };
+                typ: HandshakeType::ServerHelloDone,
+                payload: HandshakePayload::ServerHelloDone,
+            }),
+        };
 
         let app_data_ignored = Message {
             version: ProtocolVersion::TLSv1_3,
@@ -224,7 +226,7 @@ test_for_each_provider! {
 
         let end_of_early_data_flight = Message {
             version: ProtocolVersion::TLSv1_3,
-            payload: MessagePayload::HandshakeFlight(Payload::Borrowed(b"\x05\x00\x00\x00"))
+            payload: MessagePayload::HandshakeFlight(Payload::Borrowed(b"\x05\x00\x00\x00")),
         };
 
         // buffered mode
@@ -232,17 +234,26 @@ test_for_each_provider! {
         hhb.add_message(&server_hello_done_message);
         hhb.add_message(&app_data_ignored);
         hhb.add_message(&end_of_early_data_flight);
-        assert_eq!(hhb.start_hash(&SHA256).current_hash().as_ref(),
-                   SHA256.hash(b"\x0e\x00\x00\x00\x05\x00\x00\x00").as_ref());
+        assert_eq!(
+            hhb.start_hash(&SHA256)
+                .current_hash()
+                .as_ref(),
+            SHA256
+                .hash(b"\x0e\x00\x00\x00\x05\x00\x00\x00")
+                .as_ref()
+        );
 
         // non-buffered mode
         let mut hh = HandshakeHashBuffer::new().start_hash(&SHA256);
         hh.add_message(&server_hello_done_message);
         hh.add_message(&app_data_ignored);
         hh.add_message(&end_of_early_data_flight);
-        assert_eq!(hh.current_hash().as_ref(),
-                   SHA256.hash(b"\x0e\x00\x00\x00\x05\x00\x00\x00").as_ref());
-
+        assert_eq!(
+            hh.current_hash().as_ref(),
+            SHA256
+                .hash(b"\x0e\x00\x00\x00\x05\x00\x00\x00")
+                .as_ref()
+        );
     }
 
     #[cfg(feature = "tls12")]
diff --git a/rustls/src/lib.rs b/rustls/src/lib.rs
index 6be3c86120f..73cb6681a22 100644
--- a/rustls/src/lib.rs
+++ b/rustls/src/lib.rs
@@ -599,12 +599,11 @@ pub mod server {
     mod tls13;
 
     pub use builder::WantsServerCert;
-    pub use handy::AlwaysResolvesServerRawPublicKeys;
-    pub use handy::NoServerSessionStorage;
     #[cfg(any(feature = "std", feature = "hashbrown"))]
     pub use handy::ResolvesServerCertUsingSni;
     #[cfg(any(feature = "std", feature = "hashbrown"))]
     pub use handy::ServerSessionMemoryCache;
+    pub use handy::{AlwaysResolvesServerRawPublicKeys, NoServerSessionStorage};
     pub use server_conn::{
         Accepted, ClientHello, ProducesTickets, ResolvesServerCert, ServerConfig,
         ServerConnectionData, StoresServerSessions, UnbufferedServerConnection,
diff --git a/rustls/src/msgs/enums.rs b/rustls/src/msgs/enums.rs
index 358beba1acb..2d9a64adde3 100644
--- a/rustls/src/msgs/enums.rs
+++ b/rustls/src/msgs/enums.rs
@@ -7,7 +7,7 @@ enum_builder! {
     /// The `HashAlgorithm` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub enum HashAlgorithm {
         NONE => 0x00,
         MD5 => 0x01,
@@ -23,7 +23,7 @@ enum_builder! {
     /// The `ClientCertificateType` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub(crate) enum ClientCertificateType {
         RSASign => 0x01,
         DSSSign => 0x02,
@@ -42,7 +42,7 @@ enum_builder! {
     /// The `Compression` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub enum Compression {
         Null => 0x00,
         Deflate => 0x01,
@@ -54,7 +54,7 @@ enum_builder! {
     /// The `AlertLevel` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub enum AlertLevel {
         Warning => 0x01,
         Fatal => 0x02,
@@ -65,7 +65,7 @@ enum_builder! {
     /// The `HeartbeatMessageType` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub(crate) enum HeartbeatMessageType {
         Request => 0x01,
         Response => 0x02,
@@ -76,7 +76,7 @@ enum_builder! {
     /// The `ExtensionType` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U16
+    #[repr(u16)]
     pub enum ExtensionType {
         ServerName => 0x0000,
         MaxFragmentLength => 0x0001,
@@ -155,7 +155,7 @@ enum_builder! {
     /// The `ServerNameType` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub(crate) enum ServerNameType {
         HostName => 0x00,
     }
@@ -170,7 +170,7 @@ enum_builder! {
     /// by a peer during a TLS handshake. It is **not** a list of curves that
     /// Rustls supports. See [`crate::crypto::ring::kx_group`] for the list of supported
     /// elliptic curve groups.
-    @U16
+    #[repr(u16)]
     pub(crate) enum NamedCurve {
         sect163k1 => 0x0001,
         sect163r1 => 0x0002,
@@ -211,7 +211,7 @@ enum_builder! {
     /// The `NamedGroup` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U16
+    #[repr(u16)]
     pub enum NamedGroup {
         secp256r1 => 0x0017,
         secp384r1 => 0x0018,
@@ -240,7 +240,7 @@ enum_builder! {
     /// The `ECPointFormat` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub enum ECPointFormat {
         Uncompressed => 0x00,
         ANSIX962CompressedPrime => 0x01,
@@ -256,7 +256,7 @@ enum_builder! {
     /// The `HeartbeatMode` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub(crate) enum HeartbeatMode {
         PeerAllowedToSend => 0x01,
         PeerNotAllowedToSend => 0x02,
@@ -267,7 +267,7 @@ enum_builder! {
     /// The `ECCurveType` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub(crate) enum ECCurveType {
         ExplicitPrime => 0x01,
         ExplicitChar2 => 0x02,
@@ -279,7 +279,7 @@ enum_builder! {
     /// The `PSKKeyExchangeMode` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub enum PSKKeyExchangeMode {
         PSK_KE => 0x00,
         PSK_DHE_KE => 0x01,
@@ -290,7 +290,7 @@ enum_builder! {
     /// The `KeyUpdateRequest` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub enum KeyUpdateRequest {
         UpdateNotRequested => 0x00,
         UpdateRequested => 0x01,
@@ -301,7 +301,7 @@ enum_builder! {
     /// The `CertificateStatusType` TLS protocol enum.  Values in this enum are taken
     /// from the various RFCs covering TLS, and are listed by IANA.
     /// The `Unknown` item is used when processing unrecognised ordinals.
-    @U8
+    #[repr(u8)]
     pub enum CertificateStatusType {
         OCSP => 0x01,
     }
@@ -313,7 +313,7 @@ enum_builder! {
     ///
     /// [RFC 6091 Section 5]: <https://datatracker.ietf.org/doc/html/rfc6091#section-5>
     /// [RFC 7250 Section 7]: <https://datatracker.ietf.org/doc/html/rfc7250#section-7>
-    @U8
+    #[repr(u8)]
     pub enum CertificateType {
         X509 => 0x00,
         RawPublicKey => 0x02,
@@ -325,7 +325,7 @@ enum_builder! {
     /// Listed by IANA, as specified in [RFC 9180 Section 7.1]
     ///
     /// [RFC 9180 Section 7.1]: <https://datatracker.ietf.org/doc/html/rfc9180#kemid-values>
-    @U16
+    #[repr(u16)]
     pub enum HpkeKem {
         DHKEM_P256_HKDF_SHA256 => 0x0010,
         DHKEM_P384_HKDF_SHA384 => 0x0011,
@@ -340,7 +340,7 @@ enum_builder! {
     /// Listed by IANA, as specified in [RFC 9180 Section 7.2]
     ///
     /// [RFC 9180 Section 7.2]: <https://datatracker.ietf.org/doc/html/rfc9180#name-key-derivation-functions-kd>
-    @U16
+    #[repr(u16)]
     pub enum HpkeKdf {
         HKDF_SHA256 => 0x0001,
         HKDF_SHA384 => 0x0002,
@@ -360,7 +360,7 @@ enum_builder! {
     /// Listed by IANA, as specified in [RFC 9180 Section 7.3]
     ///
     /// [RFC 9180 Section 7.3]: <https://datatracker.ietf.org/doc/html/rfc9180#name-authenticated-encryption-wi>
-    @U16
+    #[repr(u16)]
     pub enum HpkeAead {
         AES_128_GCM => 0x0001,
         AES_256_GCM => 0x0002,
@@ -396,7 +396,7 @@ enum_builder! {
     /// TODO(XXX): Update reference once RFC is published.
     ///
     /// [draft-ietf-tls-esni Section 4]: <https://www.ietf.org/archive/id/draft-ietf-tls-esni-17.html#section-4>
-    @U16
+    #[repr(u16)]
     pub enum EchVersion {
         V18 => 0xfe0d,
     }
diff --git a/rustls/src/msgs/macros.rs b/rustls/src/msgs/macros.rs
index 396c012e868..5fe49ae58eb 100644
--- a/rustls/src/msgs/macros.rs
+++ b/rustls/src/msgs/macros.rs
@@ -1,22 +1,22 @@
 /// A macro which defines an enum type.
 macro_rules! enum_builder {
-    ($(#[$comment:meta])* @U8 $($enum:tt)+) => {
-        enum_builder!(u8: $(#[$comment])* $($enum)+);
-    };
-    ($(#[$comment:meta])* @U16 $($enum:tt)+) => {
-        enum_builder!(u16: $(#[$comment])* $($enum)+);
-    };
     (
-        $uint:ty:
-        $(#[$comment:meta])*
+        $(#[doc = $comment:literal])*
+        #[repr($uint:ty)]
         $enum_vis:vis enum $enum_name:ident
-        { $( $enum_var: ident => $enum_val: expr ),* $(,)? }
+        {
+          $( $enum_var:ident => $enum_val:literal),* $(,)?
+          $( !Debug:
+            $( $enum_var_nd:ident => $enum_val_nd:literal),* $(,)?
+          )?
+        }
     ) => {
-        $(#[$comment])*
+        $(#[doc = $comment])*
         #[non_exhaustive]
-        #[derive(Debug, PartialEq, Eq, Clone, Copy)]
+        #[derive(PartialEq, Eq, Clone, Copy)]
         $enum_vis enum $enum_name {
             $( $enum_var),*
+            $(, $($enum_var_nd),* )?
             ,Unknown($uint)
         }
 
@@ -32,6 +32,7 @@ macro_rules! enum_builder {
             $enum_vis fn as_str(&self) -> Option<&'static str> {
                 match self {
                     $( $enum_name::$enum_var => Some(stringify!($enum_var))),*
+                    $(, $( $enum_name::$enum_var_nd => Some(stringify!($enum_var_nd))),* )?
                     ,$enum_name::Unknown(_) => None,
                 }
             }
@@ -56,6 +57,7 @@ macro_rules! enum_builder {
             fn from(x: $uint) -> Self {
                 match x {
                     $($enum_val => $enum_name::$enum_var),*
+                    $(, $($enum_val_nd => $enum_name::$enum_var_nd),* )?
                     , x => $enum_name::Unknown(x),
                 }
             }
@@ -65,9 +67,19 @@ macro_rules! enum_builder {
             fn from(value: $enum_name) -> Self {
                 match value {
                     $( $enum_name::$enum_var => $enum_val),*
+                    $(, $( $enum_name::$enum_var_nd => $enum_val_nd),* )?
                     ,$enum_name::Unknown(x) => x
                 }
             }
         }
+
+        impl core::fmt::Debug for $enum_name {
+            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+                match self {
+                    $( $enum_name::$enum_var => f.write_str(stringify!($enum_var)), )*
+                    _ => write!(f, "{}(0x{:x?})", stringify!($enum_name), <$uint>::from(*self)),
+                }
+            }
+        }
     };
 }
diff --git a/rustls/src/suites.rs b/rustls/src/suites.rs
index 1a8f49a20f6..edc61e35077 100644
--- a/rustls/src/suites.rs
+++ b/rustls/src/suites.rs
@@ -241,9 +241,10 @@ pub enum ConnectionTrafficSecrets {
 }
 
 test_for_each_provider! {
-    use provider::tls13::*;
     use std::println;
 
+    use provider::tls13::*;
+
     #[test]
     fn test_scs_is_debug() {
         println!("{:?}", provider::ALL_CIPHER_SUITES);
diff --git a/rustls/src/tls12/mod.rs b/rustls/src/tls12/mod.rs
index 30e0a2cc99a..94e4264fcd6 100644
--- a/rustls/src/tls12/mod.rs
+++ b/rustls/src/tls12/mod.rs
@@ -339,10 +339,11 @@ pub(crate) fn decode_kx_params<'a, T: KxDecode<'a>>(
 pub(crate) const DOWNGRADE_SENTINEL: [u8; 8] = [0x44, 0x4f, 0x57, 0x4e, 0x47, 0x52, 0x44, 0x01];
 
 test_for_each_provider! {
+    use provider::kx_group::X25519;
+
     use super::*;
     use crate::common_state::{CommonState, Side};
     use crate::msgs::handshake::{ServerEcdhParams, ServerKeyExchangeParams};
-    use provider::kx_group::X25519;
 
     #[test]
     fn server_ecdhe_remaining_bytes() {
diff --git a/rustls/src/tls13/key_schedule.rs b/rustls/src/tls13/key_schedule.rs
index 0c454157530..05aeba67de3 100644
--- a/rustls/src/tls13/key_schedule.rs
+++ b/rustls/src/tls13/key_schedule.rs
@@ -900,14 +900,15 @@ where
 
 test_for_each_provider! {
     use core::fmt::Debug;
-    use std::vec;
     use std::prelude::v1::*;
+    use std::vec;
 
-    use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind};
     use provider::ring_like::aead;
     use provider::tls13::{
         TLS13_AES_128_GCM_SHA256_INTERNAL, TLS13_CHACHA20_POLY1305_SHA256_INTERNAL,
     };
+
+    use super::{derive_traffic_iv, derive_traffic_key, KeySchedule, SecretKind};
     use crate::KeyLog;
 
     #[test]
@@ -1056,7 +1057,10 @@ test_for_each_provider! {
         let expander = TLS13_AES_128_GCM_SHA256_INTERNAL
             .hkdf_provider
             .expander_for_okm(&traffic_secret);
-        let key = derive_traffic_key(expander.as_ref(), TLS13_AES_128_GCM_SHA256_INTERNAL.aead_alg);
+        let key = derive_traffic_key(
+            expander.as_ref(),
+            TLS13_AES_128_GCM_SHA256_INTERNAL.aead_alg,
+        );
         let key = aead::UnboundKey::new(aead_alg, key.as_ref()).unwrap();
         let seal_output = seal_zeroes(key);
         let expected_key = aead::UnboundKey::new(aead_alg, expected_key).unwrap();
diff --git a/rustls/src/webpki/client_verifier.rs b/rustls/src/webpki/client_verifier.rs
index 42d38c8c34f..f974317f27c 100644
--- a/rustls/src/webpki/client_verifier.rs
+++ b/rustls/src/webpki/client_verifier.rs
@@ -429,16 +429,16 @@ pub(crate) enum AnonymousClientPolicy {
 }
 
 test_for_each_provider! {
-    use super::WebPkiClientVerifier;
-    use crate::server::VerifierBuilderError;
-    use crate::RootCertStore;
+    use std::prelude::v1::*;
+    use std::sync::Arc;
+    use std::{format, println, vec};
 
     use pki_types::pem::PemObject;
     use pki_types::{CertificateDer, CertificateRevocationListDer};
 
-    use std::prelude::v1::*;
-    use std::sync::Arc;
-    use std::{vec, format, println};
+    use super::WebPkiClientVerifier;
+    use crate::server::VerifierBuilderError;
+    use crate::RootCertStore;
 
     fn load_crls(crls_der: &[&[u8]]) -> Vec<CertificateRevocationListDer<'static>> {
         crls_der
diff --git a/rustls/src/webpki/server_verifier.rs b/rustls/src/webpki/server_verifier.rs
index c27fef6009d..7130a0a3546 100644
--- a/rustls/src/webpki/server_verifier.rs
+++ b/rustls/src/webpki/server_verifier.rs
@@ -301,9 +301,9 @@ impl ServerCertVerifier for WebPkiServerVerifier {
 }
 
 test_for_each_provider! {
-    use std::sync::Arc;
-    use std::{vec, println};
     use std::prelude::v1::*;
+    use std::sync::Arc;
+    use std::{println, vec};
 
     use pki_types::pem::PemObject;
     use pki_types::{CertificateDer, CertificateRevocationListDer};


Test patch:
diff --git a/rustls/tests/api.rs b/rustls/tests/api.rs
index a6bd1f8e647..3a5c004b764 100644
--- a/rustls/tests/api.rs
+++ b/rustls/tests/api.rs
@@ -48,7 +48,6 @@ use provider::sign::RsaSigningKey;
 use rustls::ProtocolVersion::TLSv1_2;
 
 mod test_raw_keys {
-    use super::*;
     use rustls::crypto::cipher::{
         InboundOpaqueMessage, MessageDecrypter, MessageEncrypter, OutboundChunks,
         OutboundPlainMessage,
@@ -57,6 +56,8 @@ mod test_raw_keys {
     use rustls::internal::{derive_traffic_iv, derive_traffic_key};
     use rustls::{Connection, Tls13CipherSuite};
 
+    use super::*;
+
     #[test]
     fn successful_raw_key_connection_and_correct_peer_certificates() {
         for kt in ALL_KEY_TYPES {
diff --git a/rustls/tests/unbuffered.rs b/rustls/tests/unbuffered.rs
index f1e3b903390..5a36f42a36a 100644
--- a/rustls/tests/unbuffered.rs
+++ b/rustls/tests/unbuffered.rs
@@ -1298,7 +1298,7 @@ fn server_receives_incorrect_first_handshake_message() {
     assert_eq!(discard, junk_buffer_len);
     assert_eq!(
         format!("{state:?}"),
-        "Err(InappropriateHandshakeMessage { expect_types: [ClientHello], got_type: Unknown(255) })"
+        "Err(InappropriateHandshakeMessage { expect_types: [ClientHello], got_type: HandshakeType(0xff) })"
     );
 
     let UnbufferedStatus { discard, state } = server.process_tls_records(&mut []);