Skip to content

Commit

Permalink
Require internal macros be explicitly imported
Browse files Browse the repository at this point in the history
  • Loading branch information
jhpratt committed Sep 10, 2023
1 parent 5aa84bd commit 6aa8db5
Show file tree
Hide file tree
Showing 16 changed files with 221 additions and 185 deletions.
4 changes: 4 additions & 0 deletions time/src/date.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ use deranged::RangedI32;
use crate::convert::*;
#[cfg(feature = "formatting")]
use crate::formatting::Formattable;
use crate::internal_macros::{
cascade, const_try, const_try_opt, div_floor, ensure_ranged, expect_opt, impl_add_assign,
impl_sub_assign,
};
#[cfg(feature = "parsing")]
use crate::parsing::Parsable;
use crate::util::{days_in_year, days_in_year_month, is_leap_year, weeks_in_year};
Expand Down
4 changes: 4 additions & 0 deletions time/src/date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ use crate::convert::*;
use crate::date::{MAX_YEAR, MIN_YEAR};
#[cfg(feature = "formatting")]
use crate::formatting::Formattable;
use crate::internal_macros::{
bug, cascade, const_try, const_try_opt, div_floor, ensure_ranged, expect_opt, impl_add_assign,
impl_sub_assign,
};
#[cfg(feature = "parsing")]
use crate::parsing::{Parsable, Parsed};
use crate::{error, util, Date, Duration, Month, Time, UtcOffset, Weekday};
Expand Down
3 changes: 3 additions & 0 deletions time/src/duration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use deranged::RangedI32;

use crate::convert::*;
use crate::error;
use crate::internal_macros::{
const_try_opt, expect_opt, impl_add_assign, impl_div_assign, impl_mul_assign, impl_sub_assign,
};
#[cfg(feature = "std")]
use crate::Instant;

Expand Down
2 changes: 2 additions & 0 deletions time/src/error/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ pub use parse_from_description::ParseFromDescription;
#[cfg(feature = "parsing")]
pub use try_from_parsed::TryFromParsed;

use crate::internal_macros::bug;

/// A unified error type for anything returned by a method in the time crate.
///
/// This can be used when you either don't know or don't care about the exact error returned.
Expand Down
1 change: 1 addition & 0 deletions time/src/error/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use core::fmt;

use crate::error::{self, ParseFromDescription, TryFromParsed};
use crate::internal_macros::bug;

/// An error that occurred at some stage of parsing.
#[allow(variant_size_differences)]
Expand Down
1 change: 1 addition & 0 deletions time/src/format_description/parse/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use alloc::vec::Vec;
use core::iter;

use super::{lexer, unused, Error, Location, Spanned, SpannedValue, Unused};
use crate::internal_macros::bug;

/// One part of a complete format description.
pub(super) enum Item<'a> {
Expand Down
1 change: 1 addition & 0 deletions time/src/format_description/parse/format_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use core::num::NonZeroU16;
use core::str::{self, FromStr};

use super::{ast, unused, Error, Span, Spanned};
use crate::internal_macros::bug;

/// Parse an AST iterator into a sequence of format items.
pub(super) fn parse<'a>(
Expand Down
1 change: 1 addition & 0 deletions time/src/instant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use core::ops::{Add, Sub};
use core::time::Duration as StdDuration;
use std::time::Instant as StdInstant;

use crate::internal_macros::{impl_add_assign, impl_sub_assign};
use crate::Duration;

