summaryrefslogtreecommitdiffstats
path: root/third_party/rust/time/src/util.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /third_party/rust/time/src/util.rs
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/time/src/util.rs')
-rw-r--r--third_party/rust/time/src/util.rs99
1 files changed, 99 insertions, 0 deletions
diff --git a/third_party/rust/time/src/util.rs b/third_party/rust/time/src/util.rs
new file mode 100644
index 0000000000..857f5f20b0
--- /dev/null
+++ b/third_party/rust/time/src/util.rs
@@ -0,0 +1,99 @@
+//! Utility functions.
+
+pub use time_core::util::{days_in_year, is_leap_year, weeks_in_year};
+
+use crate::Month;
+
+/// Whether to adjust the date, and in which direction. Useful when implementing arithmetic.
+pub(crate) enum DateAdjustment {
+ /// The previous day should be used.
+ Previous,
+ /// The next day should be used.
+ Next,
+ /// The date should be used as-is.
+ None,
+}
+
+/// Get the number of days in the month of a given year.
+///
+/// ```rust
+/// # use time::{Month, util};
+/// assert_eq!(util::days_in_year_month(2020, Month::February), 29);
+/// ```
+pub const fn days_in_year_month(year: i32, month: Month) -> u8 {
+ use Month::*;
+ match month {
+ January | March | May | July | August | October | December => 31,
+ April | June | September | November => 30,
+ February if is_leap_year(year) => 29,
+ February => 28,
+ }
+}
+
+#[cfg(feature = "local-offset")]
+/// Utility functions relating to the local UTC offset.
+pub mod local_offset {
+ use core::sync::atomic::{AtomicBool, Ordering};
+
+ /// Whether obtaining the local UTC offset is required to be sound.
+ static LOCAL_OFFSET_IS_SOUND: AtomicBool = AtomicBool::new(true);
+
+ /// The soundness of obtaining the local UTC offset.
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
+ pub enum Soundness {
+ /// Obtaining the local UTC offset is required to be sound. Undefined behavior will never
+ /// occur. This is the default.
+ Sound,
+ /// Obtaining the local UTC offset is allowed to invoke undefined behavior. **Setting this
+ /// value is strongly discouraged.** To do so, you must comply with the safety requirements
+ /// of [`time::local_offset::set_soundness`](set_soundness).
+ Unsound,
+ }
+
+ /// Set whether obtaining the local UTC offset is allowed to invoke undefined behavior. **Use of
+ /// this function is heavily discouraged.**
+ ///
+ /// # Safety
+ ///
+ /// If this method is called with [`Soundness::Sound`], the call is always sound. If this method
+ /// is called with [`Soundness::Unsound`], the following conditions apply.
+ ///
+ /// - If the operating system provides a thread-safe environment, the call is sound.
+ /// - If the process is single-threaded, the call is sound.
+ /// - If the process is multi-threaded, no other thread may mutate the environment in any way at
+ /// the same time a call to a method that obtains the local UTC offset. This includes adding,
+ /// removing, or modifying an environment variable.
+ ///
+ /// The first two conditions are automatically checked by `time`, such that you do not need to
+ /// declare your code unsound. Currently, the only known operating systems that does _not_
+ /// provide a thread-safe environment are some Unix-like OS's. All other operating systems
+ /// should succeed when attempting to obtain the local UTC offset.
+ ///
+ /// Note that you must not only verify this safety condition for your code, but for **all** code
+ /// that will be included in the final binary. Notably, it applies to both direct and transitive
+ /// dependencies and to both Rust and non-Rust code. **For this reason it is not possible to
+ /// soundly pass [`Soundness::Unsound`] to this method if you are writing a library that may
+ /// used by others.**
+ ///
+ /// If using this method is absolutely necessary, it is recommended to keep the time between
+ /// setting the soundness to [`Soundness::Unsound`] and setting it back to [`Soundness::Sound`]
+ /// as short as possible.
+ ///
+ /// The following methods currently obtain the local UTC offset:
+ ///
+ /// - [`OffsetDateTime::now_local`](crate::OffsetDateTime::now_local)
+ /// - [`UtcOffset::local_offset_at`](crate::UtcOffset::local_offset_at)
+ /// - [`UtcOffset::current_local_offset`](crate::UtcOffset::current_local_offset)
+ pub unsafe fn set_soundness(soundness: Soundness) {
+ LOCAL_OFFSET_IS_SOUND.store(soundness == Soundness::Sound, Ordering::SeqCst);
+ }
+
+ /// Obtains the soundness of obtaining the local UTC offset. If it is [`Soundness::Unsound`],
+ /// it is allowed to invoke undefined behavior when obtaining the local UTC offset.
+ pub fn get_soundness() -> Soundness {
+ match LOCAL_OFFSET_IS_SOUND.load(Ordering::SeqCst) {
+ false => Soundness::Unsound,
+ true => Soundness::Sound,
+ }
+ }
+}