use crate::error::Error;
#[derive(Debug)]
pub struct Event {
pub kind: EventKind,
}
#[derive(Debug)]
pub enum EventKind {
DriveOpened { device: String },
DriveReady,
InitComplete { success: bool },
ProbeComplete { success: bool },
ScanComplete { titles: usize },
BytesRead {
bytes: u64,
total: u64,
},
ReadError {
sector: u64,
error: Error,
},
Retry {
attempt: u32,
},
SpeedChange {
speed_kbs: u16,
},
ExtentStart {
index: usize,
start_sector: u64,
sector_count: u64,
},
SectorRecovered { sector: u64 },
SectorSkipped { sector: u64 },
BatchSizeChanged {
new_size: u16,
reason: BatchSizeReason,
},
Complete {
bytes: u64,
errors: u32,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum BatchSizeReason {
Shrunk,
Probed,
}
pub fn ignore(_event: Event) {}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bytes_read_fields_are_u64() {
let event = Event {
kind: EventKind::BytesRead {
bytes: u64::MAX,
total: u64::MAX,
},
};
match event.kind {
EventKind::BytesRead { bytes, total } => {
assert_eq!(bytes, u64::MAX);
assert_eq!(total, u64::MAX);
}
_ => panic!("wrong variant"),
}
}
#[test]
fn sector_skipped_field_is_u64() {
let event = Event {
kind: EventKind::SectorSkipped { sector: u64::MAX },
};
match event.kind {
EventKind::SectorSkipped { sector } => {
assert_eq!(sector, u64::MAX);
}
_ => panic!("wrong variant"),
}
}
#[test]
fn batch_size_reason_variants_are_not_equal() {
assert_ne!(BatchSizeReason::Shrunk, BatchSizeReason::Probed);
}
#[test]
fn batch_size_reason_eq_is_reflexive() {
assert_eq!(BatchSizeReason::Shrunk, BatchSizeReason::Shrunk);
assert_eq!(BatchSizeReason::Probed, BatchSizeReason::Probed);
}
#[test]
fn batch_size_reason_is_copy() {
let r = BatchSizeReason::Shrunk;
let _r2 = r; let _r3 = r; }
#[test]
fn batch_size_changed_constructs_and_destructs() {
let event = Event {
kind: EventKind::BatchSizeChanged {
new_size: 32,
reason: BatchSizeReason::Shrunk,
},
};
match event.kind {
EventKind::BatchSizeChanged { new_size, reason } => {
assert_eq!(new_size, 32);
assert_eq!(reason, BatchSizeReason::Shrunk);
}
_ => panic!("wrong variant"),
}
}
#[test]
fn extent_start_fields_are_correct_types() {
let event = Event {
kind: EventKind::ExtentStart {
index: 0,
start_sector: u64::MAX,
sector_count: u64::MAX,
},
};
match event.kind {
EventKind::ExtentStart {
index,
start_sector,
sector_count,
} => {
assert_eq!(index, 0);
assert_eq!(start_sector, u64::MAX);
assert_eq!(sector_count, u64::MAX);
}
_ => panic!("wrong variant"),
}
}
#[test]
fn complete_fields_are_correct_types() {
let event = Event {
kind: EventKind::Complete {
bytes: u64::MAX,
errors: u32::MAX,
},
};
match event.kind {
EventKind::Complete { bytes, errors } => {
assert_eq!(bytes, u64::MAX);
assert_eq!(errors, u32::MAX);
}
_ => panic!("wrong variant"),
}
}
#[test]
fn ignore_accepts_any_event() {
ignore(Event {
kind: EventKind::DriveReady,
});
ignore(Event {
kind: EventKind::BytesRead { bytes: 0, total: 0 },
});
ignore(Event {
kind: EventKind::SectorSkipped { sector: 0 },
});
ignore(Event {
kind: EventKind::Complete {
bytes: 0,
errors: 0,
},
});
ignore(Event {
kind: EventKind::BatchSizeChanged {
new_size: 16,
reason: BatchSizeReason::Probed,
},
});
}
#[test]
fn speed_change_sentinel_max_is_0xffff() {
let event = Event {
kind: EventKind::SpeedChange { speed_kbs: 0xFFFF },
};
match event.kind {
EventKind::SpeedChange { speed_kbs } => {
assert_eq!(
speed_kbs, 0xFFFF,
"0xFFFF is the max-speed sentinel (MMC spec)"
);
}
_ => panic!("wrong variant"),
}
}
#[test]
fn read_error_carries_error_and_sector() {
use crate::error::Error;
let event = Event {
kind: EventKind::ReadError {
sector: 99_999,
error: Error::Halted,
},
};
match event.kind {
EventKind::ReadError { sector, .. } => {
assert_eq!(sector, 99_999u64);
}
_ => panic!("wrong variant"),
}
}
#[test]
fn retry_attempt_is_u32() {
let event = Event {
kind: EventKind::Retry { attempt: u32::MAX },
};
match event.kind {
EventKind::Retry { attempt } => {
assert_eq!(attempt, u32::MAX);
}
_ => panic!("wrong variant"),
}
}
}