ferrum_router/recognizer/
types.rs1use std::collections::HashMap;
2use std::cmp::Eq;
3use std::hash::Hash;
4use std::borrow::Borrow;
5use std::marker::{Send, Sync};
6
7pub type NameDefaultType = &'static str;
8pub type PatternDefaultType = &'static str;
9
10pub struct Type;
11
12impl Type {
13 pub const STRING_NAME: NameDefaultType = "string";
14 pub const STRING_PATTERN: PatternDefaultType = "[^/.]+";
15
16 pub const NUMBER_NAME: NameDefaultType = "number";
17 pub const NUMBER_PATTERN: PatternDefaultType = "[0-9]+";
18}
19
20pub trait TypeName: Eq + Hash + Borrow<str> + Send + Sync {}
21impl<T: Eq + Hash + Borrow<str> + Send + Sync> TypeName for T {}
22
23pub trait TypePattern: AsRef<str> + Send + Sync {}
24impl<T: AsRef<str> + Send + Sync> TypePattern for T {}
25
26pub type Store<N, P> = HashMap<N, P>;
27
28pub type DefaultStore = Store<NameDefaultType, PatternDefaultType>;
29
30pub trait DefaultStoreBuild {
31 fn with_default_types() -> Self;
32}
33
34impl DefaultStoreBuild for DefaultStore {
35 fn with_default_types() -> Self {
36 let mut store = DefaultStore::new();
37 store.insert(Type::STRING_NAME, Type::STRING_PATTERN);
38 store.insert(Type::NUMBER_NAME, Type::NUMBER_PATTERN);
39 store
40 }
41}
42
43pub trait GlobTypes {
44 type Name: TypeName;
45 type Pattern: TypePattern;
46
47 fn store(&self) -> &Store<Self::Name, Self::Pattern>;
48}
49
50pub trait GlobTypesMut: GlobTypes {
51 fn store_mut(&mut self) -> &mut Store<Self::Name, Self::Pattern>;
52}
53
54impl<N, P> GlobTypes for Store<N, P>
55 where N: TypeName,
56 P: TypePattern
57{
58 type Name = N;
59 type Pattern = P;
60
61 fn store(&self) -> &Store<Self::Name, Self::Pattern> {
62 self
63 }
64}
65
66impl<N, P> GlobTypesMut for Store<N, P>
67 where N: TypeName,
68 P: TypePattern
69{
70 fn store_mut(&mut self) -> &mut Store<Self::Name, Self::Pattern> {
71 self
72 }
73}
74
75impl<'a, N, P> GlobTypes for &'a Store<N, P>
76 where N: TypeName,
77 P: TypePattern
78{
79 type Name = N;
80 type Pattern = P;
81
82 fn store(&self) -> &Store<Self::Name, Self::Pattern> {
83 *self
84 }
85}
86
87impl<'a, N, P> GlobTypes for &'a mut Store<N, P>
88 where N: TypeName,
89 P: TypePattern
90{
91 type Name = N;
92 type Pattern = P;
93
94 fn store(&self) -> &Store<Self::Name, Self::Pattern> {
95 *self
96 }
97}
98
99impl<'a, N, P> GlobTypesMut for &'a mut Store<N, P>
100 where N: TypeName,
101 P: TypePattern
102{
103 fn store_mut(&mut self) -> &mut Store<Self::Name, Self::Pattern> {
104 &mut **self
105 }
106}
107
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 fn get_glob_types_value<'a, T>(types: &'a T, key: <T as GlobTypes>::Name) -> &'a <T as GlobTypes>::Pattern
114 where T: GlobTypes
115 {
116 types.store().get(key.borrow()).unwrap()
117 }
118
119 fn equal_glob_types_value<T>(types: T, key: <T as GlobTypes>::Name, expected: <T as GlobTypes>::Pattern)
120 where T: GlobTypes,
121 {
122 let value = types.store().get(key.borrow()).unwrap();
123 assert_eq!(value.as_ref(), expected.as_ref());
124 }
125
126 #[test]
127 fn use_different_glob_types() {
128 let mut types = Store::default();
129 types.insert("key", "value");
130
131 let value = types.get("key").unwrap();
132 assert_eq!(*value, "value");
133
134 let value = get_glob_types_value(&types, "key");
135 assert_eq!(*value, "value");
136
137 equal_glob_types_value(&types, "key", "value");
138 equal_glob_types_value(types.clone(), "key", "value");
139
140
141 let mut types = Store::default();
142 types.insert("key", "value".to_string());
143
144 let value = types.get("key").unwrap();
145 assert_eq!(*value, "value".to_string());
146
147 let value = get_glob_types_value(&types, "key");
148 assert_eq!(*value, "value".to_string());
149
150 equal_glob_types_value(&types, "key", "value".to_string());
151 equal_glob_types_value(types.clone(), "key", "value".to_string());
152 }
153}