Skip to content

Commit 784001f

Browse files
authored
Move try_collect into its own trait (#8)
1 parent 8fe3741 commit 784001f

File tree

6 files changed

+86
-36
lines changed

6 files changed

+86
-36
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "fallible_vec"
33
description = "Fallible allocation functions for the Rust standard library's `Vec` type."
4-
version = "0.1.0"
4+
version = "0.2.0"
55
edition = "2021"
66
license-file = "LICENSE"
77
repository = "https://github.com/microsoft/rust_fallible_vec"

build.ps1

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
Set-StrictMode -Version Latest
22
$ErrorActionPreference = 'Stop'
33

4+
function Invoke-CheckExitCode([scriptblock]$ScriptBlock) {
5+
& $ScriptBlock
6+
if ($LASTEXITCODE -ne 0) {
7+
exit $LASTEXITCODE
8+
}
9+
}
10+
411
function Invoke-WithEnvironment([System.Collections.IDictionary] $Environment, [scriptblock]$ScriptBlock) {
512
try {
613
# Set the environment.
@@ -29,18 +36,18 @@ Invoke-WithEnvironment `
2936
#
3037
# Run tests
3138
#
32-
cargo test --locked
39+
Invoke-CheckExitCode { cargo test --locked }
3340

3441
#
3542
# Lint and check formatting.
3643
#
37-
cargo clippy --locked -- -D warnings
38-
cargo fmt --check
44+
Invoke-CheckExitCode { cargo clippy --locked -- -D warnings }
45+
Invoke-CheckExitCode { cargo fmt --check }
3946

4047
#
4148
# Check docs
4249
#
43-
cargo doc --locked
50+
Invoke-CheckExitCode { cargo doc --locked }
4451

4552
#
4653
# Verify that we can build with #[cfg(no_global_oom_handling)] enabled.
@@ -63,10 +70,12 @@ Invoke-WithEnvironment `
6370
# in the standard library.
6471
'env:RUSTFLAGS' = '--cfg no_global_oom_handling';
6572
} `
66-
-ScriptBlock { cargo build --locked -Z build-std=core,alloc --target $target }
73+
-ScriptBlock {
74+
Invoke-CheckExitCode { cargo build --locked -Z build-std=core,alloc --target $target }
75+
}
6776
}
6877

6978
# Run tests under miri
70-
rustup toolchain install nightly --component miri
71-
cargo +nightly miri setup
72-
cargo +nightly miri test
79+
Invoke-CheckExitCode { rustup toolchain install nightly --component miri }
80+
Invoke-CheckExitCode { cargo +nightly miri setup }
81+
Invoke-CheckExitCode { cargo +nightly miri test }

src/collect.rs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
use crate::FallibleVec;
2+
use alloc::{collections::TryReserveError, vec::Vec};
3+
use core::alloc::Allocator;
4+
5+
/// Fallible allocations equivalents for [`Iterator::collect`].
6+
pub trait TryCollect<T> {
7+
/// Attempts to collect items from an iterator into a vector with the provided
8+
/// allocator.
9+
///
10+
/// # Examples
11+
///
12+
/// ```
13+
/// # #![feature(allocator_api)]
14+
/// # #[macro_use] extern crate fallible_vec;
15+
/// use fallible_vec::*;
16+
/// use std::alloc::System;
17+
///
18+
/// let doubled = [1, 2, 3, 4, 5].map(|i| i * 2);
19+
/// let vec = doubled.try_collect_in(System)?;
20+
/// assert_eq!(vec, [2, 4, 6, 8, 10]);
21+
/// # Ok::<(), std::collections::TryReserveError>(())
22+
/// ```
23+
fn try_collect_in<A: Allocator>(self, alloc: A) -> Result<Vec<T, A>, TryReserveError>;
24+
25+
/// Attempts to collect items from an iterator into a vector.
26+
///
27+
/// # Examples
28+
///
29+
/// ```
30+
/// # #![feature(allocator_api)]
31+
/// # #[macro_use] extern crate fallible_vec;
32+
/// use fallible_vec::*;
33+
///
34+
/// let doubled = [1, 2, 3, 4, 5].map(|i| i * 2);
35+
/// let vec = doubled.try_collect()?;
36+
/// assert_eq!(vec, [2, 4, 6, 8, 10]);
37+
/// # Ok::<(), std::collections::TryReserveError>(())
38+
/// ```
39+
fn try_collect(self) -> Result<Vec<T>, TryReserveError>;
40+
}
41+
42+
impl<T, I> TryCollect<T> for I
43+
where
44+
I: IntoIterator<Item = T>,
45+
{
46+
fn try_collect_in<A: Allocator>(self, alloc: A) -> Result<Vec<T, A>, TryReserveError> {
47+
let mut vec = Vec::new_in(alloc);
48+
vec.try_extend(self.into_iter())?;
49+
Ok(vec)
50+
}
51+
52+
fn try_collect(self) -> Result<Vec<T>, TryReserveError> {
53+
let mut vec = Vec::new();
54+
vec.try_extend(self.into_iter())?;
55+
Ok(vec)
56+
}
57+
}

src/lib.rs

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -46,20 +46,22 @@
4646
#![deny(unsafe_op_in_unsafe_fn)]
4747

4848
extern crate alloc;
49+
mod collect;
4950
mod set_len_on_drop;
5051

52+
use alloc::{
53+
collections::{TryReserveError, TryReserveErrorKind},
54+
vec::Vec,
55+
};
5156
use core::{
5257
alloc::Allocator,
5358
ops::{Range, RangeBounds},
5459
slice,
5560
};
56-
57-
use alloc::{
58-
collections::{TryReserveError, TryReserveErrorKind},
59-
vec::Vec,
60-
};
6161
use set_len_on_drop::SetLenOnDrop;
6262

63+
pub use collect::TryCollect;
64+
6365
// These are defined so that the try_vec! and try_vec_in! macros can refer to
6466
// these types in a consistent way: even if the consuming crate doesn't use
6567
// `no_std` and `extern crate alloc`.
@@ -68,7 +70,7 @@ pub mod alloc_usings {
6870
pub use alloc::{alloc::Layout, boxed::Box, collections::TryReserveError, vec::Vec};
6971
}
7072

71-
/// Methods available for all `Vec` instantiations.
73+
/// Fallible allocation methods for [`Vec`].
7274
pub trait FallibleVec<T, A: Allocator>: Sized {
7375
/// Extends the `Vec` using the items from the given iterator.
7476
///
@@ -430,7 +432,7 @@ impl<T, A: Allocator> FallibleVec<T, A> for Vec<T, A> {
430432
}
431433

432434
// Gather up the remainder and copy those as well.
433-
let remainder = try_collect_in(replace_with, alloc)?;
435+
let remainder = replace_with.try_collect_in(alloc)?;
434436
if !remainder.is_empty() {
435437
move_tail(self, index, remainder.len())?;
436438
// Don't need to use `SetLenOnDrop` here since we're enumerating
@@ -670,24 +672,6 @@ pub fn try_with_capacity<T>(size: usize) -> Result<Vec<T>, TryReserveError> {
670672
Ok(vec)
671673
}
672674

673-
/// Attempts to collect items from an iterator into a vector with the provided
674-
/// allocator.
675-
pub fn try_collect_in<T, A: Allocator>(
676-
iter: impl Iterator<Item = T>,
677-
alloc: A,
678-
) -> Result<Vec<T, A>, TryReserveError> {
679-
let mut vec = Vec::new_in(alloc);
680-
vec.try_extend(iter)?;
681-
Ok(vec)
682-
}
683-
684-
/// Attempts to collect items from an iterator into a vector.
685-
pub fn try_collect<T>(iter: impl Iterator<Item = T>) -> Result<Vec<T>, TryReserveError> {
686-
let mut vec = Vec::new();
687-
vec.try_extend(iter)?;
688-
Ok(vec)
689-
}
690-
691675
#[doc(hidden)]
692676
pub fn try_new_repeat_item_in<T: Clone, A: Allocator>(
693677
item: T,

src/tests.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ fn test_collect_after_iterator_clone() {
142142
let v = try_vec_in![0; 5 => Global].unwrap();
143143
let mut i = v.into_iter().map(|i| i + 1).peekable();
144144
i.peek();
145-
let v = try_collect_in(i.clone(), Global).unwrap();
145+
let v = i.clone().try_collect().unwrap();
146146
assert_eq!(v, [1, 1, 1, 1, 1]);
147147
assert!(v.len() <= v.capacity());
148148
}

0 commit comments

Comments
 (0)