• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Alorel / impl_index-rs / 14553724254

19 Apr 2025 11:13PM UTC coverage: 96.479% (-1.0%) from 97.512%
14553724254

push

github

Alorel
ci: Add `unexpected_cfgs` lint config

137 of 142 relevant lines covered (96.48%)

5.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/lib.rs
1
//! A macro for deriving [`Index`](::core::ops::Index) & [`IndexMut`](::core::ops::IndexMut) implementations.
2
//!
3
//! [![MASTER CI status](https://github.com/Alorel/impl_index-rs/actions/workflows/core.yml/badge.svg)](https://github.com/Alorel/impl_index-rs/actions/workflows/core.yml?query=branch%3Amaster)
4
//! [![crates.io badge](https://img.shields.io/crates/v/impl_index)](https://crates.io/crates/impl_index)
5
//! [![docs.rs badge](https://img.shields.io/docsrs/impl_index?label=docs.rs)](https://docs.rs/impl_index)
6
//! [![dependencies badge](https://img.shields.io/librariesio/release/cargo/impl_index)](https://libraries.io/cargo/impl_index)
7
//!
8
//! # Basic usage
9
//!
10
#![cfg_attr(doctest, doc = " ````no_test")]
11
//! ```
12
//! // Derive only Index
13
//! index!(Struct by Enum => Output:
14
//!   Variant1 => field1,
15
//!   Variant2 => field2,
16
//! );
17
//!
18
//! // Derive Index and IndexMut
19
//! index!(Struct by Enum => mut Output:
20
//!   Variant1 => field1,
21
//!   Variant2 => field2,
22
//! );
23
//!
24
//! // Match/get by pattern
25
//! index!(Struct by Enum => Output:
26
//!   pat Enum::Variant(Foo::Bar) => field1,
27
//!   pat Enum::Index(idx) => pat field2[idx],
28
//! );
29
//! ````
30
//!
31
//! # Example
32
//!
33
//! ```
34
//! use impl_index::index;
1✔
35
//!
36
//! #[derive(Default)]
37
//! struct Struct {
38
//!     a: u8,
39
//!     arr: [u8; 10],
40
//!     thing_1: u8,
41
//!     thing_2: u8,
42
//! }
43
//!
44
//! enum Enum {
45
//!     A,
46
//!     Arr(usize),
47
//!     Thing(Thing),
48
//! }
49
//!
50
//! enum Thing {
51
//!     One,
52
//!     Two,
53
//! }
54
//!
55
//! index!(Struct by Enum => mut u8:
56
//!     A => a,
57
//!     pat Enum::Arr(idx) if idx < 10 => pat arr[idx],
58
//!     pat Enum::Thing(Thing::One) => thing_1,
59
//!     pat _ => thing_2,
60
//! );
61
//!
62
//! let mut s = Struct::default();
63
//!
1✔
64
//! s[Enum::A] = 1;
1✔
65
//!
1✔
66
//! for idx in 0u8..10 {
67
//!     s[Enum::Arr(idx.into())] = idx * 10;
11✔
68
//! }
10✔
69
//!
10✔
70
//! s[Enum::Thing(Thing::One)] = 200;
71
//! s[Enum::Thing(Thing::Two)] = 201;
1✔
72
//!
1✔
73
//! assert_eq!(s[Enum::A], 1, "A");
1✔
74
//! for idx in 0u8..10 {
1✔
75
//!     assert_eq!(s[Enum::Arr(idx.into())], idx * 10, "Arr({})", idx);
11✔
76
//! }
10✔
77
//! assert_eq!(s[Enum::Thing(Thing::One)], 200, "Thing(One)");
78
//! assert_eq!(s[Enum::Thing(Thing::Two)], 201, "Thing(Two)");
1✔
79
//! ```
1✔
80
//!
1✔
81
//! ## Generated output
82
//!
83
#![cfg_attr(doctest, doc = " ````no_test")]
84
//! ```
85
//! #[automatically_derived]
86
//! impl ::core::ops::Index<Enum> for Struct {
87
//!     type Output = u8;
88
//!     fn index(&self, index_macro_derived_index_input: Enum) -> &Self::Output {
89
//!         match index_macro_derived_index_input {
90
//!             Enum::A => &self.a,
91
//!             Enum::Arr(idx) if idx < 10 => &self.arr[idx],
92
//!             Enum::Thing(Thing::One) => &self.thing_1,
93
//!             _ => &self.thing_2,
94
//!         }
95
//!     }
96
//! }
97
//! #[automatically_derived]
98
//! impl ::core::ops::IndexMut<Enum> for Struct {
99
//!     fn index_mut(&mut self, index_macro_derived_index_input: Enum) -> &mut Self::Output {
100
//!         match index_macro_derived_index_input {
101
//!             Enum::A => &mut self.a,
102
//!             Enum::Arr(idx) if idx < 10 => &mut self.arr[idx],
103
//!             Enum::Thing(Thing::One) => &mut self.thing_1,
104
//!             _ => &mut self.thing_2,
105
//!         }
106
//!     }
107
//! }
108
//! ````
109
//!
110
//! # Example without generating `IndexMut`
111
//!
112
//! This will fail to compile on `instance[Idx::Foo] = 1;`
113
//!
114
//! ```compile_fail
115
//! # use impl_index::index;
116
//! struct Struct {
117
//!   foo: usize,
118
//! }
119
//!
120
//! enum Idx {
121
//!   Foo,
122
//! }
123
//!
124
//! index!(Struct by Idx => usize: Foo => foo);
125
//!
126
//! let mut instance = Struct { foo: 0 };
127
//! instance[Idx::Foo] = 1;
128
//! ```
129

