Turned various functions in util and io const.

Added missing `Sub` and `SubAssign` implementations to `io::address::Real`.
Added `from_u64` and `as_u64` to both address types in `io`.
This commit is contained in:
2020-09-09 12:12:08 +01:00
parent ffd06d4f28
commit ae8402634a
4 changed files with 63 additions and 21 deletions

View File

@@ -15,23 +15,28 @@ use crate::{
pub struct Data(u64);
impl Data {
/// Constructs a data address from it's `u64` representation
/// Creates a data address from a `u64`
#[must_use]
pub const fn from_u64(address: u64) -> Self {
Self(address)
}
/// Returns this address as a `u64`
#[must_use]
pub const fn as_u64(self) -> u64 {
self.0
}
/// Returns the sector associated with this address
#[must_use]
#[allow(clippy::integer_division)] // We want to get the whole division
pub fn sector(self) -> u64 {
u64::from(self) / Real::DATA_BYTE_SIZE
pub const fn sector(self) -> u64 {
self.as_u64() / Real::DATA_BYTE_SIZE
}
/// Returns the offset into the data section of this address
#[must_use]
pub fn offset(self) -> u64 {
u64::from(self) % Real::DATA_BYTE_SIZE
pub const fn offset(self) -> u64 {
self.as_u64() % Real::DATA_BYTE_SIZE
}
}

View File

@@ -30,28 +30,39 @@ impl Real {
}
impl Real {
/// Creates a real address from a `u64`
#[must_use]
pub const fn from_u64(address: u64) -> Self {
Self(address)
}
/// Returns this address as a `u64`
#[must_use]
pub const fn as_u64(self) -> u64 {
self.0
}
/// Returns the real sector associated with this address
#[must_use]
#[allow(clippy::integer_division)] // We want to get the whole division
pub fn sector(self) -> u64 {
u64::from(self) / Self::SECTOR_BYTE_SIZE
pub const fn sector(self) -> u64 {
self.as_u64() / Self::SECTOR_BYTE_SIZE
}
/// Returns the offset into the sector of this address
#[must_use]
pub fn offset(self) -> u64 {
u64::from(self) % Self::SECTOR_BYTE_SIZE
pub const fn offset(self) -> u64 {
self.as_u64() % Self::SECTOR_BYTE_SIZE
}
/// Returns the address of the end of the data section in this sector.
#[must_use]
pub fn data_section_end(self) -> Self {
pub const fn data_section_end(self) -> Self {
// Get the sector
let real_sector = self.sector();
// The end of the real data section is after the header and data sections
#[rustfmt::skip]
Self::from(
Self::from_u64(
Self::SECTOR_BYTE_SIZE * real_sector + // Beginning of sector
Self::HEADER_BYTE_SIZE + // Skip Header
Self:: DATA_BYTE_SIZE, // Skip Data
@@ -60,9 +71,11 @@ impl Real {
/// Checks if this address is within the real data section
#[must_use]
pub fn in_data_section(self) -> bool {
pub const fn in_data_section(self) -> bool {
// If our offset is within the data range
Self::DATA_RANGE.contains(&self.offset())
// TODO: Replace with `Self::DATA_RANGE.contains(&self.offset())` once it's `const`.
let offset = self.offset();
offset >= Self::DATA_RANGE.start && offset < Self::DATA_RANGE.end
}
}
@@ -82,6 +95,25 @@ impl std::ops::AddAssign<i64> for Real {
}
}
// Real - Offset
impl std::ops::Sub<i64> for Real {
type Output = Self;
fn sub(self, offset: i64) -> Self {
if offset == i64::MIN {
panic!("Unable to offset `i64::MIN`")
}
Self::from(signed_offset(self.into(), -offset))
}
}
// Real += Offset
impl std::ops::SubAssign<i64> for Real {
fn sub_assign(&mut self, offset: i64) {
*self = *self - offset;
}
}
// Real - Real
impl std::ops::Sub<Real> for Real {
type Output = i64;

View File

@@ -36,7 +36,9 @@
stmt_expr_attributes,
unwrap_infallible,
external_doc,
format_args_capture
format_args_capture,
const_fn,
const_panic
)]
// Lints
#![warn(clippy::restriction, clippy::pedantic, clippy::nursery)]
@@ -72,8 +74,8 @@
// In the future, this lint should be removed globally and only enabled for modules which
// actually require the use of it.
#![allow(clippy::module_inception, clippy::module_name_repetitions)]
// Banning arithmetic is too strict for this project
#![allow(clippy::integer_arithmetic)]
// We use integer arithmetic and operations with the correct intent
#![allow(clippy::integer_arithmetic, clippy::integer_division)]
// We prefer using match ergonomic where possible
#![allow(clippy::pattern_type_mismatch)]
// False positives:

View File

@@ -21,7 +21,7 @@ pub use array_split::{array_split, array_split_mut};
/// If the result would not fit into a `i64`, a panic occurs.
#[allow(clippy::as_conversions)] // We check every operation
#[allow(clippy::panic)] // Rust panics on failed arithmetic operations by default
pub fn abs_diff(a: u64, b: u64) -> i64 {
pub const fn abs_diff(a: u64, b: u64) -> i64 {
let diff = if a > b { a - b } else { b - a };
if diff > i64::MAX as u64 {
@@ -42,11 +42,14 @@ pub fn abs_diff(a: u64, b: u64) -> i64 {
#[allow(clippy::as_conversions)] // We check every operation
#[allow(clippy::panic)] // Rust panics on failed arithmetic operations by default
#[allow(clippy::cast_sign_loss)] // We've verify it's positive
pub fn signed_offset(a: u64, b: i64) -> u64 {
pub const fn signed_offset(a: u64, b: i64) -> u64 {
// If `b` is positive, check for overflows. Else check for underflows
if b > 0 {
// Note: Cast is safe, as a positive `i64` fits into a `u64`.
a.checked_add(b as u64).expect("Overflow evaluating `u64 + i64`")
match a.checked_add(b as u64) {
Some(res) => res,
None => panic!("Overflow evaluating `u64 + i64`"),
}
} else {
// Note: On `i64::MIN`, `-b` would overflow
if b == i64::MIN || a < (-b) as u64 {