Skip to content

Commit 6ae82d5

Browse files
authored
Merge pull request #541 from rilipco/impl-alloc-interop
Add some conversion options for alloc vecs
2 parents 06a96b7 + 5dcb316 commit 6ae82d5

File tree

5 files changed

+84
-2
lines changed

5 files changed

+84
-2
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ jobs:
165165
run: |
166166
cargo check --target=${{ matrix.target }}
167167
cargo check --target=${{ matrix.target }} --features="portable-atomic-critical-section"
168-
cargo check --target=${{ matrix.target }} --features="ufmt serde defmt mpmc_large"
168+
cargo check --target=${{ matrix.target }} --features="ufmt serde defmt mpmc_large alloc"
169169
170170
doc:
171171
name: doc
@@ -208,7 +208,7 @@ jobs:
208208

209209
- name: cargo rustdoc
210210
env: {"RUSTDOCFLAGS": "-D warnings --cfg docsrs"}
211-
run: cargo rustdoc --target=${{ matrix.target }} --features="ufmt serde defmt mpmc_large portable-atomic-critical-section"
211+
run: cargo rustdoc --target=${{ matrix.target }} --features="ufmt serde defmt mpmc_large portable-atomic-critical-section alloc"
212212

213213
# Run cpass tests
214214
testcpass:

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
4242
- Added `Deque::{swap, swap_unchecked, swap_remove_front, swap_remove_back}`.
4343
- Make `String::from_utf8_unchecked` const.
4444
- Implemented `PartialEq` and `Eq` for `Deque`.
45+
- Added `alloc` feature to enable `alloc`-Vec interoperability.
46+
- Added `TryFrom<alloc::vec::Vec>` impl for `Vec`.
47+
- Added `TryFrom<Vec>` impl for `alloc::vec::Vec`.
4548
- Added `truncate` to `IndexMap`.
4649
- Added `get_index` and `get_index_mut` to `IndexMap`.
4750
- Added `String::uDisplay`.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ defmt = ["dep:defmt"]
4141
# Enable larger MPMC sizes.
4242
mpmc_large = []
4343

44+
# Implement some alloc Vec interoperability
45+
alloc = []
46+
4447
nightly = []
4548

4649
[dependencies]
@@ -67,6 +70,7 @@ features = [
6770
"defmt",
6871
"mpmc_large",
6972
"portable-atomic-critical-section",
73+
"alloc",
7074
]
7175
# for the pool module
7276
targets = ["i686-unknown-linux-gnu"]

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,9 @@
153153
clippy::if_not_else
154154
)]
155155

156+
#[cfg(feature = "alloc")]
157+
extern crate alloc;
158+
156159
pub use binary_heap::BinaryHeap;
157160
pub use deque::Deque;
158161
pub use histbuf::{HistoryBuffer, OldestOrdered};

src/vec/mod.rs

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,53 @@ impl<T, S: VecStorage<T> + ?Sized> Drop for VecInner<T, S> {
12771277
}
12781278
}
12791279

1280+
#[cfg(feature = "alloc")]
1281+
/// Converts the given `alloc::vec::Vec<T>` into a `Vec<T, N>`.
1282+
impl<T, const N: usize> TryFrom<alloc::vec::Vec<T>> for Vec<T, N> {
1283+
type Error = CapacityError;
1284+
1285+
/// Converts the given `alloc::vec::Vec<T>` into a `Vec<T, N>`.
1286+
///
1287+
/// # Errors
1288+
///
1289+
/// Returns `Err` if the length of the `alloc::vec::Vec<T>` is greater than `N`.
1290+
fn try_from(alloc_vec: alloc::vec::Vec<T>) -> Result<Self, Self::Error> {
1291+
let mut vec = Vec::new();
1292+
1293+
for e in alloc_vec {
1294+
// Push each element individually to allow handling capacity errors.
1295+
vec.push(e).map_err(|_| CapacityError {})?;
1296+
}
1297+
1298+
Ok(vec)
1299+
}
1300+
}
1301+
1302+
#[cfg(feature = "alloc")]
1303+
/// Converts the given `Vec<T, N>` into an `alloc::vec::Vec<T>`.
1304+
impl<T, const N: usize> TryFrom<Vec<T, N>> for alloc::vec::Vec<T> {
1305+
type Error = alloc::collections::TryReserveError;
1306+
1307+
/// Converts the given `Vec<T, N>` into an `alloc::vec::Vec<T>`.
1308+
///
1309+
/// # Errors
1310+
///
1311+
/// Returns `Err` if the `alloc::vec::Vec` fails to allocate memory.
1312+
fn try_from(vec: Vec<T, N>) -> Result<Self, Self::Error> {
1313+
let mut alloc_vec = alloc::vec::Vec::new();
1314+
1315+
// Allocate enough space for the elements, return an error if the
1316+
// allocation fails.
1317+
alloc_vec.try_reserve_exact(vec.len())?;
1318+
1319+
// Transfer the elements, since we reserved enough space above, this
1320+
// should not fail due to OOM.
1321+
alloc_vec.extend(vec);
1322+
1323+
Ok(alloc_vec)
1324+
}
1325+
}
1326+
12801327
impl<'a, T: Clone, const N: usize> TryFrom<&'a [T]> for Vec<T, N> {
12811328
type Error = CapacityError;
12821329

@@ -2099,6 +2146,31 @@ mod tests {
20992146
assert!(v.spare_capacity_mut().is_empty());
21002147
}
21012148

2149+
#[test]
2150+
#[cfg(feature = "alloc")]
2151+
fn heapless_to_alloc() {
2152+
let mut hv: Vec<u8, 4> = Vec::new();
2153+
hv.push(0).unwrap();
2154+
hv.push(1).unwrap();
2155+
2156+
let av: alloc::vec::Vec<u8> = hv.clone().try_into().unwrap();
2157+
assert_eq!(av.as_slice(), hv.as_slice());
2158+
}
2159+
2160+
#[test]
2161+
#[cfg(feature = "alloc")]
2162+
fn alloc_to_heapless() {
2163+
let mut av: alloc::vec::Vec<u8> = alloc::vec::Vec::new();
2164+
av.push(0);
2165+
av.push(1);
2166+
2167+
let hv: Vec<u8, 2> = av.clone().try_into().unwrap();
2168+
assert_eq!(hv.as_slice(), av.as_slice());
2169+
2170+
let _: crate::CapacityError =
2171+
<alloc::vec::Vec<u8> as TryInto<Vec<u8, 1>>>::try_into(av.clone()).unwrap_err();
2172+
}
2173+
21022174
fn _test_variance<'a: 'b, 'b>(x: Vec<&'a (), 42>) -> Vec<&'b (), 42> {
21032175
x
21042176
}

0 commit comments

Comments
 (0)