Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/rust/zlib-rs/src/deflate/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 5 kB image not shown  

Quelle  window.rs   Sprache: unbekannt

 
use crate::allocate::Allocator;
use core::mem::MaybeUninit;

#[derive(Debug)]
pub struct Window<'a> {
    // the full window allocation. This is longer than w_size so that operations don't need to
    // perform bounds checks.
    buf: &'a mut [MaybeUninit<u8>],

    // number of initialized bytes
    filled: usize,

    window_bits: usize,

    high_water: usize,
}

impl<'a> Window<'a> {
    pub fn new_in(alloc: &Allocator<'a>, window_bits: usize) -> Option<Self> {
        let buf = alloc.allocate_slice::<u8>(2 * ((1 << window_bits) + Self::padding()))?;

        Some(Self {
            buf,
            filled: 0,
            window_bits,
            high_water: 0,
        })
    }

    pub fn clone_in(&self, alloc: &Allocator<'a>) -> Option<Self> {
        let mut clone = Self::new_in(alloc, self.window_bits)?;

        clone.buf.copy_from_slice(self.buf);
        clone.filled = self.filled;
        clone.high_water = self.high_water;

        Some(clone)
    }

    pub unsafe fn drop_in(&mut self, alloc: &Allocator) {
        if !self.buf.is_empty() {
            let buf = core::mem::take(&mut self.buf);
            alloc.deallocate(buf.as_mut_ptr(), buf.len());
        }
    }

    pub fn capacity(&self) -> usize {
        2 * (1 << self.window_bits)
    }

    /// Returns a shared reference to the filled portion of the buffer.
    #[inline]
    pub fn filled(&self) -> &[u8] {
        // safety: `self.buf` has been initialized for at least `filled` elements
        unsafe { core::slice::from_raw_parts(self.buf.as_ptr().cast(), self.filled) }
    }

    /// Returns a mutable reference to the filled portion of the buffer.
    #[inline]
    pub fn filled_mut(&mut self) -> &mut [u8] {
        // safety: `self.buf` has been initialized for at least `filled` elements
        unsafe { core::slice::from_raw_parts_mut(self.buf.as_mut_ptr().cast(), self.filled) }
    }

    /// # Safety
    ///
    /// `src` must point to `range.end - range.start` valid (initialized!) bytes
    pub unsafe fn copy_and_initialize(&mut self, range: core::ops::Range<usize>, src: *const u8) {
        let (start, end) = (range.start, range.end);

        let dst = self.buf[range].as_mut_ptr() as *mut u8;
        core::ptr::copy_nonoverlapping(src, dst, end - start);

        if start >= self.filled {
            self.filled = Ord::max(self.filled, end);
        }

        self.high_water = Ord::max(self.high_water, self.filled);
    }

    // this library has many functions that operated in a chunked fashion on memory. For
    // performance, we want to minimize bounds checks. Therefore we reserve initialize some extra
    // memory at the end of the window so that chunked operations can use the whole buffer. If they
    // go slightly over `self.capacity` that's okay, we account for that here by making sure the
    // memory there is initialized!
    pub fn initialize_out_of_bounds(&mut self) {
        const WIN_INIT: usize = crate::deflate::STD_MAX_MATCH;

        // If the WIN_INIT bytes after the end of the current data have never been
        // written, then zero those bytes in order to avoid memory check reports of
        // the use of uninitialized (or uninitialised as Julian writes) bytes by
        // the longest match routines.  Update the high water mark for the next
        // time through here.  WIN_INIT is set to STD_MAX_MATCH since the longest match
        // routines allow scanning to strstart + STD_MAX_MATCH, ignoring lookahead.
        if self.high_water < self.capacity() {
            let curr = self.filled().len();

            if self.high_water < curr {
                // Previous high water mark below current data -- zero WIN_INIT
                // bytes or up to end of window, whichever is less.
                let init = Ord::min(self.capacity() - curr, WIN_INIT);

                self.buf[curr..][..init].fill(MaybeUninit::new(0));

                self.high_water = curr + init;

                self.filled += init;
            } else if self.high_water < curr + WIN_INIT {
                // High water mark at or above current data, but below current data
                // plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
                // to end of window, whichever is less.
                let init = Ord::min(
                    curr + WIN_INIT - self.high_water,
                    self.capacity() - self.high_water,
                );

                self.buf[self.high_water..][..init].fill(MaybeUninit::new(0));

                self.high_water += init;
                self.filled += init;
            }
        }
    }

    pub fn initialize_at_least(&mut self, at_least: usize) {
        let end = at_least.clamp(self.high_water, self.buf.len());
        self.buf[self.high_water..end].fill(MaybeUninit::new(0));

        self.high_water = end;
        self.filled = end;
    }

    // padding required so that SIMD operations going out-of-bounds are not a problem
    pub fn padding() -> usize {
        if crate::cpu_features::is_enabled_pclmulqdq() {
            8
        } else {
            0
        }
    }
}

[ Dauer der Verarbeitung: 0.12 Sekunden  (vorverarbeitet)  ]