Skip to main content

compressed_intvec/fixed/
macros.rs

1//! # Macros for [`FixedVec`]
2
3/// Creates a [`FixedVec`] with default parameters.
4///
5/// This macro simplifies the creation of [`FixedVec`] by using default parameters
6/// ([`usize`] for the storage word, [`LE`](dsi_bitstream::prelude::LE) for byte order) inferred
7/// from the element type. It uses [`BitWidth::Minimal`] for space efficiency.
8///
9/// There are three forms of this macro:
10///
11/// - Create a vector from a list of elements:
12///   ```
13///   # use compressed_intvec::fixed_vec;
14///   let vec = fixed_vec![10u32, 20, 30];
15///   # assert_eq!(vec.len(), 3);
16///   ```
17///
18/// - Create a vector from a repeated element:
19///   ```
20///   # use compressed_intvec::fixed_vec;
21///   let vec = fixed_vec![0i16; 100];
22///   # assert_eq!(vec.len(), 100);
23///   ```
24///
25/// - Create an empty vector (the element type must be specified):
26///   ```
27///   # use compressed_intvec::fixed_vec;
28///   # use compressed_intvec::fixed::UFixedVec;
29///   let vec: UFixedVec<u32> = fixed_vec![];
30///   # assert!(vec.is_empty());
31///   ```
32///
33/// # Examples
34///
35/// ```
36/// use compressed_intvec::fixed_vec;
37/// use compressed_intvec::fixed::UFixedVec;
38///
39/// // Create a vector from a list of elements.
40/// let vec = fixed_vec![10u32, 20, 30];
41/// assert_eq!(vec.len(), 3);
42/// assert_eq!(vec.bit_width(), 5); // 30 requires 5 bits
43///
44/// // Create a vector from a repeated element.
45/// let vec_rep = fixed_vec![0i16; 100];
46/// assert_eq!(vec_rep.len(), 100);
47/// assert_eq!(vec_rep.get(50), Some(0));
48///
49/// // Create an empty vector (type annotation is required).
50/// let empty: UFixedVec<u64> = fixed_vec![];
51/// assert!(empty.is_empty());
52/// ```
53#[macro_export]
54macro_rules! fixed_vec {
55    // Empty vector: `fixed_vec![]`
56    // Requires type annotation from the user.
57    () => {
58        $crate::fixed::FixedVec::builder().build(&[]).unwrap()
59    };
60
61    // From list: `fixed_vec![a, b, c]`
62    ($($elem:expr),+ $(,)?) => {
63        // Delegate to a helper function to avoid repeating complex bounds.
64        $crate::fixed::macros::from_slice(&[$($elem),+])
65    };
66
67    // From element and length: `fixed_vec![elem; len]`
68    ($elem:expr; $len:expr) => {
69        // Delegate to a helper function.
70        $crate::fixed::macros::from_repetition($elem, $len)
71    };
72}
73
74/// Creates a [`FixedVec`] of signed integers (forces `i64`).
75///
76/// This macro is similar to [`fixed_vec!`], but automatically casts all
77/// elements to `i64`. This ensures that ZigZag encoding is used for
78/// signed values.
79///
80/// # Examples
81///
82/// ```
83/// use compressed_intvec::sfixed_vec;
84/// let vec = sfixed_vec![-1, 2, -3];
85/// assert_eq!(vec.get(0), Some(-1));
86/// ```
87#[macro_export]
88macro_rules! sfixed_vec {
89    // Empty case
90    () => {
91        $crate::fixed::FixedVec::<i64, usize, dsi_bitstream::prelude::LE>::builder()
92            .build(&[])
93            .unwrap()
94    };
95
96    // From list: `sfixed_vec![a, b, c]`
97    ($($elem:expr),+ $(,)?) => {
98        $crate::fixed::macros::from_slice(&[$($elem as i64),+])
99    };
100
101    // From element and length: `sfixed_vec![elem; len]`
102    ($elem:expr; $len:expr) => {
103        $crate::fixed::macros::from_repetition($elem as i64, $len)
104    };
105}
106
107// --- Macro Helper Functions (Not part of the public API) ---
108
109use crate::fixed::{
110    builder::FixedVecBuilder,
111    traits::{DefaultParams, Storable, Word},
112    BitWidth, FixedVec,
113};
114use dsi_bitstream::prelude::Endianness;
115use num_traits::ToPrimitive;
116
117/// A hidden helper function for the `fixed_vec![...]` macro variant.
118///
119/// This function is not intended for direct use. It is called by the macro
120/// to construct a `FixedVec` from a slice of elements.
121#[doc(hidden)]
122pub fn from_slice<T>(slice: &[T]) -> FixedVec<T, <T as DefaultParams>::W, <T as DefaultParams>::E>
123where
124    T: DefaultParams + Storable<<T as DefaultParams>::W> + ToPrimitive,
125    <T as DefaultParams>::W: Word,
126    <T as DefaultParams>::E: Endianness,
127    FixedVecBuilder<T, <T as DefaultParams>::W, <T as DefaultParams>::E>: Default,
128    // This complex bound is required by the `build` method of the builder.
129    for<'a> dsi_bitstream::impls::BufBitWriter<
130        <T as DefaultParams>::E,
131        dsi_bitstream::impls::MemWordWriterVec<
132            <T as DefaultParams>::W,
133            Vec<<T as DefaultParams>::W>,
134        >,
135    >: dsi_bitstream::prelude::BitWrite<<T as DefaultParams>::E, Error = std::convert::Infallible>,
136{
137    FixedVec::<T, <T as DefaultParams>::W, <T as DefaultParams>::E>::builder()
138        .bit_width(BitWidth::Minimal)
139        .build(slice)
140        .unwrap()
141}
142
143/// A hidden helper function for the `fixed_vec![elem; len]` macro variant.
144///
145/// This function is not intended for direct use. It is called by the macro
146/// to construct a `FixedVec` by repeating an element.
147#[doc(hidden)]
148pub fn from_repetition<T>(
149    elem: T,
150    len: usize,
151) -> FixedVec<T, <T as DefaultParams>::W, <T as DefaultParams>::E>
152where
153    T: DefaultParams + Storable<<T as DefaultParams>::W> + ToPrimitive + Clone,
154    <T as DefaultParams>::W: Word,
155    <T as DefaultParams>::E: Endianness,
156    FixedVecBuilder<T, <T as DefaultParams>::W, <T as DefaultParams>::E>: Default,
157    // This complex bound is required by the `build` method of the builder.
158    for<'a> dsi_bitstream::impls::BufBitWriter<
159        <T as DefaultParams>::E,
160        dsi_bitstream::impls::MemWordWriterVec<
161            <T as DefaultParams>::W,
162            Vec<<T as DefaultParams>::W>,
163        >,
164    >: dsi_bitstream::prelude::BitWrite<<T as DefaultParams>::E, Error = std::convert::Infallible>,
165{
166    let mut v = Vec::new();
167    v.resize(len, elem);
168    FixedVec::<T, <T as DefaultParams>::W, <T as DefaultParams>::E>::builder()
169        .bit_width(BitWidth::Minimal)
170        .build(&v)
171        .unwrap()
172}