1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/*!

Macros for indexing slices/arrays with multiple compile-time indices/ranges.

These indexing macros check that the indices/ranges don't overlap,
erroring at compile-time if they do,
then return tuples of references to elements / arrays / slices,
based on each passed-in argument.

# Shared Macro docs

Because the indexing macros are all very similar in how they work,
they have [shared documentation] with all of what they share in common.

# Examples

### Slice as fields

This example demonstrates how you can borrow multiple indices and ranges into a `Vec`
(also works for slices, and arrays).

```rust
use multindex::multindex_mut;

let mut field = (100..200).collect::<Vec<u32>>();

const FIELD_A: usize = 32;
const FIELD_B: usize = 40;
const FIELD_C: usize = 60;
const FIELD_E: usize = 62;

// `&mut` in here copies the value through the mutable reference
let (field_a, &mut field_b, &mut field_c_to_e) =
    multindex_mut!(field; FIELD_A, FIELD_B, FIELD_C..=FIELD_E);

assert_eq!(*field_a, 132);
assert_eq!(field_b, 140);
assert_eq!(field_c_to_e, [160, 161, 162]);

*field_a = field_b;
assert_eq!(*field_a, 140);

*field_a += field_c_to_e.iter().sum::<u32>();
assert_eq!(*field_a, 623);

```

### Parsing integers

This example demonstrates how you can fallibly get the first 4 bytes of a
slice as an array, and the remainder as a slice.

```rust
use multindex::multiget;

let mut slice = &[0, 0, 1, 10, 20][..];

assert_eq!(grab_u32(&mut slice), Some(266));
assert_eq!(slice, &[20]);

assert_eq!(grab_u32(&mut slice), None);
assert_eq!(slice, &[20]);


fn grab_u32(slice: &mut &[u8]) -> Option<u32> {
    let (u32_bytes, rem) = multiget!(*slice; ..4, ..)?;
    *slice = rem;
    Some(u32::from_be_bytes(*u32_bytes))
}

```

### Splitting an array

This example demonstrates how you can split an array into reference to smaller arrays.

```rust
use multindex::multindex;

const ROW_SIZE: usize = 5;

let array: [u16; ROW_SIZE * 4] = [
    1, 2, 3, 5, 8,
    13, 21, 34, 55, 89,
    144, 233, 377, 610, 987,
    1597, 2584, 4181, 6765, 10946,
];


type Row = [u16; ROW_SIZE];
// The type annotation is for the reader, the type can be inferred.
let (row0, row1, row2, row3): (&Row, &Row, &Row, &Row) =
    multindex!(array; ..ROW_SIZE, ..ROW_SIZE * 2, ..ROW_SIZE * 3, ..ROW_SIZE * 4);

assert_eq!(row0, &[1, 2, 3, 5, 8]);
assert_eq!(row1, &[13, 21, 34, 55, 89]);
assert_eq!(row2, &[144, 233, 377, 610, 987]);
assert_eq!(row3, &[1597, 2584, 4181, 6765, 10946]);

```

# Minimum Supported Rust Version

This crate requires at least Rust 1.46.0 .

It uses branching and looping at compile-time,
to check that the indices/ranges passed to the macros don't overlap
(required for macros that index mutably).

# no-std support

This crate is `#[no-std]`.
If newer versions add features that require std,
they'll be conditional on a "std" feature being enabled
(it won't be enabled by default).


[shared documentation]: ./indexing_macro_docs/index.html

*/

#![allow(non_camel_case_types)]
#![cfg_attr(not(any(test, feature = "testing")), no_std)]

#[doc(hidden)]
pub extern crate core;

pub mod indexing_macro_docs;

#[doc(hidden)]
#[macro_use]
pub mod macros;

#[doc(hidden)]
pub mod index_argument;

#[doc(hidden)]
pub mod error;

#[doc(hidden)]
pub mod index_properties;

#[doc(hidden)]
pub mod ptr_indexing;

#[doc(hidden)]
pub mod std_const_fns;

#[doc(hidden)]
pub mod are_disjoint;

#[doc(hidden)]
pub mod utils;

#[doc(hidden)]
#[cfg(feature = "testing")]
pub mod test_utils;

#[doc(hidden)]
#[cfg(feature = "testing")]
pub mod doc_based_tests;

#[doc(hidden)]
pub use error::Error;

#[doc(hidden)]
pub mod pmr {
    pub use crate::{
        are_disjoint::AreAllDisjoint,
        error::{ErrorPicker, ErrorTuple, NoErrorsFound},
        index_argument::{
            IK_Index, IK_Range, IK_RangeFrom, IndexArgument, IndexKind, IndexKindPicker,
            IntoPrenormIndex, PrenormIndex,
        },
        index_properties::{
            ComputedConstants, IndexArgumentStats, IndexArgumentsAndStats, IndexProperties,
        },
        ptr_indexing::{IndexPointer, Indexer, IndexerParams},
        std_const_fns::result_m::is_err,
        utils::{panic_on_oob_max_index, AssocType, BorrowSelf, SliceParts, SlicePartsMut},
    };

    pub use core::option::Option::{self, None, Some};
    pub use core::result::Result::Err;
}

#[cfg(all(test, not(feature = "testing")))]
compile_error! { "tests must be run with the \"testing\" feature" }