Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 6a69f39

Browse files
committed
add Box::(try_)map
1 parent 94722ca commit 6a69f39

File tree

2 files changed

+92
-2
lines changed

2 files changed

+92
-2
lines changed

‎library/alloc/src/boxed.rs

Lines changed: 91 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,8 @@ use core::hash::{Hash, Hasher};
194194
use core::marker::{Tuple, Unsize};
195195
use core::mem::{self, SizedTypeProperties};
196196
use core::ops::{
197-
AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, Coroutine, CoroutineState, Deref,DerefMut,
198-
DerefPure, DispatchFromDyn, LegacyReceiver,
197+
AsyncFn, AsyncFnMut, AsyncFnOnce, CoerceUnsized, ControlFlow,Coroutine, CoroutineState, Deref,
198+
DerefMut,DerefPure, DispatchFromDyn, FromResidual,LegacyReceiver,Residual,Try,
199199
};
200200
use core::pin::{Pin, PinCoerceUnsized};
201201
use core::ptr::{self, NonNull, Unique};
@@ -389,6 +389,95 @@ impl<T> Box<T> {
389389
pub fn try_new_zeroed() -> Result<Box<mem::MaybeUninit<T>>, AllocError> {
390390
Box::try_new_zeroed_in(Global)
391391
}
392+
393+
/// Maps the value in a box, reusing the allocation if possible.
394+
///
395+
/// `f` is called on the value in the box, and the result is returned, also boxed.
396+
///
397+
/// Note: this is an associated function, which means that you have
398+
/// to call it as `Box::map(b, f)` instead of `b.map(f)`. This
399+
/// is so that there is no conflict with a method on the inner type.
400+
///
401+
/// # Examples
402+
///
403+
/// ```
404+
/// #![feature(smart_pointer_try_map)]
405+
///
406+
/// let b = Box::new(7);
407+
/// let new = Box::map(b, |i| i + 7);
408+
/// assert_eq!(*new, 14);
409+
/// ```
410+
#[unstable(feature = "smart_pointer_try_map", issue = "144419")]
411+
pub fn map<U>(this: Self, f: impl FnOnce(T) -> U) -> Box<U> {
412+
if size_of::<T>() == size_of::<U>() && align_of::<T>() == align_of::<U>() {
413+
let ptr = &raw const *this;
414+
unsafe {
415+
let new = f(ptr.read());
416+
let ptr = Box::into_raw(this);
417+
ptr.cast::<U>().write(new);
418+
Box::from_raw(ptr.cast::<U>())
419+
}
420+
} else {
421+
Box::new(f(*this))
422+
}
423+
}
424+
425+
/// Attempts to map the value in a box, reusing the allocation if possible.
426+
///
427+
/// `f` is called on the value in the box, and if the operation succeeds, the result is
428+
/// returned, also boxed.
429+
///
430+
/// Note: this is an associated function, which means that you have
431+
/// to call it as `Box::try_map(b, f)` instead of `b.try_map(f)`. This
432+
/// is so that there is no conflict with a method on the inner type.
433+
///
434+
/// # Examples
435+
///
436+
/// ```
437+
/// #![feature(smart_pointer_try_map)]
438+
///
439+
/// let b = Box::new(7);
440+
/// let new = Box::try_map(b, u32::try_from).unwrap();
441+
/// assert_eq!(*new, 7);
442+
/// ```
443+
#[unstable(feature = "smart_pointer_try_map", issue = "144419")]
444+
pub fn try_map<R>(
445+
this: Self,
446+
f: impl FnOnce(T) -> R,
447+
) -> <R::Residual as Residual<Box<R::Output>>>::TryType
448+
where
449+
R: Try,
450+
R::Residual: Residual<Box<R::Output>>,
451+
{
452+
if size_of::<T>() == size_of::<R::Output>() && align_of::<T>() == align_of::<R::Output>() {
453+
let ptr = &raw const *this;
454+
unsafe {
455+
let new = f(ptr.read());
456+
let ptr = Box::into_raw(this);
457+
match new.branch() {
458+
ControlFlow::Continue(c) => {
459+
ptr.cast::<R::Output>().write(c);
460+
<R::Residual as Residual<Box<R::Output>>>::TryType::from_output(
461+
Box::from_raw(ptr.cast::<R::Output>()),
462+
)
463+
}
464+
ControlFlow::Break(b) => {
465+
drop(Box::from_raw(ptr));
466+
<R::Residual as Residual<Box<R::Output>>>::TryType::from_residual(b)
467+
}
468+
}
469+
}
470+
} else {
471+
match f(*this).branch() {
472+
ControlFlow::Continue(c) => {
473+
<R::Residual as Residual<Box<R::Output>>>::TryType::from_output(Box::new(c))
474+
}
475+
ControlFlow::Break(b) => {
476+
<R::Residual as Residual<Box<R::Output>>>::TryType::from_residual(b)
477+
}
478+
}
479+
}
480+
}
392481
}
393482

394483
impl<T, A: Allocator> Box<T, A> {

‎library/alloc/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
#![feature(trusted_len)]
154154
#![feature(trusted_random_access)]
155155
#![feature(try_trait_v2)]
156+
#![feature(try_trait_v2_residual)]
156157
#![feature(try_with_capacity)]
157158
#![feature(tuple_trait)]
158159
#![feature(ub_checks)]

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /