Skip to main content

cloud_sdk_testkit/
body.rs

1//! Bounded fixture response bodies.
2
3use core::fmt;
4
5/// Maximum fixture body length, including one byte beyond the common 8 MiB
6/// response-policy ceiling for oversized-input tests.
7pub const MAX_FIXTURE_BODY_BYTES: usize = 8_388_609;
8
9/// Fixture body construction or write error.
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub enum FixtureBodyError {
12    /// The represented body exceeds [`MAX_FIXTURE_BODY_BYTES`].
13    TooLarge,
14    /// The caller-owned destination is smaller than the represented body.
15    OutputTooSmall,
16}
17
18/// Borrowed or compact repeated-byte fixture body.
19#[derive(Clone, Copy, Eq, PartialEq)]
20pub enum FixtureBody<'a> {
21    /// Borrowed response bytes.
22    Bytes(&'a [u8]),
23    /// A repeated byte with a bounded logical length.
24    Repeated {
25        /// Byte copied into the response destination.
26        byte: u8,
27        /// Logical body length.
28        len: usize,
29    },
30}
31
32impl<'a> FixtureBody<'a> {
33    /// Creates a bounded borrowed body.
34    pub const fn new(bytes: &'a [u8]) -> Result<Self, FixtureBodyError> {
35        if bytes.len() > MAX_FIXTURE_BODY_BYTES {
36            return Err(FixtureBodyError::TooLarge);
37        }
38        Ok(Self::Bytes(bytes))
39    }
40
41    /// Creates a compact repeated-byte body.
42    pub const fn repeated(byte: u8, len: usize) -> Result<Self, FixtureBodyError> {
43        if len > MAX_FIXTURE_BODY_BYTES {
44            return Err(FixtureBodyError::TooLarge);
45        }
46        Ok(Self::Repeated { byte, len })
47    }
48
49    /// Returns the represented body length.
50    #[must_use]
51    pub const fn len(self) -> usize {
52        match self {
53            Self::Bytes(bytes) => bytes.len(),
54            Self::Repeated { len, .. } => len,
55        }
56    }
57
58    /// Reports whether the represented body is empty.
59    #[must_use]
60    pub const fn is_empty(self) -> bool {
61        self.len() == 0
62    }
63
64    /// Returns borrowed bytes when this is a literal fixture.
65    #[must_use]
66    pub const fn as_bytes(self) -> Option<&'a [u8]> {
67        match self {
68            Self::Bytes(bytes) => Some(bytes),
69            Self::Repeated { .. } => None,
70        }
71    }
72
73    /// Atomically writes the represented body into a caller-owned buffer.
74    pub fn write_to(self, output: &mut [u8]) -> Result<usize, FixtureBodyError> {
75        let len = self.len();
76        let target = output
77            .get_mut(..len)
78            .ok_or(FixtureBodyError::OutputTooSmall)?;
79        match self {
80            Self::Bytes(bytes) => target.copy_from_slice(bytes),
81            Self::Repeated { byte, .. } => target.fill(byte),
82        }
83        Ok(len)
84    }
85}
86
87impl fmt::Debug for FixtureBody<'_> {
88    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
89        formatter
90            .debug_struct("FixtureBody")
91            .field("contents", &"[redacted]")
92            .field("len", &self.len())
93            .finish()
94    }
95}