Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  reader.rs   Sprache: unbekannt

 
Spracherkennung für: .rs vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

//! Byte reader.
use core::ops::Range;

use duplicate::duplicate_item;
use educe::Educe;

use crate::utils::debug::debug_slice_length;

/// An error occurred while reading bytes.
#[derive(Clone, Debug, thiserror::Error)]
pub enum ByteReaderError {
    /// Provided relative offset would move the reader offset out of bounds.
    #[error(
        "Relative offset out of bounds: relative-offset={relative_offset}, offset={offset}, length={length}"
    )]
    InvalidRelativeOffset {
        /// Requested relative offset to move within the data buffer.
        relative_offset: isize,
        /// Current offset in the underlying data buffer.
        offset: usize,
        /// Total length of the underlying data buffer.
        length: usize,
    },

    /// Insufficient remaining bytes left for the desired operation
    #[error("Insufficient bytes left: requested={requested}, remaining={remaining}, offset={offset}")]
    InsufficientRemaining {
        /// Requested amount of bytes to be read.
        requested: usize,
        /// Remaining amount of bytes available to read.
        remaining: usize,
        /// Current offset in the underlying data buffer.
        offset: usize,
    },

    /// The reader was expected to be consumed but has remaining bytes left
    #[error("Unexpected remaining bytes left: remaining={remaining}, length={length}")]
    UnexpectedRemaining {
        /// Remaining amount of bytes left to read.
        remaining: usize,
        /// Total length of the underlying data buffer.
        length: usize,
    },
}

pub(crate) struct ByteReaderContainer<T> {
    buffer: T,
    offset: usize,
}

pub(crate) trait ByteReader {
    type Buffer;

    /// Writer type used for [`ByteReader::run`].
    type RunReader<'run>: ByteReader;

    /// Writer type used for [`ByteReader::run_at`].
    type RunAtReader<'run_at>: ByteReader;

    /// Return the current offset of the reader.
    #[expect(dead_code, reason = "Will use later")]
    fn offset(&self) -> usize;

    /// Return the amount of remaining bytes in the reader.
    fn remaining(&self) -> usize;

    /// Skip over a specific amount of bytes.
    ///
    /// # Error
    ///
    /// Returns [`ByteReaderError::InsufficientRemaining`] if the reader is does not have sufficient
    /// remaining bytes left.
    fn skip(&mut self, length: usize) -> Result<(), ByteReaderError>;

    /// Run an arbitrary operation on the reader.
    ///
    /// This is useful when chaining multiple read operations that can be mapped to a single error.
    ///
    /// # Error
    ///
    /// Returns any [`ByteReaderError`] returned by the operation.
    fn run<T, F: FnOnce(&mut Self::RunReader<'_>) -> Result<T, ByteReaderError>>(
        &mut self,
        op: F,
    ) -> Result<T, ByteReaderError>;

    /// Run an arbitrary operation on the reader and take it.
    ///
    /// Note: This does not call [`ByteReader::expect_consumed`] at the end of the function!
    ///
    /// This is useful when chaining multiple read operations that can be mapped to a single error.
    ///
    /// # Error
    ///
    /// Returns any [`ByteReaderError`] returned by the operation.
    fn run_owned<T, F: FnOnce(Self::RunReader<'_>) -> Result<T, ByteReaderError>>(
        self,
        op: F,
    ) -> Result<T, ByteReaderError>;

    /// Run an arbitrary operation on the reader at a relative offset to the current offset in a
    /// child reader instance. The parent reader will maintain the current offset.
    ///
    /// # Error
    ///
    /// Returns [`ByteReaderError::InsufficientRemaining`] if the reader offset would move of the
    /// underlying data boundary.
    ///
    /// Returns any [`ByteReaderError`] returned by the operation.
    fn run_at<T, F: FnOnce(Self::RunAtReader<'_>) -> Result<T, ByteReaderError>>(
        &mut self,
        relative_offset: isize,
        op: F,
    ) -> Result<T, ByteReaderError>;

    /// Expect the reader to have consumed all data (i.e. [`Self::remaining`] is `0`), returning the
    /// underlying buffer.
    ///
    /// # Error
    ///
    /// Returns [`ByteReaderError::UnexpectedRemaining`] if the reader is not yet consumed.
    fn expect_consumed(self) -> Result<Self::Buffer, ByteReaderError>;