/// A measurement of a monotonically non-decreasing clock. Opaque and useful only with [`Duration`].
Expand Down
197 changes: 197 additions & 0 deletions time/src/internal_macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
//! Macros for use within the library. They are not publicly available.
/// Helper macro for easily implementing `OpAssign`.
macro_rules! __impl_assign {
($sym:tt $op:ident $fn:ident $target:ty : $($(#[$attr:meta])* $t:ty),+) => {$(
#[allow(unused_qualifications)]
$(#[$attr])*
impl core::ops::$op<$t> for $target {
fn $fn(&mut self, rhs: $t) {
*self = *self $sym rhs;
}
}
)+};
}

/// Implement `AddAssign` for the provided types.
macro_rules! impl_add_assign {
($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
$crate::internal_macros::__impl_assign!(
+ AddAssign add_assign $target : $($(#[$attr])* $t),+
);
};
}

/// Implement `SubAssign` for the provided types.
macro_rules! impl_sub_assign {
($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
$crate::internal_macros::__impl_assign!(
- SubAssign sub_assign $target : $($(#[$attr])* $t),+
);
};
}

/// Implement `MulAssign` for the provided types.
macro_rules! impl_mul_assign {
($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
$crate::internal_macros::__impl_assign!(
* MulAssign mul_assign $target : $($(#[$attr])* $t),+
);
};
}

/// Implement `DivAssign` for the provided types.
macro_rules! impl_div_assign {
($target:ty : $($(#[$attr:meta])* $t:ty),+ $(,)?) => {
$crate::internal_macros::__impl_assign!(
/ DivAssign div_assign $target : $($(#[$attr])* $t),+
);
};
}

/// Division of integers, rounding the resulting value towards negative infinity.
macro_rules! div_floor {
($a:expr, $b:expr) => {{
let _a = $a;
let _b = $b;

let (_quotient, _remainder) = (_a / _b, _a % _b);

if (_remainder > 0 && _b < 0) || (_remainder < 0 && _b > 0) {
_quotient - 1
} else {
_quotient
}
}};
}

/// Cascade an out-of-bounds value.
macro_rules! cascade {
(@ordinal ordinal) => {};
(@year year) => {};

// Cascade an out-of-bounds value from "from" to "to".
($from:ident in $min:literal.. $max:expr => $to:tt) => {
#[allow(unused_comparisons, unused_assignments)]
let min = $min;
let max = $max;
if $from >= max {
$from -= max - min;
$to += 1;
} else if $from < min {
$from += max - min;
$to -= 1;
}
};

// Special case the ordinal-to-year cascade, as it has different behavior.
($ordinal:ident => $year:ident) => {
// We need to actually capture the idents. Without this, macro hygiene causes errors.
cascade!(@ordinal $ordinal);
cascade!(@year $year);
#[allow(unused_assignments)]
if $ordinal > crate::util::days_in_year($year) as i16 {
$ordinal -= crate::util::days_in_year($year) as i16;
$year += 1;
} else if $ordinal < 1 {
$year -= 1;
$ordinal += crate::util::days_in_year($year) as i16;
}
};
}

/// Constructs a ranged integer, returning a `ComponentRange` error if the value is out of range.
macro_rules! ensure_ranged {
($type:ident : $value:ident) => {
match $type::new($value) {
Some(val) => val,
None => {
#[allow(trivial_numeric_casts)]
return Err(crate::error::ComponentRange {
name: stringify!($value),
minimum: $type::MIN.get() as _,
maximum: $type::MAX.get() as _,
value: $value as _,
conditional_range: false,
});
}
}
};

($type:ident : $value:ident $(as $as_type:ident)? * $factor:expr) => {
match ($value $(as $as_type)?).checked_mul($factor) {
Some(val) => match $type::new(val) {
Some(val) => val,
None => {
#[allow(trivial_numeric_casts)]
return Err(crate::error::ComponentRange {
name: stringify!($value),
minimum: $type::MIN.get() as i64 / $factor as i64,
maximum: $type::MAX.get() as i64 / $factor as i64,
value: $value as _,
conditional_range: false,
});
}
},
None => {
return Err(crate::error::ComponentRange {
name: stringify!($value),
minimum: $type::MIN.get() as i64 / $factor as i64,
maximum: $type::MAX.get() as i64 / $factor as i64,
value: $value as _,
conditional_range: false,
});
}
}
};
}

/// Try to unwrap an expression, returning if not possible.
///
/// This is similar to the `?` operator, but does not perform `.into()`. Because of this, it is
/// usable in `const` contexts.
macro_rules! const_try {
($e:expr) => {
match $e {
Ok(value) => value,
Err(error) => return Err(error),
}
};
}

/// Try to unwrap an expression, returning if not possible.
///
/// This is similar to the `?` operator, but is usable in `const` contexts.
macro_rules! const_try_opt {
($e:expr) => {
match $e {
Some(value) => value,
None => return None,
}
};
}

/// Try to unwrap an expression, panicking if not possible.
///
/// This is similar to `$e.expect($message)`, but is usable in `const` contexts.
macro_rules! expect_opt {
($e:expr, $message:literal) => {
match $e {
Some(value) => value,
None => crate::expect_failed($message),
}
};
}

/// `unreachable!()`, but better.
macro_rules! bug {
() => { compile_error!("provide an error message to help fix a possible bug") };
($descr:literal $($rest:tt)?) => {
panic!(concat!("internal error: ", $descr) $($rest)?)
}
}

pub(crate) use {
__impl_assign, bug, cascade, const_try, const_try_opt, div_floor, ensure_ranged, expect_opt,
impl_add_assign, impl_div_assign, impl_mul_assign, impl_sub_assign,
};
Loading

0 comments on commit 6aa8db5

Please sign in to comment.