1#![allow(clippy::mutable_key_type)]
20
21use std::{collections::HashMap, fmt, slice::Iter, str::FromStr};
24
25use bytes::Bytes;
26use serde::{Deserialize, Deserializer, Serialize, Serializer};
27
28#[derive(Clone, PartialEq, Eq, Debug, Default)]
48pub struct HeaderMap {
49 inner: HashMap<HeaderName, Vec<HeaderValue>>,
50}
51
52#[derive(Deserialize)]
56#[serde(untagged)]
57enum HeaderMapHelper {
58 Legacy {
60 inner: HashMap<HeaderName, Vec<HeaderValue>>,
61 },
62 Current(HashMap<HeaderName, Vec<HeaderValue>>),
64}
65
66impl<'de> Deserialize<'de> for HeaderMap {
67 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
68 where
69 D: Deserializer<'de>,
70 {
71 let helper = HeaderMapHelper::deserialize(deserializer)?;
73
74 Ok(match helper {
75 HeaderMapHelper::Legacy { inner } => HeaderMap { inner },
76 HeaderMapHelper::Current(inner) => HeaderMap { inner },
77 })
78 }
79}
80
81impl Serialize for HeaderMap {
82 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
83 where
84 S: Serializer,
85 {
86 self.inner.serialize(serializer)
88 }
89}
90
91impl FromIterator<(HeaderName, HeaderValue)> for HeaderMap {
92 fn from_iter<T: IntoIterator<Item = (HeaderName, HeaderValue)>>(iter: T) -> Self {
93 let mut header_map = HeaderMap::new();
94 for (key, value) in iter {
95 header_map.insert(key, value);
96 }
97 header_map
98 }
99}
100
101impl HeaderMap {
102 pub fn iter(&self) -> std::collections::hash_map::Iter<'_, HeaderName, Vec<HeaderValue>> {
103 self.inner.iter()
104 }
105}
106
107pub struct GetAll<'a, T> {
108 inner: Iter<'a, T>,
109}
110
111impl<'a, T> Iterator for GetAll<'a, T> {
112 type Item = &'a T;
113
114 fn next(&mut self) -> Option<Self::Item> {
115 self.inner.next()
116 }
117}
118
119impl HeaderMap {
120 pub fn new() -> Self {
131 HeaderMap::default()
132 }
133
134 pub fn is_empty(&self) -> bool {
150 self.inner.is_empty()
151 }
152
153 pub fn len(&self) -> usize {
154 self.inner.len()
155 }
156}
157
158impl HeaderMap {
159 pub fn insert<K: IntoHeaderName, V: IntoHeaderValue>(&mut self, name: K, value: V) {
170 self.inner
171 .insert(name.into_header_name(), vec![value.into_header_value()]);
172 }
173
174 pub fn append<K: IntoHeaderName, V: IntoHeaderValue>(&mut self, name: K, value: V) {
186 let key = name.into_header_name();
187 let v = self.inner.get_mut(&key);
188 match v {
189 Some(v) => {
190 v.push(value.into_header_value());
191 }
192 None => {
193 self.insert(key, value.into_header_value());
194 }
195 }
196 }
197
198 pub fn get<K: IntoHeaderName>(&self, key: K) -> Option<&HeaderValue> {
210 self.inner
211 .get(&key.into_header_name())
212 .and_then(|x| x.first())
213 }
214
215 pub fn get_last<K: IntoHeaderName>(&self, key: K) -> Option<&HeaderValue> {
227 self.inner
228 .get(&key.into_header_name())
229 .and_then(|x| x.last())
230 }
231
232 pub fn get_all<K: IntoHeaderName>(&self, key: K) -> GetAll<'_, HeaderValue> {
247 let inner = self
248 .inner
249 .get(&key.into_header_name())
250 .map(|x| x.iter())
251 .unwrap_or([].iter());
252
253 GetAll { inner }
254 }
255
256 pub(crate) fn to_bytes(&self) -> Vec<u8> {
257 let mut buf = vec![];
258 buf.extend_from_slice(b"NATS/1.0\r\n");
259 for (k, vs) in &self.inner {
260 for v in vs.iter() {
261 buf.extend_from_slice(k.as_str().as_bytes());
262 buf.extend_from_slice(b": ");
263 buf.extend_from_slice(v.inner.as_bytes());
264 buf.extend_from_slice(b"\r\n");
265 }
266 }
267 buf.extend_from_slice(b"\r\n");
268 buf
269 }
270}
271
272#[derive(Clone, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
284#[serde(transparent)]
285pub struct HeaderValue {
286 inner: String,
287}
288
289impl fmt::Display for HeaderValue {
290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291 fmt::Display::fmt(&self.as_str(), f)
292 }
293}
294
295impl AsRef<[u8]> for HeaderValue {
296 fn as_ref(&self) -> &[u8] {
297 self.inner.as_ref()
298 }
299}
300
301impl AsRef<str> for HeaderValue {
302 fn as_ref(&self) -> &str {
303 self.as_str()
304 }
305}
306
307impl From<i16> for HeaderValue {
308 fn from(v: i16) -> Self {
309 Self {
310 inner: v.to_string(),
311 }
312 }
313}
314
315impl From<i32> for HeaderValue {
316 fn from(v: i32) -> Self {
317 Self {
318 inner: v.to_string(),
319 }
320 }
321}
322
323impl From<i64> for HeaderValue {
324 fn from(v: i64) -> Self {
325 Self {
326 inner: v.to_string(),
327 }
328 }
329}
330
331impl From<isize> for HeaderValue {
332 fn from(v: isize) -> Self {
333 Self {
334 inner: v.to_string(),
335 }
336 }
337}
338
339impl From<u16> for HeaderValue {
340 fn from(v: u16) -> Self {
341 Self {
342 inner: v.to_string(),
343 }
344 }
345}
346
347impl From<u32> for HeaderValue {
348 fn from(v: u32) -> Self {
349 Self {
350 inner: v.to_string(),
351 }
352 }
353}
354
355impl From<u64> for HeaderValue {
356 fn from(v: u64) -> Self {
357 Self {
358 inner: v.to_string(),
359 }
360 }
361}
362
363impl From<usize> for HeaderValue {
364 fn from(v: usize) -> Self {
365 Self {
366 inner: v.to_string(),
367 }
368 }
369}
370
371impl FromStr for HeaderValue {
372 type Err = ParseHeaderValueError;
373
374 fn from_str(s: &str) -> Result<Self, Self::Err> {
375 if s.contains(['\r', '\n']) {
376 return Err(ParseHeaderValueError);
377 }
378
379 Ok(HeaderValue {
380 inner: s.to_string(),
381 })
382 }
383}
384
385impl From<&str> for HeaderValue {
386 fn from(v: &str) -> Self {
387 Self {
388 inner: v.to_string(),
389 }
390 }
391}
392
393impl From<String> for HeaderValue {
394 fn from(inner: String) -> Self {
395 Self { inner }
396 }
397}
398
399impl HeaderValue {
400 pub fn new() -> Self {
401 HeaderValue::default()
402 }
403
404 pub fn as_str(&self) -> &str {
405 self.inner.as_str()
406 }
407}
408
409#[derive(Debug, Clone)]
410pub struct ParseHeaderValueError;
411
412impl fmt::Display for ParseHeaderValueError {
413 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
414 write!(
415 f,
416 r#"invalid character found in header value (value cannot contain '\r' or '\n')"#
417 )
418 }
419}
420
421impl std::error::Error for ParseHeaderValueError {}
422
423pub trait IntoHeaderName {
424 fn into_header_name(self) -> HeaderName;
425}
426
427impl IntoHeaderName for &str {
428 fn into_header_name(self) -> HeaderName {
429 HeaderName {
430 inner: HeaderRepr::Custom(self.into()),
431 }
432 }
433}
434
435impl IntoHeaderName for String {
436 fn into_header_name(self) -> HeaderName {
437 HeaderName {
438 inner: HeaderRepr::Custom(self.into()),
439 }
440 }
441}
442
443impl IntoHeaderName for HeaderName {
444 fn into_header_name(self) -> HeaderName {
445 self
446 }
447}
448
449pub trait IntoHeaderValue {
450 fn into_header_value(self) -> HeaderValue;
451}
452
453impl IntoHeaderValue for &str {
454 fn into_header_value(self) -> HeaderValue {
455 HeaderValue {
456 inner: self.to_string(),
457 }
458 }
459}
460
461impl IntoHeaderValue for String {
462 fn into_header_value(self) -> HeaderValue {
463 HeaderValue { inner: self }
464 }
465}
466
467impl IntoHeaderValue for HeaderValue {
468 fn into_header_value(self) -> HeaderValue {
469 self
470 }
471}
472
473macro_rules! standard_headers {
474 (
475 $(
476 $(#[$docs:meta])*
477 ($variant:ident, $constant:ident, $bytes:literal);
478 )+
479 ) => {
480 #[allow(clippy::enum_variant_names)]
481 #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
482 enum StandardHeader {
483 $(
484 $variant,
485 )+
486 }
487
488 $(
489 $(#[$docs])*
490 pub const $constant: HeaderName = HeaderName {
491 inner: HeaderRepr::Standard(StandardHeader::$variant),
492 };
493 )+
494
495 impl StandardHeader {
496 #[inline]
497 fn as_str(&self) -> &'static str {
498 match *self {
499 $(
500 StandardHeader::$variant => unsafe { std::str::from_utf8_unchecked( $bytes ) },
501 )+
502 }
503 }
504
505 const fn from_bytes(bytes: &[u8]) -> Option<StandardHeader> {
506 match bytes {
507 $(
508 $bytes => Some(StandardHeader::$variant),
509 )+
510 _ => None,
511 }
512 }
513 }
514
515 #[cfg(test)]
516 mod standard_header_tests {
517 use super::HeaderName;
518 use std::str::{self, FromStr};
519
520 const TEST_HEADERS: &'static [(&'static HeaderName, &'static [u8])] = &[
521 $(
522 (&super::$constant, $bytes),
523 )+
524 ];
525
526 #[test]
527 fn from_str() {
528 for &(header, bytes) in TEST_HEADERS {
529 let utf8 = str::from_utf8(bytes).expect("string constants isn't utf8");
530 assert_eq!(HeaderName::from_str(utf8).unwrap(), *header);
531 }
532 }
533 }
534 }
535}
536
537standard_headers! {
539 (NatsStream, NATS_STREAM, b"Nats-Stream");
541 (NatsSequence, NATS_SEQUENCE, b"Nats-Sequence");
543 (NatsTimeStamp, NATS_TIME_STAMP, b"Nats-Time-Stamp");
545 (NatsSubject, NATS_SUBJECT, b"Nats-Subject");
547 (NatsMessageId, NATS_MESSAGE_ID, b"Nats-Msg-Id");
549 (NatsLastStream, NATS_LAST_STREAM, b"Nats-Last-Stream");
551 (NatsLastConsumer, NATS_LAST_CONSUMER, b"Nats-Last-Consumer");
553 (NatsLastSequence, NATS_LAST_SEQUENCE, b"Nats-Last-Sequence");
555 (NatsExpectedLastSubjectSequence, NATS_EXPECTED_LAST_SUBJECT_SEQUENCE, b"Nats-Expected-Last-Subject-Sequence");
557 (NatsExpectedLastMessageId, NATS_EXPECTED_LAST_MESSAGE_ID, b"Nats-Expected-Last-Msg-Id");
559 (NatsExpectedLastSequence, NATS_EXPECTED_LAST_SEQUENCE, b"Nats-Expected-Last-Sequence");
561 (NatsExpectedStream, NATS_EXPECTED_STREAM, b"Nats-Expected-Stream");
563 (NatsMessageTtl, NATS_MESSAGE_TTL, b"Nats-TTL");
565 (NatsMarkerReason, NATS_MARKER_REASON, b"Nats-Marker-Reason");
567}
568
569#[derive(Debug, Hash, PartialEq, Eq, Clone)]
570struct CustomHeader {
571 bytes: Bytes,
572}
573
574impl CustomHeader {
575 #[inline]
576 pub(crate) const fn from_static(value: &'static str) -> CustomHeader {
577 CustomHeader {
578 bytes: Bytes::from_static(value.as_bytes()),
579 }
580 }
581
582 #[inline]
583 pub(crate) fn as_str(&self) -> &str {
584 unsafe { std::str::from_utf8_unchecked(self.bytes.as_ref()) }
585 }
586}
587
588impl From<String> for CustomHeader {
589 #[inline]
590 fn from(value: String) -> CustomHeader {
591 CustomHeader {
592 bytes: Bytes::from(value),
593 }
594 }
595}
596
597impl<'a> From<&'a str> for CustomHeader {
598 #[inline]
599 fn from(value: &'a str) -> CustomHeader {
600 CustomHeader {
601 bytes: Bytes::copy_from_slice(value.as_bytes()),
602 }
603 }
604}
605
606#[derive(Debug, Hash, PartialEq, Eq, Clone)]
607enum HeaderRepr {
608 Standard(StandardHeader),
609 Custom(CustomHeader),
610}
611
612#[derive(Clone, PartialEq, Eq, Hash, Debug)]
622pub struct HeaderName {
623 inner: HeaderRepr,
624}
625
626impl HeaderName {
627 #[inline]
629 pub const fn from_static(value: &'static str) -> HeaderName {
630 if let Some(standard) = StandardHeader::from_bytes(value.as_bytes()) {
631 return HeaderName {
632 inner: HeaderRepr::Standard(standard),
633 };
634 }
635
636 HeaderName {
637 inner: HeaderRepr::Custom(CustomHeader::from_static(value)),
638 }
639 }
640
641 #[inline]
643 fn as_str(&self) -> &str {
644 match self.inner {
645 HeaderRepr::Standard(v) => v.as_str(),
646 HeaderRepr::Custom(ref v) => v.as_str(),
647 }
648 }
649}
650
651impl FromStr for HeaderName {
652 type Err = ParseHeaderNameError;
653
654 fn from_str(s: &str) -> Result<Self, Self::Err> {
655 if s.contains(|c: char| c == ':' || (c as u8) < 33 || (c as u8) > 126) {
656 return Err(ParseHeaderNameError);
657 }
658
659 match StandardHeader::from_bytes(s.as_ref()) {
660 Some(v) => Ok(HeaderName {
661 inner: HeaderRepr::Standard(v),
662 }),
663 None => Ok(HeaderName {
664 inner: HeaderRepr::Custom(CustomHeader::from(s)),
665 }),
666 }
667 }
668}
669
670impl fmt::Display for HeaderName {
671 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
672 fmt::Display::fmt(&self.as_str(), f)
673 }
674}
675
676impl AsRef<[u8]> for HeaderName {
677 fn as_ref(&self) -> &[u8] {
678 self.as_str().as_bytes()
679 }
680}
681
682impl AsRef<str> for HeaderName {
683 fn as_ref(&self) -> &str {
684 self.as_str()
685 }
686}
687
688impl Serialize for HeaderName {
689 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
690 where
691 S: serde::Serializer,
692 {
693 serializer.serialize_str(self.as_str())
694 }
695}
696
697impl<'de> Deserialize<'de> for HeaderName {
698 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
699 where
700 D: serde::Deserializer<'de>,
701 {
702 String::deserialize(deserializer)?
703 .parse()
704 .map_err(serde::de::Error::custom)
705 }
706}
707
708#[derive(Debug, Clone)]
709pub struct ParseHeaderNameError;
710
711impl std::fmt::Display for ParseHeaderNameError {
712 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
713 write!(f, "invalid header name (name cannot contain non-ascii alphanumeric characters other than '-')")
714 }
715}
716
717impl std::error::Error for ParseHeaderNameError {}
718
719#[cfg(test)]
720mod tests {
721 use super::{HeaderMap, HeaderName, HeaderValue, IntoHeaderName, IntoHeaderValue};
722 use std::str::{from_utf8, FromStr};
723
724 #[test]
725 fn try_from() {
726 let mut headers = HeaderMap::new();
727 headers.insert("name", "something".parse::<HeaderValue>().unwrap());
728 headers.insert("name", "something2");
729 }
730
731 #[test]
732 fn append() {
733 let mut headers = HeaderMap::new();
734 headers.append("Key", "value");
735 headers.append("Key", "second_value");
736
737 let mut result = headers.get_all("Key");
738
739 assert_eq!(
740 result.next().unwrap(),
741 &HeaderValue::from_str("value").unwrap()
742 );
743
744 assert_eq!(
745 result.next().unwrap(),
746 &HeaderValue::from_str("second_value").unwrap()
747 );
748
749 assert_eq!(result.next(), None);
750 }
751
752 #[test]
753 fn get_string() {
754 let mut headers = HeaderMap::new();
755 headers.append("Key", "value");
756 headers.append("Key", "other");
757
758 assert_eq!(headers.get("Key").unwrap().to_string(), "value");
759
760 let key: String = headers.get("Key").unwrap().as_str().into();
761 assert_eq!(key, "value".to_string());
762
763 let key: String = headers.get("Key").unwrap().as_str().to_owned();
764 assert_eq!(key, "value".to_string());
765
766 assert_eq!(headers.get("Key").unwrap().as_str(), "value");
767
768 let key: String = headers.get_last("Key").unwrap().as_str().into();
769 assert_eq!(key, "other".to_string());
770 }
771
772 #[test]
773 fn insert() {
774 let mut headers = HeaderMap::new();
775 headers.insert("Key", "Value");
776
777 let mut result = headers.get_all("Key");
778
779 assert_eq!(
780 result.next().unwrap(),
781 &HeaderValue::from_str("Value").unwrap()
782 );
783 assert_eq!(result.next(), None);
784 }
785
786 #[test]
787 fn serialize() {
788 let mut headers = HeaderMap::new();
789 headers.append("Key", "value");
790 headers.append("Key", "second_value");
791 headers.insert("Second", "SecondValue");
792
793 let bytes = headers.to_bytes();
794
795 println!("bytes: {:?}", from_utf8(&bytes));
796 }
797
798 #[test]
799 fn is_empty() {
800 let mut headers = HeaderMap::new();
801 assert!(headers.is_empty());
802
803 headers.append("Key", "value");
804 headers.append("Key", "second_value");
805 headers.insert("Second", "SecondValue");
806 assert!(!headers.is_empty());
807 }
808
809 #[test]
810 fn parse_value() {
811 assert!("Foo\r".parse::<HeaderValue>().is_err());
812 assert!("Foo\n".parse::<HeaderValue>().is_err());
813 assert!("Foo\r\n".parse::<HeaderValue>().is_err());
814 }
815
816 #[test]
817 fn valid_header_name() {
818 let valid_header_name = "X-Custom-Header";
819 let parsed_header = HeaderName::from_str(valid_header_name);
820
821 assert!(
822 parsed_header.is_ok(),
823 "Expected Ok(HeaderName), but got an error: {:?}",
824 parsed_header.err()
825 );
826 }
827
828 #[test]
829 fn dollar_header_name() {
830 let valid_header_name = "$X_Custom_Header";
831 let parsed_header = HeaderName::from_str(valid_header_name);
832
833 assert!(
834 parsed_header.is_ok(),
835 "Expected Ok(HeaderName), but got an error: {:?}",
836 parsed_header.err()
837 );
838 }
839
840 #[test]
841 fn invalid_header_name_with_space() {
842 let invalid_header_name = "X Custom Header";
843 let parsed_header = HeaderName::from_str(invalid_header_name);
844
845 assert!(
846 parsed_header.is_err(),
847 "Expected Err(InvalidHeaderNameError), but got Ok: {:?}",
848 parsed_header.ok()
849 );
850 }
851
852 #[test]
853 fn invalid_header_name_with_special_chars() {
854 let invalid_header_name = "X-Header:";
855 let parsed_header = HeaderName::from_str(invalid_header_name);
856
857 assert!(
858 parsed_header.is_err(),
859 "Expected Err(InvalidHeaderNameError), but got Ok: {:?}",
860 parsed_header.ok()
861 );
862 }
863
864 #[test]
865 fn from_static_eq() {
866 let a = HeaderName::from_static("NATS-Stream");
867 let b = HeaderName::from_static("NATS-Stream");
868
869 assert_eq!(a, b);
870 }
871
872 #[test]
873 fn header_name_serde() {
874 let raw = "Nats-Stream";
875 let raw_json = "\"Nats-Stream\"";
876 let header = HeaderName::from_static(raw);
877
878 assert_eq!(serde_json::to_string(&header).unwrap(), raw_json);
880 assert_eq!(
881 serde_json::from_str::<HeaderName>(raw_json).unwrap(),
882 header
883 );
884 }
885
886 #[test]
887 fn header_name_from_string() {
888 let string = "NATS-Stream".to_string();
889 let name = string.into_header_name();
890
891 assert_eq!("NATS-Stream", name.as_str());
892 }
893
894 #[test]
895 fn header_value_from_string_with_trait() {
896 let string = "some value".to_string();
897
898 let value = string.into_header_value();
899
900 assert_eq!("some value", value.as_str());
901 }
902
903 #[test]
904 fn header_value_from_string() {
905 let string = "some value".to_string();
906
907 let value: HeaderValue = string.into();
908
909 assert_eq!("some value", value.as_str());
910 }
911
912 #[test]
913 fn header_map_backward_compatible_deserialization() {
914 let new_format_json =
916 r#"{"Content-Type": ["application/json"], "Authorization": ["Bearer token"]}"#;
917 let header_map: HeaderMap = serde_json::from_str(new_format_json).unwrap();
918
919 assert_eq!(
920 header_map.get("Content-Type").unwrap().as_str(),
921 "application/json"
922 );
923 assert_eq!(
924 header_map.get("Authorization").unwrap().as_str(),
925 "Bearer token"
926 );
927
928 let legacy_format_json = r#"{"inner": {"Content-Type": ["application/json"], "Authorization": ["Bearer token"]}}"#;
930 let header_map_legacy: HeaderMap = serde_json::from_str(legacy_format_json).unwrap();
931
932 assert_eq!(
933 header_map_legacy.get("Content-Type").unwrap().as_str(),
934 "application/json"
935 );
936 assert_eq!(
937 header_map_legacy.get("Authorization").unwrap().as_str(),
938 "Bearer token"
939 );
940
941 assert_eq!(header_map, header_map_legacy);
943 }
944
945 #[test]
946 fn header_map_serialization_new_format() {
947 let mut headers = HeaderMap::new();
949 headers.insert("Content-Type", "application/json");
950 headers.insert("Authorization", "Bearer token");
951
952 let serialized = serde_json::to_string(&headers).unwrap();
953
954 assert!(!serialized.contains("inner"));
956
957 let deserialized: HeaderMap = serde_json::from_str(&serialized).unwrap();
959 assert_eq!(headers, deserialized);
960 }
961
962 #[test]
963 fn header_map_roundtrip_compatibility() {
964 let mut original = HeaderMap::new();
966 original.insert("X-Custom-Header", "custom-value");
967 original.append("Multi-Value", "value1");
968 original.append("Multi-Value", "value2");
969
970 let new_serialized = serde_json::to_string(&original).unwrap();
972 let new_deserialized: HeaderMap = serde_json::from_str(&new_serialized).unwrap();
973 assert_eq!(original, new_deserialized);
974
975 let legacy_json = format!(r#"{{"inner": {}}}"#, new_serialized);
977 let legacy_deserialized: HeaderMap = serde_json::from_str(&legacy_json).unwrap();
978 assert_eq!(original, legacy_deserialized);
979 }
980
981 #[test]
982 fn header_map_invalid_format_error() {
983 let invalid_json = r#"{"not_inner_or_direct": {"Content-Type": ["application/json"]}}"#;
985 let result = serde_json::from_str::<HeaderMap>(invalid_json);
986 assert!(result.is_err());
987
988 let error_message = result.unwrap_err().to_string();
989 assert!(error_message.contains("did not match any variant"));
991 }
992
993 #[test]
994 fn header_map_empty_cases() {
995 let empty = HeaderMap::new();
997 let serialized = serde_json::to_string(&empty).unwrap();
998 assert_eq!(serialized, "{}");
999
1000 let deserialized: HeaderMap = serde_json::from_str("{}").unwrap();
1001 assert!(deserialized.is_empty());
1002
1003 let legacy_empty = r#"{"inner": {}}"#;
1005 let legacy_deserialized: HeaderMap = serde_json::from_str(legacy_empty).unwrap();
1006 assert!(legacy_deserialized.is_empty());
1007 }
1008
1009 #[test]
1010 fn header_map_mixed_legacy_detection() {
1011 let json_with_inner_header =
1014 r#"{"inner": ["some-value"], "Other-Header": ["other-value"]}"#;
1015 let header_map: HeaderMap = serde_json::from_str(json_with_inner_header).unwrap();
1016
1017 assert_eq!(header_map.len(), 2);
1019 assert_eq!(header_map.get("inner").unwrap().as_str(), "some-value");
1020 assert_eq!(
1021 header_map.get("Other-Header").unwrap().as_str(),
1022 "other-value"
1023 );
1024 }
1025
1026 #[test]
1027 fn header_map_large_headers() {
1028 let mut headers = HeaderMap::new();
1030 for i in 0..100 {
1031 headers.insert(format!("Header-{}", i), format!("Value-{}", i));
1032 }
1033
1034 let serialized = serde_json::to_string(&headers).unwrap();
1035 let deserialized: HeaderMap = serde_json::from_str(&serialized).unwrap();
1036
1037 assert_eq!(headers.len(), deserialized.len());
1038 for i in 0..100 {
1039 assert_eq!(
1040 deserialized
1041 .get(format!("Header-{}", i).as_str())
1042 .unwrap()
1043 .as_str(),
1044 format!("Value-{}", i)
1045 );
1046 }
1047 }
1048}