    /// Read a specific amount of bytes.
    ///
    /// # Error
    ///
    /// Returns [`ByteReaderError::InsufficientRemaining`] if the reader is does not have sufficient
    /// remaining bytes left.
    fn read(&mut self, length: usize) -> Result<&[u8], ByteReaderError>;

    /// Read a specific amount of bytes, yielding the offset range of the slice.
    ///
    /// This can be used when wrapping a [`ByteReader`] around a [`Vec<u8>`] to get a mutable slice
    /// over the returned range at after consuming the [`ByteReader`].
    ///
    /// # Error
    ///
    /// Returns [`ByteReaderError::InsufficientRemaining`] if the reader is does not have sufficient
    /// remaining bytes left.
    fn read_range(&mut self, length: usize) -> Result<Range<usize>, ByteReaderError>;

    /// Read all remaining bytes in the reader.
    fn read_remaining(&mut self) -> &[u8];

    /// Read a specific amount of bytes, yielding a fixed-size slice.
    ///
    /// # Error
    ///
    /// Returns [`ByteReaderError::InsufficientRemaining`] if the reader is does not have sufficient
    /// remaining bytes left.
    #[inline]
    fn read_fixed<const LENGTH: usize>(&mut self) -> Result<[u8; LENGTH], ByteReaderError> {
        let bytes = self.read(LENGTH)?;
        // Note: The `.read` call above ensures that the `expect` call does not fail
        Ok(bytes
            .try_into()
            .expect("[offset..offset + LENGTH] must be LENGTH bytes"))
    }

    /// Read a u8.
    ///
    /// # Error
    ///
    /// Returns [`ByteReaderError::InsufficientRemaining`] if the reader is does not have sufficient
    /// remaining bytes left.
    #[inline]
    fn read_u8(&mut self) -> Result<u8, ByteReaderError> {
        self.read_fixed::<1>().map(|bytes| bytes[0])
    }

    /// Read a u16 (little endian).
    ///
    /// # Error
    ///
    /// Returns [`ByteReaderError::InsufficientRemaining`] if the reader is does not have sufficient
    /// remaining bytes left.
    #[inline]
    fn read_u16_le(&mut self) -> Result<u16, ByteReaderError> {
        let bytes = self.read_fixed::<2>()?;
        Ok(u16::from_le_bytes(bytes))
    }

    /// Read a u32 (little endian).
    ///
    /// # Error
    ///
    /// Returns [`ByteReaderError::InsufficientRemaining`] if the reader is does not have sufficient
    /// remaining bytes left.
    #[inline]
    fn read_u32_le(&mut self) -> Result<u32, ByteReaderError> {
        let bytes = self.read_fixed::<4>()?;
        Ok(u32::from_le_bytes(bytes))
    }

    /// Read a u64 (little endian).
    ///
    /// # Error
    ///
    /// Returns [`ByteReaderError::InsufficientRemaining`] if the reader is does not have sufficient
    /// remaining bytes left.
    #[inline]
    fn read_u64_le(&mut self) -> Result<u64, ByteReaderError> {
        let bytes = self.read_fixed::<8>()?;
        Ok(u64::from_le_bytes(bytes))
    }
}

/// Contains a range reference to an encrypted section of data.
#[derive(Clone, Educe)]
#[educe(Debug)]
pub(crate) struct EncryptedDataRange<const TAG_LENGTH: usize> {
    /// Tag for the decryption process
    #[educe(Debug(method(debug_slice_length)))]
    pub(crate) tag: [u8; TAG_LENGTH],

    /// Data range reference
    pub(crate) data: Range<usize>,
}

/// Extension to read a specific amount of encrypted bytes and its encryption tag.
pub(crate) trait EncryptedDataRangeReader<const TAG_LENGTH: usize> {
    /// Read a specific amount of encrypted bytes and its encryption tag, yielding the offset range of the
    /// slice and the tag at once.
    ///
    /// Note: `length` should NOT include the length of the tag.
    ///
    /// IMPORTANT: This may only be used for encryption implementations with a **prefix tag** (e.g.
    /// Salsa20Poly1305).
    ///
    /// # Error
    ///
    /// Returns [`ByteReaderError::InsufficientRemaining`] if the reader is does not have sufficient remaining
    /// bytes left.
    fn read_encrypted_data_range_tag_ahead(
        &mut self,
        length: usize,
    ) -> Result<EncryptedDataRange<TAG_LENGTH>, ByteReaderError>;
}
impl<TReader: ByteReader, const TAG_LENGTH: usize> EncryptedDataRangeReader<TAG_LENGTH> for TReader {
    fn read_encrypted_data_range_tag_ahead(
        &mut self,
        length: usize,
    ) -> Result<EncryptedDataRange<TAG_LENGTH>, ByteReaderError> {
        Ok(EncryptedDataRange {
            tag: self.read_fixed::<TAG_LENGTH>()?.to_owned(),
            data: self.read_range(length)?,
        })
    }
}

