1313
1414//! NATS [Message][crate::Message] headers, modeled loosely after the [http::header] crate.
1515
16+ use bytes:: Bytes ;
1617use std:: { collections:: HashMap , fmt, slice, str:: FromStr } ;
1718
1819/// A struct for handling NATS headers.
@@ -265,7 +266,7 @@ pub trait IntoHeaderName {
265266impl IntoHeaderName for & str {
266267 fn into_header_name ( self ) -> HeaderName {
267268 HeaderName {
268- inner : HeaderRepr :: Custom ( self . to_string ( ) ) ,
269+ inner : HeaderRepr :: Custom ( self . into ( ) ) ,
269270 }
270271 }
271272}
@@ -385,10 +386,47 @@ standard_headers! {
385386 ( NatsExpectedStream , NATS_EXPECTED_STREAM , b"Nats-Expected-Stream" ) ;
386387}
387388
389+ #[ derive( Debug , Hash , PartialEq , Eq , Clone ) ]
390+ struct CustomHeader {
391+ bytes : Bytes ,
392+ }
393+
394+ impl CustomHeader {
395+ #[ inline]
396+ pub ( crate ) const fn from_static ( value : & ' static str ) -> CustomHeader {
397+ CustomHeader {
398+ bytes : Bytes :: from_static ( value. as_bytes ( ) ) ,
399+ }
400+ }
401+
402+ #[ inline]
403+ pub ( crate ) fn as_str ( & self ) -> & str {
404+ unsafe { std:: str:: from_utf8_unchecked ( self . bytes . as_ref ( ) ) }
405+ }
406+ }
407+
408+ impl From < String > for CustomHeader {
409+ #[ inline]
410+ fn from ( value : String ) -> CustomHeader {
411+ CustomHeader {
412+ bytes : Bytes :: from ( value) ,
413+ }
414+ }
415+ }
416+
417+ impl < ' a > From < & ' a str > for CustomHeader {
418+ #[ inline]
419+ fn from ( value : & ' a str ) -> CustomHeader {
420+ CustomHeader {
421+ bytes : Bytes :: copy_from_slice ( value. as_bytes ( ) ) ,
422+ }
423+ }
424+ }
425+
388426#[ derive( Debug , Hash , PartialEq , Eq , Clone ) ]
389427enum HeaderRepr {
390428 Standard ( StandardHeader ) ,
391- Custom ( String ) ,
429+ Custom ( CustomHeader ) ,
392430}
393431
394432#[ derive( Clone , PartialEq , Eq , Hash , Debug ) ]
@@ -397,6 +435,20 @@ pub struct HeaderName {
397435}
398436
399437impl HeaderName {
438+ /// Converts a static string to a NATS header name.
439+ #[ inline]
440+ pub const fn from_static ( value : & ' static str ) -> HeaderName {
441+ if let Some ( standard) = StandardHeader :: from_bytes ( value. as_bytes ( ) ) {
442+ return HeaderName {
443+ inner : HeaderRepr :: Standard ( standard) ,
444+ } ;
445+ }
446+
447+ HeaderName {
448+ inner : HeaderRepr :: Custom ( CustomHeader :: from_static ( value) ) ,
449+ }
450+ }
451+
400452 /// Returns a `str` representation of the header.
401453 #[ inline]
402454 fn as_str ( & self ) -> & str {
@@ -420,7 +472,7 @@ impl FromStr for HeaderName {
420472 inner : HeaderRepr :: Standard ( v) ,
421473 } ) ,
422474 None => Ok ( HeaderName {
423- inner : HeaderRepr :: Custom ( s . to_string ( ) ) ,
475+ inner : HeaderRepr :: Custom ( CustomHeader :: from ( s ) ) ,
424476 } ) ,
425477 }
426478 }
@@ -572,4 +624,12 @@ mod tests {
572624 parsed_header. ok( )
573625 ) ;
574626 }
627+
628+ #[ test]
629+ fn from_static_eq ( ) {
630+ let a = HeaderName :: from_static ( "NATS-Stream" ) ;
631+ let b = HeaderName :: from_static ( "NATS-Stream" ) ;
632+
633+ assert_eq ! ( a, b) ;
634+ }
575635}
0 commit comments