Make Sequence impl work without changing dumps

This commit is contained in:
F. Levi 2024-11-13 10:59:42 +02:00
parent 7e45125e7a
commit 146c87bd6f
2 changed files with 99 additions and 76 deletions

View File

@ -405,11 +405,11 @@ impl From<v5::Action> for v6::Action {
v5::Action::SettingsAll => v6::Action::SettingsAll,
v5::Action::SettingsGet => v6::Action::SettingsGet,
v5::Action::SettingsUpdate => v6::Action::SettingsUpdate,
v5::Action::StatsAll => v6::Action::StatsGet,
v5::Action::StatsAll => v6::Action::StatsAll,
v5::Action::StatsGet => v6::Action::StatsGet,
v5::Action::MetricsAll => v6::Action::MetricsGet,
v5::Action::MetricsAll => v6::Action::MetricsAll,
v5::Action::MetricsGet => v6::Action::MetricsGet,
v5::Action::DumpsAll => v6::Action::DumpsCreate,
v5::Action::DumpsAll => v6::Action::DumpsAll,
v5::Action::DumpsCreate => v6::Action::DumpsCreate,
v5::Action::Version => v6::Action::Version,
v5::Action::KeysAdd => v6::Action::KeysAdd,

View File

@ -183,6 +183,7 @@ fn parse_expiration_date(
bitflags! {
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
// NOTE: For `Sequence` impl to work, the values of these must be in ascending order
pub struct Action: u32 {
const Search = 1;
// Documents
@ -206,10 +207,19 @@ bitflags! {
const SettingsGet = 1 << 12;
const SettingsUpdate = 1 << 13;
const SettingsAll = Self::SettingsGet.bits() | Self::SettingsUpdate.bits();
// Stats
const StatsGet = 1 << 14;
const StatsAll = Self::StatsGet.bits();
// Metrics
const MetricsGet = 1 << 15;
const MetricsAll = Self::MetricsGet.bits();
// Dumps
const DumpsCreate = 1 << 16;
const DumpsAll = Self::DumpsCreate.bits();
// Snapshots
const SnapshotsCreate = 1 << 17;
const SnapshotsAll = Self::SnapshotsCreate.bits();
// Keys without an "all" version
const Version = 1 << 18;
const KeysAdd = 1 << 19;
const KeysGet = 1 << 20;
@ -217,22 +227,13 @@ bitflags! {
const KeysDelete = 1 << 22;
const ExperimentalFeaturesGet = 1 << 23;
const ExperimentalFeaturesUpdate = 1 << 24;
const All = {
let mut all = 0;
let mut exp = 0;
while exp <= 24 {
all = (all << 1) + 1;
exp += 1;
}
all
};
// All
const All = 0xFFFFFFFF >> (32 - 1 - 24);
}
}
impl Action {
const SERDE_MAP_ARR: [(&'static str, Self); 30] = [
const SERDE_MAP_ARR: [(&'static str, Self); 34] = [
("search", Self::Search),
("documents.add", Self::DocumentsAdd),
("documents.get", Self::DocumentsGet),
@ -252,9 +253,13 @@ impl Action {
("settings.update", Self::SettingsUpdate),
("settings.*", Self::SettingsAll),
("stats.get", Self::StatsGet),
("stats.*", Self::StatsAll),
("metrics.get", Self::MetricsGet),
("metrics.*", Self::MetricsAll),
("dumps.create", Self::DumpsCreate),
("dumps.*", Self::DumpsAll),
("snapshots.create", Self::SnapshotsCreate),
("snapshots.*", Self::SnapshotsAll),
("version", Self::Version),
("keys.create", Self::KeysAdd),
("keys.get", Self::KeysGet),
@ -279,6 +284,19 @@ impl Action {
.map(|(serde_name, _)| serde_name)
.expect("an action is missing a matching serialized value")
}
// when we remove "all" flags, this will give us the exact index
fn get_potential_index(&self) -> usize {
if self.is_empty() {
return 0;
}
// most significant bit for u32
let msb = 1u32 << (31 - self.bits().leading_zeros());
// index of the single set bit
msb.trailing_zeros() as usize
}
}
pub mod actions {
@ -303,9 +321,13 @@ pub mod actions {
pub const SETTINGS_UPDATE: u32 = A::SettingsUpdate.bits();
pub const SETTINGS_ALL: u32 = A::SettingsAll.bits();
pub const STATS_GET: u32 = A::StatsGet.bits();
pub const STATS_ALL: u32 = A::StatsAll.bits();
pub const METRICS_GET: u32 = A::MetricsGet.bits();
pub const METRICS_ALL: u32 = A::MetricsAll.bits();
pub const DUMPS_CREATE: u32 = A::DumpsCreate.bits();
pub const DUMPS_ALL: u32 = A::DumpsAll.bits();
pub const SNAPSHOTS_CREATE: u32 = A::SnapshotsCreate.bits();
pub const SNAPSHOTS_ALL: u32 = A::SnapshotsAll.bits();
pub const VERSION: u32 = A::Version.bits();
pub const KEYS_CREATE: u32 = A::KeysAdd.bits();
pub const KEYS_GET: u32 = A::KeysGet.bits();
@ -313,6 +335,7 @@ pub mod actions {
pub const KEYS_DELETE: u32 = A::KeysDelete.bits();
pub const EXPERIMENTAL_FEATURES_GET: u32 = A::ExperimentalFeaturesGet.bits();
pub const EXPERIMENTAL_FEATURES_UPDATE: u32 = A::ExperimentalFeaturesUpdate.bits();
pub const ALL: u32 = A::All.bits();
}
impl<E: DeserializeError> Deserr<E> for Action {
@ -381,49 +404,49 @@ impl<'de> Deserialize<'de> for Action {
}
}
// TODO: Once "all" type flags are removed, simplify
// Essentially `get_potential_index` will give the exact index, +1 the exact next, -1 the exact previous
impl Sequence for Action {
const CARDINALITY: usize = Self::FLAGS.len();
fn next(&self) -> Option<Self> {
let mut iter = Self::FLAGS.iter();
while let Some(action) = iter.next() {
if action.value() == self {
if let Some(action) = iter.next() {
return Some(*action.value());
let mut potential_next_index = self.get_potential_index() + 1;
loop {
if let Some(next_flag) = Self::FLAGS.get(potential_next_index) {
let next_flag_value = next_flag.value();
if next_flag_value > self {
return Some(*next_flag_value);
}
break;
potential_next_index += 1;
} else {
return None;
}
}
None
}
fn previous(&self) -> Option<Self> {
let mut iter = Self::FLAGS.iter().peekable();
// -2 because of "all" type flags that represent a single flag, otherwise -1 would suffice
let mut potential_previous_index = self.get_potential_index() - 2;
let mut previous_item: Option<Self> = None;
if let Some(action) = iter.next() {
if action.value() == self {
loop {
if let Some(next_flag) = Self::FLAGS.get(potential_previous_index) {
let next_flag_value = next_flag.value();
if next_flag_value > self {
return previous_item;
}
previous_item = Some(*next_flag_value);
potential_previous_index += 1;
} else {
return None;
}
if let Some(next_action) = iter.peek() {
if next_action.value() == self {
return Some(*action.value());
}
}
}
while let Some(action) = iter.next() {
if let Some(next_action) = iter.peek() {
if next_action.value() == self {
return Some(*action.value());
}
}
}
None
}
fn first() -> Option<Self> {
Self::FLAGS.first().map(|v| *v.value())