|
62 | 62 |
|
63 | 63 | use std::any::TypeId;
|
64 | 64 | use std::collections::hash_map::HashMap;
|
| 65 | +use std::fmt::Debug; |
| 66 | +use std::sync::Arc; |
65 | 67 |
|
66 | 68 | const BASE_VERSION: u16 = 1;
|
67 | 69 |
|
| 70 | +/// Trait to check whether is specific `version` is supported by a `VersionMap`. |
| 71 | +pub trait VersionFilter: Debug { |
| 72 | + /// Check whether the `version` is supported or not. |
| 73 | + fn is_supported(&self, version: u16) -> bool; |
| 74 | +} |
| 75 | + |
| 76 | +impl VersionFilter for () { |
| 77 | + fn is_supported(&self, _version: u16) -> bool { |
| 78 | + true |
| 79 | + } |
| 80 | +} |
68 | 81 | ///
|
69 | 82 | /// The VersionMap API provides functionality to define the version for each
|
70 | 83 | /// type and attach them to specific root versions.
|
71 |
| -#[derive(Clone, Debug, Default)] |
| 84 | +#[derive(Clone, Debug)] |
72 | 85 | pub struct VersionMap {
|
73 | 86 | versions: Vec<HashMap<TypeId, u16>>,
|
| 87 | + filter: Arc<dyn VersionFilter>, |
| 88 | +} |
| 89 | + |
| 90 | +impl Default for VersionMap { |
| 91 | + fn default() -> Self { |
| 92 | + VersionMap { |
| 93 | + versions: vec![HashMap::new(); 1], |
| 94 | + filter: Arc::new(()), |
| 95 | + } |
| 96 | + } |
74 | 97 | }
|
75 | 98 |
|
76 | 99 | impl VersionMap {
|
77 | 100 | /// Create a new version map initialized at version 1.
|
78 | 101 | pub fn new() -> Self {
|
| 102 | + Default::default() |
| 103 | + } |
| 104 | + |
| 105 | + /// Create a new version map with specified version filter. |
| 106 | + pub fn with_filter(filter: Arc<dyn VersionFilter>) -> Self { |
79 | 107 | VersionMap {
|
80 | 108 | versions: vec![HashMap::new(); 1],
|
| 109 | + filter, |
81 | 110 | }
|
82 | 111 | }
|
83 | 112 |
|
@@ -119,16 +148,36 @@ impl VersionMap {
|
119 | 148 | pub fn latest_version(&self) -> u16 {
|
120 | 149 | self.versions.len() as u16
|
121 | 150 | }
|
| 151 | + |
| 152 | + /// Check whether the `version` is supported by the version map. |
| 153 | + pub fn is_supported(&self, version: u16) -> bool { |
| 154 | + if version == 0 || version > self.latest_version() { |
| 155 | + false |
| 156 | + } else { |
| 157 | + self.filter.is_supported(version) |
| 158 | + } |
| 159 | + } |
122 | 160 | }
|
123 | 161 |
|
124 | 162 | #[cfg(test)]
|
125 | 163 | mod tests {
|
126 | 164 | use super::{TypeId, VersionMap, BASE_VERSION};
|
| 165 | + use std::sync::Arc; |
| 166 | + use version_map::VersionFilter; |
127 | 167 |
|
128 | 168 | pub struct MyType;
|
129 | 169 | pub struct MySecondType;
|
130 | 170 | pub struct MyThirdType;
|
131 | 171 |
|
| 172 | + #[derive(Debug)] |
| 173 | + struct MyFilter; |
| 174 | + |
| 175 | + impl VersionFilter for MyFilter { |
| 176 | + fn is_supported(&self, version: u16) -> bool { |
| 177 | + version < 5 |
| 178 | + } |
| 179 | + } |
| 180 | + |
132 | 181 | #[test]
|
133 | 182 | fn test_default_version() {
|
134 | 183 | let vm = VersionMap::new();
|
@@ -223,4 +272,32 @@ mod tests {
|
223 | 272 | assert_eq!(vm.get_type_version(129, TypeId::of::<MyType>()), 2);
|
224 | 273 | assert_eq!(vm.get_type_version(1, TypeId::of::<MyType>()), BASE_VERSION);
|
225 | 274 | }
|
| 275 | + |
| 276 | + #[test] |
| 277 | + fn test_version_filter() { |
| 278 | + let mut vm = VersionMap::default(); |
| 279 | + vm.new_version(); |
| 280 | + |
| 281 | + assert_eq!(vm.is_supported(0), false); |
| 282 | + assert_eq!(vm.is_supported(1), true); |
| 283 | + assert_eq!(vm.is_supported(2), true); |
| 284 | + assert_eq!(vm.is_supported(3), false); |
| 285 | + |
| 286 | + let mut vm = VersionMap::with_filter(Arc::new(MyFilter)); |
| 287 | + vm.new_version(); |
| 288 | + vm.new_version(); |
| 289 | + vm.new_version(); |
| 290 | + vm.new_version(); |
| 291 | + vm.new_version(); |
| 292 | + |
| 293 | + let vm1 = vm.clone(); |
| 294 | + assert_eq!(vm1.is_supported(0), false); |
| 295 | + assert_eq!(vm1.is_supported(1), true); |
| 296 | + assert_eq!(vm1.is_supported(2), true); |
| 297 | + assert_eq!(vm1.is_supported(3), true); |
| 298 | + assert_eq!(vm1.is_supported(4), true); |
| 299 | + assert_eq!(vm1.is_supported(5), false); |
| 300 | + assert_eq!(vm1.is_supported(6), false); |
| 301 | + assert_eq!(vm.latest_version(), 6); |
| 302 | + } |
226 | 303 | }
|
0 commit comments