wire_enum! {
#[derive(Default)]
pub enum ClientVerb: u8 {
#[default]
ScanSpec = 0,
Push = 1,
DeltaPoll = 4,
Resolve = 5,
DdlTxn = 6,
PushTxn = 7,
ScanMulti = 8,
AllocSerialRange = 9,
AllocIds = 10,
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub struct WireFlags {
pub verb: ClientVerb,
pub conflict_mode: WireConflictMode,
pub continuation: bool,
pub scan_last: bool,
pub probe_mode: WireProbeMode,
}
pub(crate) const FLAG_HAS_SCHEMA: u64 = 1 << 32;
pub(crate) const FLAG_HAS_DATA: u64 = 1 << 33;
const RESERVED_BITS: u64 = !crate::low_bits_mask(38) | (crate::low_bits_mask(32) & !crate::low_bits_mask(16));
impl WireFlags {
pub const fn train_frame(last: bool) -> Self {
WireFlags {
verb: ClientVerb::ScanSpec,
conflict_mode: WireConflictMode::Update,
continuation: true,
scan_last: last,
probe_mode: WireProbeMode::Pk,
}
}
pub const fn pack(self) -> u64 {
self.verb as u64
| (self.conflict_mode as u64) << 8
| (self.continuation as u64) << 34
| (self.scan_last as u64) << 35
| (self.probe_mode as u64) << 36
}
pub fn unpack(w: u64) -> Result<Self, &'static str> {
if w & RESERVED_BITS != 0 {
return Err("flags: reserved bits set");
}
let bit = |b: u32| (w >> b) & 1 != 0;
Ok(WireFlags {
verb: ClientVerb::from_wire(w as u8).ok_or("flags: unknown request verb")?,
conflict_mode: WireConflictMode::from_wire((w >> 8) as u8).ok_or("flags: unknown conflict mode")?,
continuation: bit(34),
scan_last: bit(35),
probe_mode: WireProbeMode::from_wire(((w >> 36) & 3) as u8).ok_or("flags: unknown probe mode")?,
})
}
}
wire_enum! {
#[derive(Default)]
pub enum WireConflictMode: u8 {
#[default]
Update = 0,
Error = 1,
}
}
wire_enum! {
#[derive(Default)]
pub enum WireProbeMode: u8 {
#[default]
Pk = 0,
PkColumn = 1,
Index = 2,
}
}
impl std::str::FromStr for WireConflictMode {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"update" => Ok(WireConflictMode::Update),
"error" => Ok(WireConflictMode::Error),
other => Err(format!("invalid conflict mode '{other}', expected 'update' or 'error'")),
}
}
}
wire_enum! {
#[derive(Default)]
pub enum WireStatus: u32 {
#[default]
Ok = 0,
Error = 1,
TxnConflict = 3,
DeltaExpired = 4,
SalFull = 5,
NotFound = 6,
IntegrityViolation = 7,
StaleCatalog = 8,
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct WireFault {
pub status: WireStatus,
pub text: String,
}
impl<S: Into<String>> From<S> for WireFault {
fn from(text: S) -> Self {
WireFault {
status: WireStatus::Error,
text: text.into(),
}
}
}
impl std::fmt::Display for WireFault {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.text)
}
}
#[cfg(test)]
#[path = "tests/flags.rs"]
mod tests;