#[duplicate_item(
    buffer_type;
    [ &'buffer [u8] ];
    [ Vec<u8> ];
    [ &'buffer Vec<u8> ];
)]
#[expect(clippy::allow_attributes, reason = "duplicate shenanigans")]
#[allow(clippy::extra_unused_lifetimes, reason = "Abstracted duplicate")]
impl<'buffer> ByteReaderContainer<buffer_type> {
    /// Create a new [`ByteReader`] starting at the **beginning** of the `buffer`.
    #[inline]
    #[allow(dead_code, reason = "Will use later")]
    pub(crate) const fn new(buffer: buffer_type) -> Self {
        Self { buffer, offset: 0 }
    }

    /// Consume this reader, returning the underlying buffer.
    #[inline]
    #[allow(dead_code, reason = "Will use later")]
    pub(crate) fn into_inner(self) -> buffer_type {
        self.buffer
    }
}

impl ByteReaderContainer<&[u8]> {
    #[inline]
    fn insufficient_remaining(&self, length: usize) -> ByteReaderError {
        ByteReaderError::InsufficientRemaining {
            requested: length,
            remaining: self.remaining(),
            offset: self.offset,
        }
    }
}

impl<'buffer> ByteReader for ByteReaderContainer<&'buffer [u8]> {
    type Buffer = &'buffer [u8];
    type RunAtReader<'run_at> = ByteReaderContainer<&'run_at [u8]>;
    type RunReader<'run> = ByteReaderContainer<&'run [u8]>;

    #[inline]
    fn offset(&self) -> usize {
        self.offset
    }

    #[inline]
    fn remaining(&self) -> usize {
        #[expect(clippy::panic, reason = "Impossible")]
        let Some(remaining) = self.buffer.len().checked_sub(self.offset) else {
            panic!("length must be >= offset and therefore usize")
        };
        remaining
    }

    #[inline]
    fn skip(&mut self, length: usize) -> Result<(), ByteReaderError> {
        let insufficient_remaining = || self.insufficient_remaining(length);

        // Calculate new offset
        let updated_offset = self
            .offset
            .checked_add(length)
            .ok_or_else(insufficient_remaining)?;

        // Check if there are sufficient remaining bytes left
        if updated_offset > self.buffer.len() {
            return Err(insufficient_remaining());
        }

        // Update offset
        self.offset = updated_offset;
        Ok(())
    }

    #[inline]
    fn run<T, F: FnOnce(&mut Self::RunReader<'_>) -> Result<T, ByteReaderError>>(
        &mut self,
        op: F,
    ) -> Result<T, ByteReaderError> {
        op(self)
    }

    #[inline]
    fn run_owned<T, F: FnOnce(Self) -> Result<T, ByteReaderError>>(
        self,
        op: F,
    ) -> Result<T, ByteReaderError> {
        op(self)
    }

    #[inline]
    fn run_at<T, F: FnOnce(Self::RunAtReader<'_>) -> Result<T, ByteReaderError>>(
        &mut self,
        relative_offset: isize,
        op: F,
    ) -> Result<T, ByteReaderError> {
        let invalid_offset = || ByteReaderError::InvalidRelativeOffset {
            relative_offset,
            offset: self.offset,
            length: self.buffer.len(),
        };

        // Calculate new offset
        let updated_offset: usize = relative_offset
            .checked_add(self.offset.try_into().map_err(|_| invalid_offset())?)
            .ok_or_else(invalid_offset)?
            .try_into()
            .map_err(|_| invalid_offset())?;
        if updated_offset > self.buffer.len() {
            return Err(invalid_offset());
        }

        // Run
        op(Self::RunAtReader {
            buffer: self.buffer,
            offset: updated_offset,
        })
    }

