Skip to content

Commit

Permalink
Add feature to support platforms without atomic CAS (#467)
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e authored Jan 31, 2025
1 parent 71824b0 commit 16fd473
Show file tree
Hide file tree
Showing 7 changed files with 53 additions and 6 deletions.
19 changes: 19 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,25 @@ jobs:
- name: Test
run: cargo test --target ${{ matrix.target }}

# Build for no_std environment.
no-std:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install Rust
run: rustup update stable
- name: Install cargo-hack
uses: taiki-e/install-action@cargo-hack
# thumbv6m-none-eabi supports atomic, but not atomic CAS.
# thumbv7m-none-eabi supports atomic CAS.
- run: rustup target add thumbv6m-none-eabi thumbv7m-none-eabi
# * --optional-deps is needed for serde feature
# * --no-dev-deps is needed to avoid https://github.com/rust-lang/cargo/issues/4866
- run: cargo hack build --target thumbv7m-none-eabi --feature-powerset --skip std,default --optional-deps --no-dev-deps
# A sound way to provide atomic CAS on platforms without native atomic CAS is system-dependent.
# portable-atomic provides major ways via cfgs and accepts user-defined implementations via critical-section feature.
- run: cargo hack build --target thumbv6m-none-eabi --feature-powerset --skip std,default --optional-deps --no-dev-deps --features extra-platforms,extra-platforms/critical-section

# Sanitizers
tsan:
name: tsan
Expand Down
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ std = []

[dependencies]
serde = { version = "1.0.60", optional = true, default-features = false, features = ["alloc"] }
# Use portable-atomic crate to support platforms without atomic CAS.
# See "no_std support" section in readme for more information.
#
# Enable require-cas feature to provide a better error message if the end user forgets to use the cfg or feature.
extra-platforms = { package = "portable-atomic", version = "1.3", optional = true, default-features = false, features = ["require-cas"] }

[dev-dependencies]
serde_test = "1.0"
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,21 @@ Next, add this to your crate:
use bytes::{Bytes, BytesMut, Buf, BufMut};
```

## no_std support

To use `bytes` with no_std environment, disable the (enabled by default) `std` feature.

```toml
[dependencies]
bytes = { version = "1", default-features = false }
```

To use `bytes` with no_std environment without atomic CAS, such as thumbv6m, you also need to enable
the `extra-platforms` feature. See the [documentation for the `portable-atomic`
crate](https://docs.rs/portable-atomic) for more information.

The MSRV when `extra-platforms` feature is enabled depends on the MSRV of `portable-atomic`.

## Serde support

Serde support is optional and disabled by default. To enable use the feature `serde`.
Expand All @@ -36,6 +51,8 @@ Serde support is optional and disabled by default. To enable use the feature `se
bytes = { version = "1", features = ["serde"] }
```

The MSRV when `serde` feature is enabled depends on the MSRV of `serde`.

## Building documentation

When building the `bytes` documentation the `docsrs` option should be used, otherwise
Expand Down
7 changes: 5 additions & 2 deletions ci/test-stable.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ if [[ "${RUST_VERSION}" == "nightly"* ]]; then
cargo check --benches

# Check minimal versions
cargo clean
cargo update -Zminimal-versions
# Remove dev-dependencies from Cargo.toml to prevent the next `cargo update`
# from determining minimal versions based on dev-dependencies.
cargo hack --remove-dev-deps --workspace
# Update Cargo.lock to minimal version dependencies.
cargo update -Z minimal-versions
cargo check --all-features
fi
4 changes: 2 additions & 2 deletions src/buf/chain.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::buf::{IntoIter, UninitSlice};
use crate::{Buf, BufMut, Bytes};
use crate::{Buf, BufMut};

#[cfg(feature = "std")]
use std::io::IoSlice;
Expand Down Expand Up @@ -169,7 +169,7 @@ where
n
}

fn copy_to_bytes(&mut self, len: usize) -> Bytes {
fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
let a_rem = self.a.remaining();
if a_rem >= len {
self.a.copy_to_bytes(len)
Expand Down
4 changes: 2 additions & 2 deletions src/buf/take.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Buf, Bytes};
use crate::Buf;

use core::cmp;

Expand Down Expand Up @@ -148,7 +148,7 @@ impl<T: Buf> Buf for Take<T> {
self.limit -= cnt;
}

fn copy_to_bytes(&mut self, len: usize) -> Bytes {
fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
assert!(len <= self.remaining(), "`len` greater than remaining");

let r = self.inner.copy_to_bytes(len);
Expand Down
3 changes: 3 additions & 0 deletions src/loom.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
#[cfg(not(all(test, loom)))]
pub(crate) mod sync {
pub(crate) mod atomic {
#[cfg(not(feature = "extra-platforms"))]
pub(crate) use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
#[cfg(feature = "extra-platforms")]
pub(crate) use extra_platforms::{AtomicPtr, AtomicUsize, Ordering};

pub(crate) trait AtomicMut<T> {
fn with_mut<F, R>(&mut self, f: F) -> R
Expand Down

0 comments on commit 16fd473

Please sign in to comment.