scopegraphs/label.rs
1use std::array;
2
3pub(crate) trait ArrayInit<T> {
4 fn init_from_fn(init: impl FnMut() -> T) -> Self;
5}
6
7impl<T, const N: usize> ArrayInit<T> for [T; N] {
8 fn init_from_fn(mut init: impl FnMut() -> T) -> Self {
9 array::from_fn(|_| init())
10 }
11}
12
13unsafe impl Label for () {
14 type Array<T> = [T; 1];
15
16 fn to_usize(&self) -> usize {
17 0
18 }
19
20 fn iter() -> impl Iterator<Item = Self>
21 where
22 Self: Sized,
23 {
24 [()].into_iter()
25 }
26
27 fn iter_ref() -> impl Iterator<Item = &'static Self>
28 where
29 Self: Sized + 'static,
30 {
31 [&()].into_iter()
32 }
33}
34
35/// Represents types that can be used as labels on [`scopegraph edges`](crate::concepts::edges).
36///
37/// Can, and should, be derived using the [`Label`](scopegraphs_macros::Label) derive macro.
38///
39/// # Safety
40///
41/// This trait is unsafe to implement by yourself, as code in this library depends on the fact
42/// that [`to_usize`](Label::to_usize) returns a list of consecutive indices from 0 to [`NUM_LABELS`](Label::NUM_LABELS) - 1
43pub unsafe trait Label: Eq + Copy {
44 /// The type of an array of these labels, with one slot for each label type.
45 /// NOTE: using an associated const doesn't work without full const generics
46 #[allow(private_bounds)]
47 type Array<T>: AsRef<[T]> + AsMut<[T]> + ArrayInit<T>;
48
49 /// Convert any label to a unique usize, which m
50 fn to_usize(&self) -> usize;
51
52 /// Iterate over all possible labels that this label type could be.
53 fn iter() -> impl Iterator<Item = Self>
54 where
55 Self: Sized;
56
57 /// Iterate over all possible labels that this label type could be, by reference.
58 fn iter_ref() -> impl Iterator<Item = &'static Self>
59 where
60 Self: Sized + 'static;
61}
62
63/// `query_regex` is a wrapper around [`compile_regex`](crate::compile_regex) that should be used
64/// when you're using the resulting regex only once, inline. This is often the case in
65/// [scope graph queries](crate::resolve::Query).
66///
67/// [`compile_regex`](crate::compile_regex) generates a type, which when instantiated can match
68/// a string. This macro avoids the need to instantiate, and combines the compiling and instantiation.
69#[macro_export]
70macro_rules! query_regex {
71 ($label_type:path: $($regex:tt)*) => {
72 {
73 $crate::compile_regex!(type QueryRegex<$label_type> = $($regex)*);
74 QueryRegex::new()
75 }
76 };
77}