    #[inline]
    fn expect_consumed(self) -> Result<Self::Buffer, ByteReaderError> {
        if self.offset != self.buffer.len() {
            return Err(ByteReaderError::UnexpectedRemaining {
                remaining: self.remaining(),
                length: self.buffer.len(),
            });
        }
        Ok(self.buffer)
    }

    #[inline]
    fn read(&mut self, length: usize) -> Result<&'buffer [u8], ByteReaderError> {
        let insufficient_remaining = || self.insufficient_remaining(length);

        // Calculate new offset
        let updated_offset = self
            .offset
            .checked_add(length)
            .ok_or_else(insufficient_remaining)?;

        // Attempt to read
        let bytes = self
            .buffer
            .get(self.offset..updated_offset)
            .ok_or_else(insufficient_remaining)?;

        // Update offset and return read bytes
        self.offset = updated_offset;
        Ok(bytes)
    }

    #[inline]
    fn read_range(&mut self, length: usize) -> Result<Range<usize>, ByteReaderError> {
        let insufficient_remaining = || self.insufficient_remaining(length);

        // Calculate new offset
        let updated_offset = self
            .offset
            .checked_add(length)
            .ok_or_else(insufficient_remaining)?;

        // Check if there are sufficient remaining bytes left
        if updated_offset > self.buffer.len() {
            return Err(insufficient_remaining());
        }

        // Update offset and return range
        let range = self.offset..updated_offset;
        self.offset = updated_offset;
        Ok(range)
    }

    #[inline]
    fn read_remaining(&mut self) -> &'buffer [u8] {
        let bytes = self
            .buffer
            .get(self.offset..)
            .expect("offset should be <= buffer length");
        self.offset = self.buffer.len();
        bytes
    }
}

#[duplicate_item(
    buffer_type;
    [ Vec<u8> ];
    [ &Vec<u8> ];
)]
impl ByteReaderContainer<buffer_type> {
    #[inline]
    fn insufficient_remaining(&self, length: usize) -> ByteReaderError {
        ByteReaderError::InsufficientRemaining {
            requested: length,
            remaining: self.remaining(),
            offset: self.offset,
        }
    }
}

impl ByteReaderContainer<Vec<u8>> {
    /// Truncate the underlying buffer to the remaining bytes. The current offset will be updated accordingly.
    #[inline]
    pub(crate) fn truncate(&mut self) {
        let _ = self.buffer.drain(..self.offset);
        self.offset = 0;
    }

    /// Read all remaining bytes and consume the reader and its underlying buffer.
    #[inline]
    pub(crate) fn read_remaining_owned(mut self) -> Vec<u8> {
        self.buffer.drain(self.offset..).collect()
    }
}

