time header cleanup

This commit is contained in:
auronandace
2026-02-27 18:14:51 +00:00
parent 6fd923adec
commit 1db7abb2d3
5 changed files with 54 additions and 57 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ exclude = ["tests", "dlmalloc-rs"]
[workspace.lints.clippy]
borrow_as_ptr = "warn" # TODO review occurrences
cast_lossless = "warn" # TODO review occurrences
cast_ptr_alignment = "warn" # TODO review occurrences
cast_ptr_alignment = "allow" # TODO review occurrences
missing_safety_doc = "allow" # TODO review occurrences
mut_from_ref = "warn" # TODO review occurrences
precedence = "deny"
+1 -1
View File
@@ -10,7 +10,7 @@ pub mod sys;
pub use self::sys::*;
pub(crate) const UTC: *const c_char = b"UTC\0".as_ptr().cast();
pub(crate) const UTC: *const c_char = c"UTC".as_ptr().cast();
pub(crate) const DAY_NAMES: [&str; 7] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
pub(crate) const MON_NAMES: [&str; 12] = [
+29 -33
View File
@@ -138,7 +138,7 @@ pub struct itimerspec {
#[deprecated]
#[unsafe(no_mangle)]
pub unsafe extern "C" fn asctime(timeptr: *const tm) -> *mut c_char {
unsafe { asctime_r(timeptr, &raw mut ASCTIME as *mut _) }
unsafe { asctime_r(timeptr, (&raw mut ASCTIME).cast()) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9699919799/functions/asctime.html>.
@@ -187,17 +187,16 @@ pub unsafe extern "C" fn asctime_r(tm: *const tm, buf: *mut c_char) -> *mut c_ch
* message for all fields. */
const OUT_OF_RANGE_MESSAGE: &str = "tm member out of range";
assert!(0 <= tm_sec && tm_sec <= 99, "{}", OUT_OF_RANGE_MESSAGE);
assert!(0 <= tm_min && tm_min <= 99, "{}", OUT_OF_RANGE_MESSAGE);
assert!(0 <= tm_hour && tm_hour <= 99, "{}", OUT_OF_RANGE_MESSAGE);
assert!(-99 <= tm_mday && tm_mday <= 999, "{}", OUT_OF_RANGE_MESSAGE);
assert!(0 <= tm_mon && tm_mon <= 11, "{}", OUT_OF_RANGE_MESSAGE);
assert!((0..=99).contains(&tm_sec), "{OUT_OF_RANGE_MESSAGE}");
assert!((0..=99).contains(&tm_min), "{OUT_OF_RANGE_MESSAGE}");
assert!((0..=99).contains(&tm_hour), "{OUT_OF_RANGE_MESSAGE}");
assert!((-99..=999).contains(&tm_mday), "{OUT_OF_RANGE_MESSAGE}");
assert!((0..=11).contains(&tm_mon), "{OUT_OF_RANGE_MESSAGE}");
assert!(
-999 - 1900 <= tm_year && tm_year <= 9999 - 1900,
"{}",
OUT_OF_RANGE_MESSAGE
(-999 - 1900..=9999 - 1900).contains(&tm_year),
"{OUT_OF_RANGE_MESSAGE}"
);
assert!(0 <= tm_wday && tm_wday <= 6, "{}", OUT_OF_RANGE_MESSAGE);
assert!((0..=6).contains(&tm_wday), "{OUT_OF_RANGE_MESSAGE}");
// At this point, we can safely use the values as given.
let write_result = core::fmt::write(
@@ -236,10 +235,7 @@ pub extern "C" fn clock() -> clock_t {
let clocks =
ts.tv_sec * CLOCKS_PER_SEC as i64 + (ts.tv_nsec / (1_000_000_000 / CLOCKS_PER_SEC)) as i64;
match clock_t::try_from(clocks) {
Ok(ok) => ok,
Err(_err) => -1,
}
clock_t::try_from(clocks).unwrap_or(-1)
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/clock_getcpuclockid.html>.
@@ -304,8 +300,8 @@ pub unsafe extern "C" fn ctime(clock: *const time_t) -> *mut c_char {
pub unsafe extern "C" fn ctime_r(clock: *const time_t, buf: *mut c_char) -> *mut c_char {
// Using MaybeUninit<tm> seems to cause a panic during the build process
let mut tm1 = blank_tm();
unsafe { localtime_r(clock, &mut tm1) };
unsafe { asctime_r(&tm1, buf) }
unsafe { localtime_r(clock, &raw mut tm1) };
unsafe { asctime_r(&raw const tm1, buf) }
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/difftime.html>.
@@ -422,7 +418,7 @@ pub unsafe extern "C" fn strftime(
) -> size_t {
let ret = unsafe {
strftime::strftime(
&mut platform::StringWriter(s as *mut u8, maxsize),
&mut platform::StringWriter(s.cast::<u8>(), maxsize),
format,
timeptr,
)
@@ -441,7 +437,7 @@ pub unsafe extern "C" fn strftime(
#[unsafe(no_mangle)]
pub unsafe extern "C" fn time(tloc: *mut time_t) -> time_t {
let mut ts = timespec::default();
if let Ok(_) = Sys::clock_gettime(CLOCK_REALTIME, Out::from_mut(&mut ts)) {}; // TODO what to do if Err?
if Sys::clock_gettime(CLOCK_REALTIME, Out::from_mut(&mut ts)).is_ok() {}; // TODO what to do if Err?
if !tloc.is_null() {
unsafe { *tloc = ts.tv_sec }
};
@@ -462,7 +458,7 @@ pub unsafe extern "C" fn timegm(tm: *mut tm) -> time_t {
(*tm).tm_yday = dt.ordinal0() as _; // day of year starting at 0
(*tm).tm_isdst = 0; // UTC does not use DST
(*tm).tm_gmtoff = 0; // UTC offset is zero
(*tm).tm_zone = UTC_STR.as_ptr() as *const c_char;
(*tm).tm_zone = UTC_STR.as_ptr().cast::<c_char>();
}
dt.timestamp()
@@ -502,7 +498,7 @@ pub unsafe extern "C" fn timer_create(
return Err(Errno(EFAULT)).or_minus_one_errno();
}
let (evp, timerid) = unsafe { (&*evp, Out::nonnull(timerid)) };
Sys::timer_create(clock_id, &evp, timerid)
Sys::timer_create(clock_id, evp, timerid)
.map(|()| 0)
.or_minus_one_errno()
}
@@ -645,10 +641,10 @@ fn get_system_time_zone<'a>() -> Option<&'a str> {
let path = unsafe { CStr::from_ptr(buffer.as_mut_ptr().cast()) };
if let Ok(tz_name) = path.to_str() {
if let Some(stripped) = tz_name.strip_prefix(prefix) {
return Some(stripped);
}
if let Ok(tz_name) = path.to_str()
&& let Some(stripped) = tz_name.strip_prefix(prefix)
{
return Some(stripped);
}
None
@@ -656,11 +652,11 @@ fn get_system_time_zone<'a>() -> Option<&'a str> {
fn get_current_time_zone<'a>() -> &'a str {
// Check the `TZ` environment variable
let tz_env = unsafe { getenv(c"TZ".as_ptr() as _) };
if !tz_env.is_null() {
if let Ok(tz) = unsafe { CStr::from_ptr(tz_env) }.to_str() {
return tz;
}
let tz_env = unsafe { getenv(c"TZ".as_ptr().cast()) };
if !tz_env.is_null()
&& let Ok(tz) = unsafe { CStr::from_ptr(tz_env) }.to_str()
{
return tz;
}
// Fallback to the system's default time zone
@@ -680,7 +676,7 @@ fn time_zone() -> Tz {
#[inline(always)]
fn now() -> NaiveDateTime {
let mut now = timespec::default();
if let Ok(_) = Sys::clock_gettime(CLOCK_REALTIME, Out::from_mut(&mut now)) {}; // TODO what to do if Err?
if Sys::clock_gettime(CLOCK_REALTIME, Out::from_mut(&mut now)).is_ok() {}; // TODO what to do if Err?
NaiveDateTime::from_timestamp(now.tv_sec, now.tv_nsec as _)
}
@@ -702,7 +698,7 @@ fn get_localtime(clock: time_t, t: *mut tm) -> (Option<DateTime<Tz>>, Option<Dat
unsafe fn datetime_to_tm(local_time: &DateTime<Tz>) -> tm {
let tz = local_time.timezone().name();
let tz = tz.strip_prefix("Etc/").or(Some(tz)).unwrap();
let tz = tz.strip_prefix("Etc/").unwrap_or(tz);
let mut t = blank_tm();
// Populate the `tm` structure
@@ -792,9 +788,9 @@ const fn blank_tm() -> tm {
pub(crate) fn timespec_realtime_to_monotonic(abstime: timespec) -> Result<timespec, Errno> {
let mut realtime = timespec::default();
unsafe { clock_gettime(CLOCK_REALTIME, &mut realtime) };
unsafe { clock_gettime(CLOCK_REALTIME, &raw mut realtime) };
let mut monotonic = timespec::default();
unsafe { clock_gettime(CLOCK_MONOTONIC, &mut monotonic) };
unsafe { clock_gettime(CLOCK_MONOTONIC, &raw mut monotonic) };
let Some(delta) = timespec::subtract(abstime, realtime) else {
return Err(Errno(ETIMEDOUT));
};
+7 -10
View File
@@ -35,10 +35,7 @@ unsafe fn langinfo_to_str(item: nl_item) -> &'static str {
if ptr.is_null() {
return "";
}
match unsafe { CStr::from_ptr(ptr) }.to_str() {
Ok(s) => s,
Err(_) => "",
}
unsafe { CStr::from_ptr(ptr) }.to_str().unwrap_or_default()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strftime.html>.
@@ -116,26 +113,26 @@ pub unsafe fn strftime<W: WriteByte>(w: &mut W, format: *const c_char, t: *const
// Abbreviated weekday name: %a
b'a' => {
// `ABDAY_1 + tm_wday` is the correct langinfo ID for abbreviated weekdays
let s = unsafe { langinfo_to_str(ABDAY_1 + (*t).tm_wday as i32) };
let s = unsafe { langinfo_to_str(ABDAY_1 + (*t).tm_wday) };
w!(s);
}
// Full weekday name: %A
b'A' => {
// `DAY_1 + tm_wday` is the correct langinfo ID for full weekdays
let s = unsafe { langinfo_to_str(DAY_1 + (*t).tm_wday as i32) };
let s = unsafe { langinfo_to_str(DAY_1 + (*t).tm_wday) };
w!(s);
}
// Abbreviated month name: %b or %h
b'b' | b'h' => {
let s = unsafe { langinfo_to_str(ABMON_1 + (*t).tm_mon as i32) };
let s = unsafe { langinfo_to_str(ABMON_1 + (*t).tm_mon) };
w!(s);
}
// Full month name: %B
b'B' => {
let s = unsafe { langinfo_to_str(MON_1 + (*t).tm_mon as i32) };
let s = unsafe { langinfo_to_str(MON_1 + (*t).tm_mon) };
w!(s);
}
@@ -204,7 +201,7 @@ pub unsafe fn strftime<W: WriteByte>(w: &mut W, format: *const c_char, t: *const
b'R' => w!(recurse "%H:%M"),
// Seconds since the Epoch: %s => calls mktime() to convert tm to time_t
b's' => w!("{}", unsafe { super::mktime(t as *mut tm) }),
b's' => w!("{}", unsafe { super::mktime(t.cast_mut()) }),
// Seconds (00-60): %S (unchanged)
b'S' => w!("{:02}", unsafe { (*t).tm_sec }),
@@ -285,7 +282,7 @@ pub unsafe fn strftime<W: WriteByte>(w: &mut W, format: *const c_char, t: *const
/// ## Source
/// https://en.wikipedia.org/wiki/ISO_week_date
fn weeks_per_year(year: c_int) -> c_int {
let year = year as f64;
let year = f64::from(year);
let p_y = (year + (year / 4.) - (year / 100.) + (year / 400.)) as c_int % 7;
if p_y == 4 { 53 } else { 52 }
}
+16 -12
View File
@@ -48,13 +48,13 @@ pub unsafe extern "C" fn strptime(
tm: *mut tm,
) -> *mut c_char {
// Validate inputs
let buf_ptr = if let Some(ptr) = NonNull::new(buf as *const c_void as *mut c_void) {
let buf_ptr = if let Some(ptr) = NonNull::new(buf.cast::<c_void>().cast_mut()) {
ptr
} else {
return ptr::null_mut();
};
//
let fmt_ptr = if let Some(ptr) = NonNull::new(format as *const c_void as *mut c_void) {
let fmt_ptr = if let Some(ptr) = NonNull::new(format.cast::<c_void>().cast_mut()) {
ptr
} else {
return ptr::null_mut();
@@ -230,7 +230,7 @@ pub unsafe extern "C" fn strptime(
Some(v) => v,
None => return ptr::null_mut(),
};
if val < 1 || val > 12 {
if !(1..=12).contains(&val) {
return ptr::null_mut();
}
unsafe {
@@ -364,7 +364,7 @@ pub unsafe extern "C" fn strptime(
Some(v) => v,
None => return ptr::null_mut(),
};
if val < 1 || val > 366 {
if !(1..=366).contains(&val) {
return ptr::null_mut();
}
// store in tm_yday
@@ -432,7 +432,7 @@ pub unsafe extern "C" fn strptime(
// If we got here, parsing was successful. Return pointer to the
// next unparsed character in `buf`.
let ret_ptr = unsafe { buf.add(index_in_input) };
ret_ptr as *mut c_char
ret_ptr.cast_mut()
}
// Helper / Parsing Logic
@@ -444,16 +444,18 @@ pub unsafe extern "C" fn strptime(
/// (e.g., `%Y` can have more than 4 digits, but also might parse "2023" or "12345").
fn parse_int(input: &str, width: usize, allow_variable: bool) -> Option<(i32, usize)> {
let mut val = 0i32;
let mut chars = input.chars();
let chars = input.chars();
let mut count = 0;
while let Some(c) = chars.next() {
for c in chars {
if !c.is_ascii_digit() {
break;
}
// Check for integer overflow
val = val.checked_mul(10)?.checked_add((c as u8 - b'0') as i32)?;
val = val
.checked_mul(10)?
.checked_add(i32::from(c as u8 - b'0'))?;
count += 1;
if count == width && !allow_variable {
@@ -484,13 +486,14 @@ fn parse_am_pm(s: &str) -> Option<(bool, usize)> {
/// Parse a weekday name from `s`.
/// - if `abbrev == true`, match short forms: "Mont".."Sun"
/// - otherwise, match "Monday".."Sunday"
///
/// Return (weekday_index, length_consumed).
fn parse_weekday(s: &str, abbrev: bool) -> Option<(usize, usize)> {
let list = if abbrev { &SHORT_DAYS } else { &LONG_DAYS };
for (i, name) in list.iter().enumerate() {
if s.len() >= name.len()
&& s.get(0..name.len())
.map_or(false, |sub| sub.eq_ignore_ascii_case(name))
.is_some_and(|sub| sub.eq_ignore_ascii_case(name))
{
return Some((i, name.len()));
}
@@ -501,13 +504,14 @@ fn parse_weekday(s: &str, abbrev: bool) -> Option<(usize, usize)> {
/// Parse a month name from `s`.
/// - If `abbrev == true`, match short forms: "Jan".."Dec"
/// - Otherwise, match "January".."December"
///
/// Return (month_index, length_consumed).
fn parse_month(s: &str, abbrev: bool) -> Option<(usize, usize)> {
let list = if abbrev { &SHORT_MONTHS } else { &LONG_MONTHS };
for (i, name) in list.iter().enumerate() {
if s.len() >= name.len()
&& s.get(0..name.len())
.map_or(false, |sub| sub.eq_ignore_ascii_case(name))
.is_some_and(|sub| sub.eq_ignore_ascii_case(name))
{
return Some((i, name.len()));
}
@@ -536,8 +540,8 @@ unsafe fn apply_subformat(input: &str, subfmt: &str, tm: *mut tm) -> Option<usiz
let consumed_ptr = unsafe {
strptime(
tmpbuf.as_ptr() as *const c_char,
tmpfmt.as_ptr() as *const c_char,
tmpbuf.as_ptr().cast::<c_char>(),
tmpfmt.as_ptr().cast::<c_char>(),
tm,
)
};