Skip to content

Commit 9395efa

Browse files
committed
feat(bind): add fn_bind_map
1 parent 81aabd1 commit 9395efa

File tree

2 files changed

+85
-3
lines changed

2 files changed

+85
-3
lines changed

src/r3/src/bind/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,9 @@
113113
use r3_core::kernel::{cfg, raw, raw_cfg};
114114

115115
pub use r3_core::bind::{
116-
Bind, BindBorrow, BindBorrowMut, BindDefiner, BindRef, BindTable, BindTake, BindTakeMut,
117-
BindTakeRef, Binder, ExecutableDefiner, ExecutableDefinerExt, FnBind, FnBindNever, UnzipBind,
118-
INIT_HOOK_PRIORITY,
116+
fn_bind_map, Bind, BindBorrow, BindBorrowMut, BindDefiner, BindRef, BindTable, BindTake,
117+
BindTakeMut, BindTakeRef, Binder, ExecutableDefiner, ExecutableDefinerExt, FnBind, FnBindMap,
118+
FnBindNever, UnzipBind, INIT_HOOK_PRIORITY,
119119
};
120120

121121
/// A shorthand for [`Bind`][]`::`[`define`][1]`().`[`init_with_bind`][2]`(...)`.

src/r3_core/src/bind.rs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,6 +1184,88 @@ where
11841184
}
11851185
}
11861186

1187+
/// Apply a function to an `impl `[`FnBind`][]`<_>`'s output.
1188+
///
1189+
/// # Example
1190+
///
1191+
/// ```rust
1192+
/// #![feature(const_fn_trait_bound)]
1193+
/// #![feature(const_trait_impl)]
1194+
/// #![feature(const_mut_refs)]
1195+
/// use core::cell::UnsafeCell;
1196+
/// use r3_core::{kernel::{cfg, traits}, bind::{Bind, FnBind, fn_bind_map}};
1197+
///
1198+
/// /// Like `r3::bind::bind` but wraps the output in `UnsafeCell`
1199+
/// const fn unsafe_cell_bind<'pool, C, Binder, Func, T>(
1200+
/// cfg: &mut cfg::Cfg<'pool, C>,
1201+
/// binder: Binder,
1202+
/// func: Func,
1203+
/// ) -> Bind<'pool, C::System, UnsafeCell<T>>
1204+
/// where
1205+
/// C: ~const traits::CfgBase,
1206+
/// C::System: traits::KernelBase + traits::KernelStatic,
1207+
/// Func: ~const FnBind<Binder, Output = T>,
1208+
/// T: 'static,
1209+
/// {
1210+
/// Bind::define()
1211+
/// // Apply `UnsafeCell::new` on `func`'s output
1212+
/// .init_with_bind(binder, fn_bind_map(func, UnsafeCell::new))
1213+
/// .finish(cfg)
1214+
/// }
1215+
/// ```
1216+
pub const fn fn_bind_map<FnBind, Mapper>(
1217+
inner: FnBind,
1218+
mapper: Mapper,
1219+
) -> FnBindMap<FnBind, Mapper> {
1220+
FnBindMap { inner, mapper }
1221+
}
1222+
1223+
/// Applies a function to a [`FnBind`][]'s output.
1224+
///
1225+
/// Created by [`fn_bind_map`][].
1226+
pub struct FnBindMap<Inner, Mapper> {
1227+
inner: Inner,
1228+
mapper: Mapper,
1229+
}
1230+
1231+
impl<Binder, Inner, InnerBoundFn, Output, Mapper, NewOutput> const FnBind<Binder>
1232+
for FnBindMap<Inner, Mapper>
1233+
where
1234+
Inner: ~const FnBind<Binder, Output = Output, BoundFn = InnerBoundFn>,
1235+
InnerBoundFn: FnOnce() -> Output + Copy + Send + 'static,
1236+
Output: 'static,
1237+
Mapper: FnOnce(Output) -> NewOutput + Copy + Send + 'static,
1238+
NewOutput: 'static,
1239+
{
1240+
type Output = NewOutput;
1241+
1242+
// FIXME: `impl` type alias in trait impls implicitly captures the
1243+
// surrounding environment's generic parameters? That's probably why this
1244+
// `impl` type alias has to stay outside this `impl` block.
1245+
type BoundFn = MappedBoundFn<InnerBoundFn, Output, Mapper, NewOutput>;
1246+
1247+
fn bind(self, binder: Binder, ctx: &mut CfgBindCtx<'_>) -> Self::BoundFn {
1248+
map_bind_inner(self.inner.bind(binder, ctx), self.mapper)
1249+
}
1250+
}
1251+
1252+
type MappedBoundFn<InnerBoundFn, Output, Mapper, NewOutput>
1253+
where
1254+
InnerBoundFn: Copy + Send + 'static,
1255+
Mapper: Copy + Send + 'static,
1256+
= impl FnOnce() -> NewOutput + Copy + Send + 'static;
1257+
1258+
const fn map_bind_inner<InnerBoundFn, Output, Mapper, NewOutput>(
1259+
inner_bound_fn: InnerBoundFn,
1260+
mapper: Mapper,
1261+
) -> MappedBoundFn<InnerBoundFn, Output, Mapper, NewOutput>
1262+
where
1263+
InnerBoundFn: FnOnce() -> Output + Copy + Send + 'static,
1264+
Mapper: FnOnce(Output) -> NewOutput + Copy + Send + 'static,
1265+
{
1266+
move || (mapper)(inner_bound_fn())
1267+
}
1268+
11871269
// Binder traits
11881270
// ----------------------------------------------------------------------------
11891271

0 commit comments

Comments
 (0)