From 4782af6e74826b9052dac5351199bc12858ebbf3 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 27 Dec 2024 19:55:02 +0100 Subject: [PATCH] no_std: support platforms that do not have native atomics Fixes #162, Closes #177 --- .github/workflows/ci.yml | 20 ++++++++++++++++++++ CHANGELOG.md | 2 ++ Cargo.toml | 12 +++++++++++- src/error.rs | 4 +++- src/lib.rs | 12 ++++++++++++ src/tz/db/mod.rs | 4 ++-- src/tz/mod.rs | 6 ++---- src/tz/system/mod.rs | 3 ++- src/tz/zic.rs | 2 +- 9 files changed, 55 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e7afe7e1..21018ec2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -155,6 +155,26 @@ jobs: - run: cross test --verbose --target ${{ matrix.target }} --all - run: cross test --verbose --target ${{ matrix.target }} -p jiff-cli + # This is meant to test that Jiff's use of `Arc` from `portable-atomic-util` + # on targets that don't have `alloc::sync::Arc` in `std` works. + # + # Normally I'd do this with Cross, but I guess `riscv32imc-unknown-none-elf` + # isn't in Cross, and that's the target that the end user wanting this + # cares about[1,2]. + # + # [1]: https://github.com/BurntSushi/jiff/issues/162 + # [2]: https://github.com/BurntSushi/jiff/pull/177 + riscv32imc-unknown-none-elf: + runs-on: ubuntu-latest + steps: + - uses: dtolnay/rust-toolchain@master + with: + targets: riscv32imc-unknown-none-elf + - uses: actions/checkout@v4 + - name: Test the build only + run: | + cargo build --target riscv32imc-unknown-none-elf --features alloc --no-default-features --features portable-atomic/critical-section + # Test the wasm32-wasip1 target via wasmtime. wasm32-wasip1: runs-on: ubuntu-latest diff --git a/CHANGELOG.md b/CHANGELOG.md index 03fb079d..bbfa34be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ TBD. Enhancements: +* [#162](https://github.com/BurntSushi/jiff/issues/162): +Support platforms that do not have atomics in `std`. * [#169](https://github.com/BurntSushi/jiff/issues/169): Add `TimeZone::to_fixed_offset` for accessing an invariant offset if possible. diff --git a/Cargo.toml b/Cargo.toml index 285a6c6a..01050f6f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,7 @@ members = [ [features] default = ["std", "tz-system", "tzdb-bundle-platform", "tzdb-zoneinfo"] std = ["alloc", "serde?/std"] -alloc = ["serde?/alloc"] +alloc = ["serde?/alloc", "portable-atomic-util/alloc"] serde = ["dep:serde"] logging = ["dep:log"] @@ -96,6 +96,16 @@ optional = true js-sys = { version = "0.3.50", optional = true } wasm-bindgen = { version = "0.2.70", optional = true } +# For targets that have no atomics in `std`, we add a dependency on +# `portable-atomic-util` for its Arc implementation. +# +# Note that for this to work, you may need to enable a `portable-atomic` +# feature like `portable-atomic/unsafe-assume-single-core` or +# `portable-atomic/critical-section`. +[target.'cfg(not(target_has_atomic = "ptr"))'.dependencies] +portable-atomic = { version = "1.10.0", default-features = false } +portable-atomic-util = { version = "0.2.4", default-features = false } + [dev-dependencies] anyhow = "1.0.81" chrono = { version = "0.4.38", features = ["serde"] } diff --git a/src/error.rs b/src/error.rs index 892b3e30..f34c4f6c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,6 @@ -use alloc::{boxed::Box, string::String, sync::Arc}; +use alloc::{boxed::Box, string::String}; + +use crate::sync::Arc; /// Creates a new ad hoc error with no causal chain. /// diff --git a/src/lib.rs b/src/lib.rs index dc4b030f..8954d58a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -743,6 +743,18 @@ pub mod _documentation { pub mod changelog {} } +/// This module re-exports `Arc`. +/// +/// That is, it provides some indirection for the case when `alloc::sync::Arc` +/// is unavailable. +mod sync { + #[cfg(not(target_has_atomic = "ptr"))] + pub use portable_atomic_util::Arc; + + #[cfg(target_has_atomic = "ptr")] + pub use alloc::sync::Arc; +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/tz/db/mod.rs b/src/tz/db/mod.rs index be904cd7..dad61e0c 100644 --- a/src/tz/db/mod.rs +++ b/src/tz/db/mod.rs @@ -1,6 +1,6 @@ -use alloc::{string::String, sync::Arc, vec::Vec}; +use alloc::{string::String, vec::Vec}; -use crate::{error::Error, tz::TimeZone}; +use crate::{error::Error, sync::Arc, tz::TimeZone}; use self::{bundled::BundledZoneInfo, zoneinfo::ZoneInfo}; diff --git a/src/tz/mod.rs b/src/tz/mod.rs index 1931ef43..9f9764c7 100644 --- a/src/tz/mod.rs +++ b/src/tz/mod.rs @@ -83,14 +83,12 @@ TO get the system's default time zone, use [`TimeZone::system`]. [`GetDynamicTimeZoneInformation`]: https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-getdynamictimezoneinformation */ -use alloc::{ - string::{String, ToString}, - sync::Arc, -}; +use alloc::string::{String, ToString}; use crate::{ civil::DateTime, error::{err, Error, ErrorContext}, + sync::Arc, util::array_str::ArrayStr, Timestamp, Zoned, }; diff --git a/src/tz/system/mod.rs b/src/tz/system/mod.rs index 96f15dd6..647670cf 100644 --- a/src/tz/system/mod.rs +++ b/src/tz/system/mod.rs @@ -1,9 +1,10 @@ use std::{sync::RwLock, time::Duration}; -use alloc::{string::ToString, sync::Arc}; +use alloc::string::ToString; use crate::{ error::{err, Error, ErrorContext}, + sync::Arc, tz::{posix::PosixTz, TimeZone, TimeZoneDatabase}, util::cache::Expiration, }; diff --git a/src/tz/zic.rs b/src/tz/zic.rs index 1fb03843..fbd7e716 100644 --- a/src/tz/zic.rs +++ b/src/tz/zic.rs @@ -105,7 +105,6 @@ use core::{ops::RangeInclusive, str::FromStr}; use alloc::{ collections::BTreeMap, string::{String, ToString}, - sync::Arc, vec, vec::Vec, }; @@ -114,6 +113,7 @@ use crate::{ civil::{Date, DateTime, Time, Weekday}, error::{err, Error, ErrorContext}, span::{Span, ToSpan}, + sync::Arc, timestamp::Timestamp, tz::{Dst, Offset}, util::{