ferrum_router/recognizer/
types.rs

1use 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}