Access token permissions
This commit is contained in:
12
crates/utils/proc-macros/Cargo.toml
Normal file
12
crates/utils/proc-macros/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "proc_macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "2.0", features = ["full"] }
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
77
crates/utils/proc-macros/src/lib.rs
Normal file
77
crates/utils/proc-macros/src/lib.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020 Stalwart Labs Ltd <hello@stalw.art>
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, Data, DeriveInput};
|
||||
|
||||
#[proc_macro_derive(EnumMethods)]
|
||||
pub fn enum_id(input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as DeriveInput);
|
||||
let name = &input.ident;
|
||||
|
||||
let variants = match input.data {
|
||||
Data::Enum(ref data) => &data.variants,
|
||||
_ => panic!("EnumMethods only works on enums"),
|
||||
};
|
||||
|
||||
let variant_count = variants.len();
|
||||
let variant_names: Vec<_> = variants.iter().map(|v| &v.ident).collect();
|
||||
let variant_ids: Vec<usize> = (0..variant_count).collect();
|
||||
let snake_case_names: Vec<String> = variant_names
|
||||
.iter()
|
||||
.map(|name| to_snake_case(&name.to_string()))
|
||||
.collect();
|
||||
|
||||
let expanded = quote! {
|
||||
impl #name {
|
||||
pub const COUNT: usize = #variant_count;
|
||||
|
||||
pub const fn id(&self) -> usize {
|
||||
match self {
|
||||
#(#name::#variant_names => #variant_ids,)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_id(id: usize) -> Option<Self> {
|
||||
match id {
|
||||
#(#variant_ids => Some(#name::#variant_names),)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
#(#name::#variant_names => #snake_case_names,)*
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_name(name: &str) -> Option<Self> {
|
||||
match name {
|
||||
#(#snake_case_names => Some(#name::#variant_names),)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TokenStream::from(expanded)
|
||||
}
|
||||
|
||||
fn to_snake_case(s: &str) -> String {
|
||||
let mut result = String::new();
|
||||
for (i, ch) in s.char_indices() {
|
||||
if ch.is_uppercase() {
|
||||
if i > 0 {
|
||||
result.push('-');
|
||||
}
|
||||
result.push(ch.to_ascii_lowercase());
|
||||
} else {
|
||||
result.push(ch);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL
|
||||
*/
|
||||
|
||||
use std::{borrow::Borrow, fmt};
|
||||
use std::{borrow::Borrow, cmp::Ordering, fmt, hash::Hash};
|
||||
|
||||
use serde::{de::DeserializeOwned, ser::SerializeMap, Deserialize, Serialize};
|
||||
|
||||
@@ -14,50 +14,51 @@ use serde::{de::DeserializeOwned, ser::SerializeMap, Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct VecMap<K: Eq + PartialEq, V> {
|
||||
pub k: Vec<K>,
|
||||
pub v: Vec<V>,
|
||||
inner: Vec<KeyValue<K, V>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct KeyValue<K: Eq + PartialEq, V> {
|
||||
key: K,
|
||||
value: V,
|
||||
}
|
||||
|
||||
impl<K: Eq + PartialEq, V> Default for VecMap<K, V> {
|
||||
fn default() -> Self {
|
||||
VecMap {
|
||||
k: Vec::new(),
|
||||
v: Vec::new(),
|
||||
}
|
||||
VecMap { inner: Vec::new() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Eq + PartialEq, V> VecMap<K, V> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
k: Vec::new(),
|
||||
v: Vec::new(),
|
||||
}
|
||||
Self::default()
|
||||
}
|
||||
|
||||
pub fn with_capacity(capacity: usize) -> Self {
|
||||
Self {
|
||||
k: Vec::with_capacity(capacity),
|
||||
v: Vec::with_capacity(capacity),
|
||||
inner: Vec::with_capacity(capacity),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn set(&mut self, key: K, value: V) -> bool {
|
||||
if let Some(pos) = self.k.iter().position(|k| *k == key) {
|
||||
self.v[pos] = value;
|
||||
if let Some(kv) = self.inner.iter_mut().find(|kv| kv.key == key) {
|
||||
kv.value = value;
|
||||
false
|
||||
} else {
|
||||
self.k.push(key);
|
||||
self.v.push(value);
|
||||
self.inner.push(KeyValue { key, value });
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn append(&mut self, key: K, value: V) {
|
||||
self.k.push(key);
|
||||
self.v.push(value);
|
||||
self.inner.push(KeyValue { key, value });
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn insert(&mut self, idx: usize, key: K, value: V) {
|
||||
self.inner.insert(idx, KeyValue { key, value });
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
@@ -65,104 +66,158 @@ impl<K: Eq + PartialEq, V> VecMap<K, V> {
|
||||
where
|
||||
K: Borrow<Q> + PartialEq<Q>,
|
||||
{
|
||||
self.k.iter().position(|k| k == key).map(|pos| &self.v[pos])
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
|
||||
self.k
|
||||
.iter_mut()
|
||||
.position(|k| k == key)
|
||||
.map(|pos| &mut self.v[pos])
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn contains_key(&self, key: &K) -> bool {
|
||||
self.k.contains(key)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn remove(&mut self, key: &K) -> Option<V> {
|
||||
self.k.iter().position(|k| k == key).map(|pos| {
|
||||
self.k.swap_remove(pos);
|
||||
self.v.swap_remove(pos)
|
||||
self.inner.iter().find_map(|kv| {
|
||||
if &kv.key == key {
|
||||
Some(&kv.value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn remove_entry(&mut self, key: &K) -> Option<(K, V)> {
|
||||
self.k
|
||||
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
|
||||
self.inner.iter_mut().find_map(|kv| {
|
||||
if &kv.key == key {
|
||||
Some(&mut kv.value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn contains_key(&self, key: &K) -> bool {
|
||||
self.inner.iter().any(|kv| kv.key == *key)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn remove(&mut self, key: &K) -> Option<V> {
|
||||
self.inner
|
||||
.iter()
|
||||
.position(|k| k == key)
|
||||
.map(|pos| (self.k.swap_remove(pos), self.v.swap_remove(pos)))
|
||||
.position(|kv| kv.key == *key)
|
||||
.map(|pos| self.inner.remove(pos).value)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn remove_all(&mut self, key: &K) {
|
||||
self.inner.retain(|kv| kv.key != *key);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn remove_entry(&mut self, key: &K) -> Option<(K, V)> {
|
||||
self.inner.iter().position(|k| &k.key == key).map(|pos| {
|
||||
let kv = self.inner.remove(pos);
|
||||
(kv.key, kv.value)
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn swap_remove(&mut self, index: usize) -> V {
|
||||
self.k.swap_remove(index);
|
||||
self.v.swap_remove(index)
|
||||
self.inner.swap_remove(index).value
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.k.is_empty()
|
||||
self.inner.is_empty()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn len(&self) -> usize {
|
||||
self.k.len()
|
||||
self.inner.len()
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn clear(&mut self) {
|
||||
self.k.clear();
|
||||
self.v.clear();
|
||||
self.inner.clear();
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn iter(&self) -> impl Iterator<Item = (&K, &V)> {
|
||||
self.k.iter().zip(self.v.iter())
|
||||
self.inner.iter().map(|kv| (&kv.key, &kv.value))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn iter_by_key<'x, 'y: 'x>(&'x self, key: &'y K) -> impl Iterator<Item = &'x V> + 'x {
|
||||
self.inner.iter().filter_map(move |kv| {
|
||||
if &kv.key == key {
|
||||
Some(&kv.value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&mut K, &mut V)> {
|
||||
self.k.iter_mut().zip(self.v.iter_mut())
|
||||
self.inner.iter_mut().map(|kv| (&mut kv.key, &mut kv.value))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn iter_mut_by_key<'x, 'y: 'x>(
|
||||
&'x mut self,
|
||||
key: &'y K,
|
||||
) -> impl Iterator<Item = &'x mut V> + 'x {
|
||||
self.inner.iter_mut().filter_map(move |kv| {
|
||||
if &kv.key == key {
|
||||
Some(&mut kv.value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn keys(&self) -> impl Iterator<Item = &K> {
|
||||
self.k.iter()
|
||||
self.inner.iter().map(|kv| &kv.key)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn values(&self) -> impl Iterator<Item = &V> {
|
||||
self.v.iter()
|
||||
self.inner.iter().map(|kv| &kv.value)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
|
||||
self.v.iter_mut()
|
||||
self.inner.iter_mut().map(|kv| &mut kv.value)
|
||||
}
|
||||
|
||||
pub fn get_mut_or_insert_with(&mut self, key: K, fnc: impl FnOnce() -> V) -> &mut V {
|
||||
if let Some(pos) = self.k.iter().position(|k| k == &key) {
|
||||
&mut self.v[pos]
|
||||
if let Some(pos) = self.inner.iter().position(|kv| kv.key == key) {
|
||||
&mut self.inner[pos].value
|
||||
} else {
|
||||
self.k.push(key);
|
||||
self.v.push(fnc());
|
||||
self.v.last_mut().unwrap()
|
||||
self.inner.push(KeyValue { key, value: fnc() });
|
||||
&mut self.inner.last_mut().unwrap().value
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_key_value(mut self, key: K, value: V) -> Self {
|
||||
self.append(key, value);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn sort_unstable(&mut self)
|
||||
where
|
||||
K: Ord,
|
||||
V: Ord,
|
||||
{
|
||||
self.inner.sort_unstable_by(|a, b| match a.key.cmp(&b.key) {
|
||||
Ordering::Equal => a.value.cmp(&b.value),
|
||||
cmp => cmp,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Eq + PartialEq, V: Default> VecMap<K, V> {
|
||||
pub fn get_mut_or_insert(&mut self, key: K) -> &mut V {
|
||||
if let Some(pos) = self.k.iter().position(|k| k == &key) {
|
||||
&mut self.v[pos]
|
||||
if let Some(pos) = self.inner.iter().position(|kv| kv.key == key) {
|
||||
&mut self.inner[pos].value
|
||||
} else {
|
||||
self.k.push(key);
|
||||
self.v.push(V::default());
|
||||
self.v.last_mut().unwrap()
|
||||
self.inner.push(KeyValue {
|
||||
key,
|
||||
value: V::default(),
|
||||
});
|
||||
&mut self.inner.last_mut().unwrap().value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,20 +225,34 @@ impl<K: Eq + PartialEq, V: Default> VecMap<K, V> {
|
||||
impl<K: Eq + PartialEq, V> IntoIterator for VecMap<K, V> {
|
||||
type Item = (K, V);
|
||||
|
||||
type IntoIter = std::iter::Zip<std::vec::IntoIter<K>, std::vec::IntoIter<V>>;
|
||||
type IntoIter =
|
||||
std::iter::Map<std::vec::IntoIter<KeyValue<K, V>>, fn(KeyValue<K, V>) -> (K, V)>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.k.into_iter().zip(self.v)
|
||||
self.inner.into_iter().map(|kv| (kv.key, kv.value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'x, K: Eq + PartialEq, V> IntoIterator for &'x VecMap<K, V> {
|
||||
type Item = (&'x K, &'x V);
|
||||
|
||||
type IntoIter = std::iter::Zip<std::slice::Iter<'x, K>, std::slice::Iter<'x, V>>;
|
||||
type IntoIter = std::iter::Map<
|
||||
std::slice::Iter<'x, KeyValue<K, V>>,
|
||||
fn(&'x KeyValue<K, V>) -> (&'x K, &'x V),
|
||||
>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.k.iter().zip(self.v.iter())
|
||||
self.inner.iter().map(|kv| (&kv.key, &kv.value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> Hash for VecMap<K, V>
|
||||
where
|
||||
K: Eq + PartialEq + Hash,
|
||||
V: Hash,
|
||||
{
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.inner.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user