rustifact/phf/
ordered_map.rs

1use crate::tokens::ToTokenStream;
2use proc_macro2::TokenStream;
3use quote::quote;
4
5/// A compile time builder for an order-preserving immutable map.
6///
7/// Produces a highly optimised `OrderedMap` when output (for example, by `write_static!`) from the build script.
8///
9/// Internally, this is a wrapper for `phf_codegen::OrderedMap` from the excellent
10/// [phf_codegen](https://crates.io/crates/phf_codegen) crate.
11///
12/// *This API requires the following crate feature to be activated: `map`*
13pub struct OrderedMapBuilder<K, V>(phf_codegen::OrderedMap<K>, std::marker::PhantomData<V>);
14
15/// An order-preserving immutable map with lookup via a perfect hash function.
16///
17/// Constructable at compile time with a `BuildOrderedMap`. Unlike a `Map`, iteration order is guaranteed to
18/// match the definition order.
19///
20/// Internally, this is a wrapper for `phf::OrderedMap` from the excellent
21/// [phf](https://crates.io/crates/phf) crate.
22///
23/// *This API requires the following crate feature to be activated: `map`*
24pub struct OrderedMap<K: 'static, V: 'static>(phf::OrderedMap<K, V>);
25
26impl<K, V> OrderedMapBuilder<K, V>
27where
28    K: ToTokenStream + std::hash::Hash + phf_shared::PhfHash + Eq + phf_shared::FmtConst,
29    V: ToTokenStream,
30{
31    pub fn new() -> OrderedMapBuilder<K, V> {
32        let mut internal = phf_codegen::OrderedMap::new();
33        internal.phf_path("rustifact::internal::phf");
34        OrderedMapBuilder(internal, std::marker::PhantomData)
35    }
36
37    #[inline]
38    pub fn entry(&mut self, key: K, value: V) {
39        self.0.entry(key, &value.to_tok_stream().to_string());
40    }
41}
42
43impl<K, V> OrderedMap<K, V> {
44    #[inline]
45    pub const fn len(&self) -> usize {
46        self.0.len()
47    }
48
49    #[inline]
50    pub const fn is_empty(&self) -> bool {
51        self.0.is_empty()
52    }
53
54    #[inline]
55    pub fn contains_key<T>(&self, key: &T) -> bool
56    where
57        T: phf_shared::PhfHash + Eq + ?Sized,
58        K: phf_shared::PhfBorrow<T>,
59    {
60        self.0.contains_key(key)
61    }
62
63    #[inline]
64    pub fn get<T>(&self, key: &T) -> Option<&V>
65    where
66        T: phf_shared::PhfHash + Eq + ?Sized,
67        K: phf_shared::PhfBorrow<T>,
68    {
69        self.0.get(key)
70    }
71
72    #[inline]
73    pub fn get_key<T>(&self, key: &T) -> Option<&K>
74    where
75        T: phf_shared::PhfHash + Eq + ?Sized,
76        K: phf_shared::PhfBorrow<T>,
77    {
78        self.0.get_key(key)
79    }
80
81    #[inline]
82    pub fn get_entry<T>(&self, key: &T) -> Option<(&K, &V)>
83    where
84        T: phf_shared::PhfHash + Eq + ?Sized,
85        K: phf_shared::PhfBorrow<T>,
86    {
87        self.0.get_entry(key)
88    }
89
90    #[inline]
91    pub fn get_index<T>(&self, key: &T) -> Option<usize>
92    where
93        T: phf_shared::PhfHash + Eq + ?Sized,
94        K: phf_shared::PhfBorrow<T>,
95    {
96        self.0.get_index(key)
97    }
98
99    #[inline]
100    pub fn index<T>(&self, index: usize) -> Option<(&K, &V)> {
101        self.0.index(index)
102    }
103
104    #[inline]
105    pub fn entries(&self) -> phf::ordered_map::Entries<'_, K, V> {
106        self.0.entries()
107    }
108
109    #[inline]
110    pub fn keys(&self) -> phf::ordered_map::Keys<'_, K, V> {
111        self.0.keys()
112    }
113
114    #[inline]
115    pub fn values(&self) -> phf::ordered_map::Values<'_, K, V> {
116        self.0.values()
117    }
118
119    /// An implementation detail. You shouldn't need to call this function.
120    #[inline]
121    pub const fn init_raw(map: phf::OrderedMap<K, V>) -> OrderedMap<K, V> {
122        OrderedMap(map)
123    }
124}
125
126impl<K, V> ToTokenStream for OrderedMapBuilder<K, V>
127where
128    K: ToTokenStream + std::hash::Hash + phf_shared::PhfHash + Eq + phf_shared::FmtConst,
129{
130    fn to_toks(&self, tokens: &mut TokenStream) {
131        let map_toks_str = self.0.build().to_string();
132        if let Ok(t) = crate::internal::parse_str::<syn::Expr>(&map_toks_str) {
133            tokens.extend(quote! { rustifact::OrderedMap::init_raw(#t) });
134        } else {
135            panic!("Couldn't parse the expression '{}'", map_toks_str);
136        }
137    }
138}