Coverage Report

Created: 2025-10-31 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/hyper-1.6.0/src/body/length.rs
Line
Count
Source
1
use std::fmt;
2
3
#[derive(Clone, Copy, PartialEq, Eq)]
4
pub(crate) struct DecodedLength(u64);
5
6
#[cfg(any(feature = "http1", feature = "http2"))]
7
impl From<Option<u64>> for DecodedLength {
8
0
    fn from(len: Option<u64>) -> Self {
9
0
        len.and_then(|len| {
10
            // If the length is u64::MAX, oh well, just reported chunked.
11
0
            Self::checked_new(len).ok()
12
0
        })
13
0
        .unwrap_or(DecodedLength::CHUNKED)
14
0
    }
15
}
16
17
#[cfg(any(feature = "http1", feature = "http2", test))]
18
const MAX_LEN: u64 = u64::MAX - 2;
19
20
impl DecodedLength {
21
    pub(crate) const CLOSE_DELIMITED: DecodedLength = DecodedLength(u64::MAX);
22
    pub(crate) const CHUNKED: DecodedLength = DecodedLength(u64::MAX - 1);
23
    pub(crate) const ZERO: DecodedLength = DecodedLength(0);
24
25
    #[cfg(test)]
26
    pub(crate) fn new(len: u64) -> Self {
27
        debug_assert!(len <= MAX_LEN);
28
        DecodedLength(len)
29
    }
30
31
    /// Takes the length as a content-length without other checks.
32
    ///
33
    /// Should only be called if previously confirmed this isn't
34
    /// CLOSE_DELIMITED or CHUNKED.
35
    #[inline]
36
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http1"))]
37
0
    pub(crate) fn danger_len(self) -> u64 {
38
0
        debug_assert!(self.0 < Self::CHUNKED.0);
39
0
        self.0
40
0
    }
41
42
    /// Converts to an Option<u64> representing a Known or Unknown length.
43
    #[cfg(all(
44
        any(feature = "http1", feature = "http2"),
45
        any(feature = "client", feature = "server")
46
    ))]
47
0
    pub(crate) fn into_opt(self) -> Option<u64> {
48
0
        match self {
49
0
            DecodedLength::CHUNKED | DecodedLength::CLOSE_DELIMITED => None,
50
0
            DecodedLength(known) => Some(known),
51
        }
52
0
    }
53
54
    /// Checks the `u64` is within the maximum allowed for content-length.
55
    #[cfg(any(feature = "http1", feature = "http2"))]
56
0
    pub(crate) fn checked_new(len: u64) -> Result<Self, crate::error::Parse> {
57
0
        if len <= MAX_LEN {
58
0
            Ok(DecodedLength(len))
59
        } else {
60
            warn!("content-length bigger than maximum: {} > {}", len, MAX_LEN);
61
0
            Err(crate::error::Parse::TooLarge)
62
        }
63
0
    }
64
65
    #[cfg(all(
66
        any(feature = "http1", feature = "http2"),
67
        any(feature = "client", feature = "server")
68
    ))]
69
0
    pub(crate) fn sub_if(&mut self, amt: u64) {
70
0
        match *self {
71
0
            DecodedLength::CHUNKED | DecodedLength::CLOSE_DELIMITED => (),
72
0
            DecodedLength(ref mut known) => {
73
0
                *known -= amt;
74
0
            }
75
        }
76
0
    }
77
78
    /// Returns whether this represents an exact length.
79
    ///
80
    /// This includes 0, which of course is an exact known length.
81
    ///
82
    /// It would return false if "chunked" or otherwise size-unknown.
83
    #[cfg(all(any(feature = "client", feature = "server"), feature = "http2"))]
84
    pub(crate) fn is_exact(&self) -> bool {
85
        self.0 <= MAX_LEN
86
    }
87
}
88
89
impl fmt::Debug for DecodedLength {
90
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91
0
        match *self {
92
0
            DecodedLength::CLOSE_DELIMITED => f.write_str("CLOSE_DELIMITED"),
93
0
            DecodedLength::CHUNKED => f.write_str("CHUNKED"),
94
0
            DecodedLength(n) => f.debug_tuple("DecodedLength").field(&n).finish(),
95
        }
96
0
    }
97
}
98
99
impl fmt::Display for DecodedLength {
100
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
101
0
        match *self {
102
0
            DecodedLength::CLOSE_DELIMITED => f.write_str("close-delimited"),
103
0
            DecodedLength::CHUNKED => f.write_str("chunked encoding"),
104
0
            DecodedLength::ZERO => f.write_str("empty"),
105
0
            DecodedLength(n) => write!(f, "content-length ({} bytes)", n),
106
        }
107
0
    }
108
}
109
110
#[cfg(test)]
111
mod tests {
112
    use super::*;
113
114
    #[test]
115
    fn sub_if_known() {
116
        let mut len = DecodedLength::new(30);
117
        len.sub_if(20);
118
119
        assert_eq!(len.0, 10);
120
    }
121
122
    #[test]
123
    fn sub_if_chunked() {
124
        let mut len = DecodedLength::CHUNKED;
125
        len.sub_if(20);
126
127
        assert_eq!(len, DecodedLength::CHUNKED);
128
    }
129
}