compressed_intvec/fixed/
proxy.rs

1//! # Mutable Access Proxy
2//!
3//! This module defines [`MutProxy`], a temporary proxy object that enables
4//! ergonomic, index-like mutable access to elements within a [`FixedVec`].
5//!
6//! Because [`FixedVec`] stores its elements in a compressed, bit-packed format,
7//! it is not possible to return a direct mutable reference (`&mut T`) to an
8//! element. Instead, methods like [`at_mut`](super::FixedVec::at_mut) return a
9//! [`MutProxy`]. This proxy holds a temporary, decoded copy of an element's value.
10//! When the proxy is dropped (goes out of scope), its [`Drop`] implementation
11//! automatically writes the (potentially modified) value back into the vector.
12//!
13//! # Examples
14//!
15//! ```
16//! use compressed_intvec::fixed::{FixedVec, UFixedVec, BitWidth};
17//!
18//! let data: &[u32] = &[10, 20, 30];
19//! let mut vec: UFixedVec<u32> = FixedVec::builder().bit_width(BitWidth::Explicit(7)).build(data).unwrap();
20//!
21//! // Get a mutable proxy for the element at index 1.
22//! if let Some(mut proxy) = vec.at_mut(1) {
23//!     // DerefMut allows us to modify the value.
24//!     *proxy = 99;
25//! } // The proxy is dropped here, and the new value is written back.
26//!
27//! assert_eq!(vec.get(1), Some(99));
28//! ```
29
30use super::{
31    traits::{Storable, Word},
32    FixedVec,
33};
34use dsi_bitstream::prelude::Endianness;
35use std::{
36    mem,
37    ops::{Deref, DerefMut},
38};
39
40/// A proxy object for mutable access to an element within a [`FixedVec`].
41///
42/// This struct is returned by [`FixedVec::at_mut`]. It holds a temporary copy
43/// of an element's value. When the proxy is dropped, its [`Drop`] implementation
44/// writes the (potentially modified) value back into the parent vector.
45/// This "copy-on-read, write-on-drop" mechanism allows for an API that feels
46/// like direct mutable access.
47pub struct MutProxy<'a, T, W, E, B>
48where
49    T: Storable<W>,
50    W: Word,
51    E: Endianness,
52    B: AsRef<[W]> + AsMut<[W]>,
53{
54    /// A mutable reference to the parent vector.
55    vec: &'a mut FixedVec<T, W, E, B>,
56    /// The index of the element being accessed.
57    index: usize,
58    /// A temporary, decoded copy of the element's value.
59    value: T,
60}
61
62impl<'a, T, W, E, B> MutProxy<'a, T, W, E, B>
63where
64    T: Storable<W>,
65    W: Word,
66    E: Endianness,
67    B: AsRef<[W]> + AsMut<[W]>,
68{
69    /// Creates a new [`MutProxy`].
70    ///
71    /// This is called by [`at_mut`](FixedVec::at_mut). It reads the initial value
72    /// from the vector and stores it in the `value` field.
73    pub(super) fn new(vec: &'a mut FixedVec<T, W, E, B>, index: usize) -> Self {
74        let value = vec
75            .get(index)
76            .expect("Index out of bounds in MutProxy creation");
77        Self { vec, index, value }
78    }
79
80    /// Consumes the proxy, returning the current value without writing it back.
81    ///
82    /// This can be used to avoid the overhead of a write operation if the value
83    /// was read but not modified.
84    pub fn into_inner(self) -> T {
85        // Take ownership of the value.
86        let value = self.value;
87        // Prevent the Drop implementation from running, thus skipping the write-back.
88        mem::forget(self);
89        value
90    }
91}
92
93impl<T, W, E, B> Deref for MutProxy<'_, T, W, E, B>
94where
95    T: Storable<W>,
96    W: Word,
97    E: Endianness,
98    B: AsRef<[W]> + AsMut<[W]>,
99{
100    type Target = T;
101
102    /// Returns a reference to the temporary value held by the proxy.
103    fn deref(&self) -> &Self::Target {
104        &self.value
105    }
106}
107
108impl<T, W, E, B> DerefMut for MutProxy<'_, T, W, E, B>
109where
110    T: Storable<W>,
111    W: Word,
112    E: Endianness,
113    B: AsRef<[W]> + AsMut<[W]>,
114{
115    /// Returns a mutable reference to the temporary value, allowing modification.
116    fn deref_mut(&mut self) -> &mut Self::Target {
117        &mut self.value
118    }
119}
120
121impl<T, W, E, B> Drop for MutProxy<'_, T, W, E, B>
122where
123    T: Storable<W>,
124    W: Word,
125    E: Endianness,
126    B: AsRef<[W]> + AsMut<[W]>,
127{
128    /// Writes the potentially modified value back to the [`FixedVec`] when the
129    /// proxy goes out of scope.
130    fn drop(&mut self) {
131        // The `value` field is copied here before being passed to `set`.
132        // `set` will handle re-encoding the value and writing it to the bit buffer.
133        self.vec.set(self.index, self.value);
134    }
135}