#[duplicate_item(
    buffer_type          run_writer_type   run_at_writer_type;
    [ &'buffer Vec<u8> ] [ &'run Vec<u8> ] [ &'run_at Vec<u8> ];
    [ Vec<u8> ]          [ Vec<u8> ]       [ &'run_at Vec<u8> ];
)]
#[expect(clippy::allow_attributes, reason = "duplicate shenanigans")]
#[allow(clippy::extra_unused_lifetimes, reason = "Abstracted duplicate")]
impl<'buffer> ByteReader for ByteReaderContainer<buffer_type> {
    type Buffer = buffer_type;
    type RunAtReader<'run_at> = ByteReaderContainer<run_at_writer_type>;
    type RunReader<'run> = ByteReaderContainer<run_writer_type>;

    #[inline]
    fn offset(&self) -> usize {
        self.offset
    }

    #[inline]
    fn remaining(&self) -> usize {
        #[expect(clippy::panic, reason = "Impossible")]
        let Some(remaining) = self.buffer.len().checked_sub(self.offset) else {
            panic!("length must be >= offset and therefore usize")
        };
        remaining
    }

    #[inline]
    fn skip(&mut self, length: usize) -> Result<(), ByteReaderError> {
        let insufficient_remaining = || self.insufficient_remaining(length);

        // Calculate new offset
        let updated_offset = self
            .offset
            .checked_add(length)
            .ok_or_else(insufficient_remaining)?;

        // Check if there are sufficient remaining bytes left
        if updated_offset > self.buffer.len() {
            return Err(insufficient_remaining());
        }

        // Update offset
        self.offset = updated_offset;
        Ok(())
    }

    #[inline]
    fn run<T, F: FnOnce(&mut Self::RunReader<'_>) -> Result<T, ByteReaderError>>(
        &mut self,
        op: F,
    ) -> Result<T, ByteReaderError> {
        op(self)
    }

    #[inline]
    fn run_owned<T, F: FnOnce(Self) -> Result<T, ByteReaderError>>(
        self,
        op: F,
    ) -> Result<T, ByteReaderError> {
        op(self)
    }

    #[inline]
    fn run_at<T, F: FnOnce(Self::RunAtReader<'_>) -> Result<T, ByteReaderError>>(
        &mut self,
        relative_offset: isize,
        op: F,
    ) -> Result<T, ByteReaderError> {
        let invalid_offset = || ByteReaderError::InvalidRelativeOffset {
            relative_offset,
            offset: self.offset,
            length: self.buffer.len(),
        };

        // Calculate new offset
        let updated_offset: usize = relative_offset
            .checked_add(self.offset.try_into().map_err(|_| invalid_offset())?)
            .ok_or_else(invalid_offset)?
            .try_into()
            .map_err(|_| invalid_offset())?;
        if updated_offset > self.buffer.len() {
            return Err(invalid_offset());
        }

        // Run
        #[allow(clippy::needless_borrow, reason = "(Poorly) abstracted duplicate")]
        op(Self::RunAtReader {
            buffer: &self.buffer,
            offset: updated_offset,
        })
    }

    #[inline]
    fn expect_consumed(self) -> Result<Self::Buffer, ByteReaderError> {
        if self.offset != self.buffer.len() {
            return Err(ByteReaderError::UnexpectedRemaining {
                remaining: self.remaining(),
                length: self.buffer.len(),
            });
        }
        Ok(self.buffer)
    }

    #[inline]
    fn read(&mut self, length: usize) -> Result<&[u8], ByteReaderError> {
        let insufficient_remaining = || self.insufficient_remaining(length);

        // Calculate new offset
        let updated_offset = self
            .offset
            .checked_add(length)
            .ok_or_else(insufficient_remaining)?;

        // Attempt to read
        let bytes = self
            .buffer
            .get(self.offset..updated_offset)
            .ok_or_else(insufficient_remaining)?;

        // Update offset and return read bytes
        self.offset = updated_offset;
        Ok(bytes)
    }

    #[inline]
    fn read_range(&mut self, length: usize) -> Result<Range<usize>, ByteReaderError> {
        let insufficient_remaining = || self.insufficient_remaining(length);

        // Calculate new offset
        let updated_offset = self
            .offset
            .checked_add(length)
            .ok_or_else(insufficient_remaining)?;

        // Check if there are sufficient remaining bytes left
        if updated_offset > self.buffer.len() {
            return Err(insufficient_remaining());
        }

        // Update offset and return range
        let range = self.offset..updated_offset;
        self.offset = updated_offset;
        Ok(range)
    }

    #[inline]
    fn read_remaining(&mut self) -> &[u8] {
        let bytes = self
            .buffer
            .get(self.offset..)
            .expect("offset should be <= buffer length");
        self.offset = self.buffer.len();
        bytes
    }
}

/// Wraps a [`&[u8]`] and allows to apply read operations safely within the constrained space.
pub(crate) type SliceByteReader<'buffer> = ByteReaderContainer<&'buffer [u8]>;

/// Wraps or creates a [`Vec<u8>`] and allows to apply read operations safely within the constrained
/// space.
pub(crate) type OwnedVecByteReader = ByteReaderContainer<Vec<u8>>;

/// Wraps a [`&Vec<u8>`](Vec<u8>) and is otherwise identical to the [`OwnedVecByteReader`].
#[expect(dead_code, reason = "Will use later")]
pub(crate) type BorrowedVecByteReader<'buffer> = ByteReaderContainer<&'buffer Vec<u8>>;

#[cfg(test)]
mod tests {
    use super::*;

    const DATA: [u8; 25] = [
        0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
    ];

    struct StateValidator {
        offset: usize,
        remaining: usize,
    }
    impl StateValidator {
        fn assert_processed(&mut self, reader: &mut impl ByteReader, n_processed: usize) {
            self.offset += n_processed;
            self.remaining -= n_processed;

            assert_eq!(reader.offset(), self.offset);
            assert_eq!(reader.remaining(), self.remaining);
        }
    }