130
#![deny(clippy::correctness, clippy::suspicious)]
131
#![warn(clippy::complexity, clippy::perf, clippy::style, clippy::pedantic)]
132
#![warn(missing_docs)]
133
#![cfg_attr(doc_cfg, feature(doc_cfg, doc_auto_cfg))]
134

135
mod parse;
136
mod tokenise;
137

138
use proc_macro::TokenStream as BaseTokenStream;
139
use proc_macro2::Ident;
140
use syn::punctuated::Punctuated;
141
use syn::{parse_macro_input, Expr, Pat, Token};
142

143
/// Derive [`Index`](::core::ops::Index) & [`IndexMut`](::core::ops::IndexMut) implementations.
144
///
145
#[cfg_attr(doctest, doc = " ````no_test")]
146
/// ```
147
/// index!(Struct by Enum => mut u8:
148
///     UnitVariant => field_1,
149
///     pat Enum::Array(idx) if idx < 10 => pat array_field[idx],
150
///     pat Enum::Thing(Thing::One) => thing_1,
151
///     pat _ => thing_2,
152
/// );
153
/// ````
154
///
155
/// See [crate-level docs](crate) for a full example.
156
#[proc_macro]
157
pub fn index(input: BaseTokenStream) -> BaseTokenStream {
2✔
158
    parse_macro_input!(input as IndexMacro)
2✔
159
        .into_token_stream()
2✔
160
        .into()
2✔
161
}
2✔
162

163
struct IndexMacro {
164
    impl_mut: bool,
165
    generics: Option<syn::Generics>,
166
    idx_by: syn::Type,
167
    impl_for: syn::Type,
168
    output: syn::Type,
169
    pairings: Punctuated<Pairing, Token![,]>,
170
}
171

172
struct Pairing {
173
    enum_variant: MaybeIdent<Pattern>,
174
    struct_field: MaybeIdent<Expr>,
175
}
176

177
struct Pattern {
178
    pat: Pat,
179
    guard: Option<(Token![if], Expr)>,
180
}
181

182
enum MaybeIdent<Other> {
183
    Ident(Ident),
184
    Other(Other),
185
}
186

187
struct IndexedPairing<P, T> {
188
    pairing: P,
189
    idx_by: T,
190
    mut_ref: Option<Token![mut]>,
191
}
192

193
impl AsRef<Pairing> for Pairing {
194
    #[inline]
195
    fn as_ref(&self) -> &Pairing {
9✔
196
        self
9✔
197
    }
9✔
198
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc