Skip to content

Commit 16fd473

Browse files
authored
Add feature to support platforms without atomic CAS (#467)
1 parent 71824b0 commit 16fd473

File tree

7 files changed

+53
-6
lines changed

7 files changed

+53
-6
lines changed

.github/workflows/ci.yml

+19
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,25 @@ jobs:
127127
- name: Test
128128
run: cargo test --target ${{ matrix.target }}
129129

130+
# Build for no_std environment.
131+
no-std:
132+
runs-on: ubuntu-latest
133+
steps:
134+
- uses: actions/checkout@v4
135+
- name: Install Rust
136+
run: rustup update stable
137+
- name: Install cargo-hack
138+
uses: taiki-e/install-action@cargo-hack
139+
# thumbv6m-none-eabi supports atomic, but not atomic CAS.
140+
# thumbv7m-none-eabi supports atomic CAS.
141+
- run: rustup target add thumbv6m-none-eabi thumbv7m-none-eabi
142+
# * --optional-deps is needed for serde feature
143+
# * --no-dev-deps is needed to avoid https://github.com/rust-lang/cargo/issues/4866
144+
- run: cargo hack build --target thumbv7m-none-eabi --feature-powerset --skip std,default --optional-deps --no-dev-deps
145+
# A sound way to provide atomic CAS on platforms without native atomic CAS is system-dependent.
146+
# portable-atomic provides major ways via cfgs and accepts user-defined implementations via critical-section feature.
147+
- 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
148+
130149
# Sanitizers
131150
tsan:
132151
name: tsan

Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ std = []
2424

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

2833
[dev-dependencies]
2934
serde_test = "1.0"

README.md

+17
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ Next, add this to your crate:
2727
use bytes::{Bytes, BytesMut, Buf, BufMut};
2828
```
2929

30+
## no_std support
31+
32+
To use `bytes` with no_std environment, disable the (enabled by default) `std` feature.
33+
34+
```toml
35+
[dependencies]
36+
bytes = { version = "1", default-features = false }
37+
```
38+
39+
To use `bytes` with no_std environment without atomic CAS, such as thumbv6m, you also need to enable
40+
the `extra-platforms` feature. See the [documentation for the `portable-atomic`
41+
crate](https://docs.rs/portable-atomic) for more information.
42+
43+
The MSRV when `extra-platforms` feature is enabled depends on the MSRV of `portable-atomic`.
44+
3045
## Serde support
3146

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

54+
The MSRV when `serde` feature is enabled depends on the MSRV of `serde`.
55+
3956
## Building documentation
4057

4158
When building the `bytes` documentation the `docsrs` option should be used, otherwise

ci/test-stable.sh

+5-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,10 @@ if [[ "${RUST_VERSION}" == "nightly"* ]]; then
1616
cargo check --benches
1717

1818
# Check minimal versions
19-
cargo clean
20-
cargo update -Zminimal-versions
19+
# Remove dev-dependencies from Cargo.toml to prevent the next `cargo update`
20+
# from determining minimal versions based on dev-dependencies.
21+
cargo hack --remove-dev-deps --workspace
22+
# Update Cargo.lock to minimal version dependencies.
23+
cargo update -Z minimal-versions
2124
cargo check --all-features
2225
fi

src/buf/chain.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::buf::{IntoIter, UninitSlice};
2-
use crate::{Buf, BufMut, Bytes};
2+
use crate::{Buf, BufMut};
33

44
#[cfg(feature = "std")]
55
use std::io::IoSlice;
@@ -169,7 +169,7 @@ where
169169
n
170170
}
171171

172-
fn copy_to_bytes(&mut self, len: usize) -> Bytes {
172+
fn copy_to_bytes(&mut self, len: usize) -> crate::Bytes {
173173
let a_rem = self.a.remaining();
174174
if a_rem >= len {
175175
self.a.copy_to_bytes(len)

src/buf/take.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{Buf, Bytes};
1+
use crate::Buf;
22

33
use core::cmp;
44

@@ -148,7 +148,7 @@ impl<T: Buf> Buf for Take<T> {
148148
self.limit -= cnt;
149149
}
150150

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

154154
let r = self.inner.copy_to_bytes(len);

src/loom.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
#[cfg(not(all(test, loom)))]
22
pub(crate) mod sync {
33
pub(crate) mod atomic {
4+
#[cfg(not(feature = "extra-platforms"))]
45
pub(crate) use core::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
6+
#[cfg(feature = "extra-platforms")]
7+
pub(crate) use extra_platforms::{AtomicPtr, AtomicUsize, Ordering};
58

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

0 commit comments

Comments
 (0)