refactor(uffs-mft): introduce Usn(i64) newtype for journal USNs#257
Merged
Conversation
Replaces ad-hoc `i64` USN values with a typed `uffs_mft::usn::Usn` newtype so cache wrap detection, checkpoint persistence, and journal record fields stop relying on raw integers that any caller could mis-interpret as a generic counter. The newtype is `Copy + Eq + Ord + Hash + Display` and exposes `Usn::ZERO`, `Usn::new`, `Usn::raw`, and `Usn::is_zero` so: * monotonic comparisons (`cached_usn < first_usn`, `start_usn >= next_usn`) read directly from the type rather than re-deriving meaning from `i64` arithmetic; * the `0` sentinel meaning "no prior checkpoint — read from journal head" gets a self-documenting constant; * tracing fields use `%`-Display so logs render `123` not `Usn(123)`. ## Wire format unchanged Pinned by `tests_extensions::serialize_roundtrip` / `tests_storage::empty_serialized_index` / `usn::tests::raw_roundtrip_preserves_i64_exactly`: * on-disk `IndexHeader.next_usn` still serializes as 8 LE i64 bytes via `.raw().to_le_bytes()` and deserializes via `Usn::new(read_i64)`; * daemon-side `JournalSource::poll` keeps its `cursor: u64` persistence contract — the `Usn` wrap/unwrap is a single call-boundary narrowing inside `sources.rs`; * the `#[repr(C)]` Win32 ABI mirror structs (`UsnJournalDataV0`, `ReadUsnJournalDataV0`, `UsnRecordV2Header`) keep their raw `i64` fields — they mirror `winioctl.h` byte-for-byte; * the `uffs-mft usn-read --start-usn <i64>` CLI flag stays `Option<i64>` and is wrapped at the consumer site. ## File split Migrating UI doc + tests pushed `usn.rs` over the 800-LOC policy limit. Split into `usn/mod.rs` (DTOs + reason flags + aggregation + non-Windows stubs + tests, 428 LOC) and `usn/windows.rs` (Win32 FFI mirror structs + ioctl helpers + targeted FRS reads, 527 LOC). No file needs a size-policy exception. ## Untouched on purpose `StandardInfo.usn: u64` (from the NTFS `$STANDARD_INFORMATION` attribute) is a separate USN flavour with a different signedness contract; out of scope for this PR.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces ad-hoc `i64` USN values across the cache-checkpoint, journal-read, and incremental-apply paths with a typed `uffs_mft::usn::Usn` newtype. Cache wrap detection (`cached_usn < first_usn`), checkpoint persistence, and `UsnRecord.usn` now read directly off the type instead of relying on bare integer arithmetic that any caller could mis-interpret as a generic counter.
Why
Phase 4 sub-phase 5c of the platform-typing refactor. After 5b.0/5b.1 (DriveLetter, PipeName) it was the last hot-path identifier still flowing as a primitive. The newtype is `Copy + Eq + Ord + Hash + Display` so:
Wire format unchanged
Three regression tests pin the contract:
Out of scope on purpose
File split
The migration (newtype + unit tests) pushed `usn.rs` from 767 LOC over the 800-LOC policy limit. Rather than add an exception entry, split into two cohesive units:
`pub use windows::{query_usn_journal, read_targeted_frs_records, read_usn_journal}` keeps the public API path `uffs_mft::usn::*` unchanged.
Verification