    /// Test byte reading for an implementation of [`ByteReading`].
    ///
    /// The tests fail if the passed reader does not contain [`DATA`]
    fn test_byte_reader<Reader, Inner>(mut reader: Reader, inner: Inner)
    where
        Reader: ByteReader,
        Inner: Fn(&Reader::Buffer) -> &[u8],
    {
        // Initialize validator
        let mut validator = StateValidator {
            offset: 0,
            remaining: DATA.len(),
        };
        validator.assert_processed(&mut reader, 0);

        // Read byte [0]
        assert_eq!(reader.read_u8().unwrap(), 0);
        validator.assert_processed(&mut reader, 1);

        // Read bytes [1, 2] as u16 little endian
        assert_eq!(reader.read_u16_le().unwrap(), 513);
        validator.assert_processed(&mut reader, 2);

        // Read bytes [3, 4, 5, 6] as u32 little endian
        assert_eq!(reader.read_u32_le().unwrap(), 100_992_003);
        validator.assert_processed(&mut reader, 4);

        // Read bytes [7, 8, 9, 10, 11, 12, 13, 14] as u64 little endian
        assert_eq!(reader.read_u64_le().unwrap(), 1_012_478_732_780_767_239);
        validator.assert_processed(&mut reader, 8);

        // Skip byte 15
        reader.skip(1).unwrap();
        validator.assert_processed(&mut reader, 1);

        // Read bytes [16, 17, 18]
        assert_eq!(reader.read(3).unwrap(), &[16, 17, 18]);
        validator.assert_processed(&mut reader, 3);

        // Read range of length 2
        let range_19_20 = reader.read_range(2).unwrap();
        assert_eq!(range_19_20, validator.offset..(validator.offset + 2));
        validator.assert_processed(&mut reader, 2);

        // Check the last two bytes (i.e., [19, 20])
        assert_eq!(
            reader.run_at(-2, |mut reader| reader.read_u16_le()).unwrap(),
            5139,
        );
        validator.assert_processed(&mut reader, 0);

        // Skip the next byte (i.e., 21) and read u8 (i.e., 22)
        assert_eq!(reader.run_at(1, |mut reader| reader.read_u8()).unwrap(), 22);
        validator.assert_processed(&mut reader, 0);

        // Try to read out of bound
        assert!(
            reader
                .run_at(DATA.len().try_into().unwrap(), |mut reader| reader.read_u8())
                .is_err(),
        );
        validator.assert_processed(&mut reader, 0);

        // Get the remaining bytes
        let remaining_bytes = &DATA[validator.offset..];
        assert_eq!(reader.read_remaining(), remaining_bytes);
        validator.assert_processed(&mut reader, remaining_bytes.len());

        // Try to read some more out of range...
        assert!(reader.read_u8().is_err());
        // .. but with changed offset it should work
        assert_eq!(
            reader.run_at(-1, |mut reader| reader.read_u8()).unwrap(),
            DATA[DATA.len() - 1],
        );

        // Check that all data is read and compare underlying data
        let data = reader.expect_consumed().unwrap();
        assert_eq!(inner(&data), DATA);

        // Apply the range we read earlier against bytes [19, 20]
        assert_eq!(&inner(&data)[range_19_20], &[19, 20]);
    }

    #[test]
    fn slice_byte_reader() {
        let reader = SliceByteReader::new(&DATA);
        test_byte_reader(reader, |buffer| buffer);
    }

    #[test]
    fn owned_vec_byte_reader() {
        let reader = OwnedVecByteReader::new(DATA.to_vec());
        test_byte_reader(reader, |buffer| buffer);
    }

    #[test]
    fn borrowed_vec_byte_reader() {
        let data = DATA.to_vec();
        let reader = BorrowedVecByteReader::new(&data);
        test_byte_reader(reader, |buffer| buffer);
    }

    #[test]
    fn truncate() {
        let mut reader = OwnedVecByteReader::new(DATA.to_vec());
        assert_eq!(reader.buffer, DATA);
        assert_eq!(reader.buffer.len(), 25);

        // Truncate after offset 18 and ensure only the remaining data is available
        reader.skip(18).unwrap();
        reader.truncate();
        assert_eq!(reader.buffer, DATA[18..]);
    }
}

[Dauer der Verarbeitung: 0.30 Sekunden, vorverarbeitet 2026-04-27]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge