Skip to content

Commit 8929c79

Browse files
committed
rust: init: Add chain() and pin_chain() functions
These functinos allow users to chain post-processing code to an initializer, which can be used to mutate the (fully initialized) object in place as part of an initializer chain. Ideally this would be a trait function (e.g. init!(...).and_then(...)), but that requires return_position_impl_trait_in_trait... Signed-off-by: Asahi Lina <[email protected]>
1 parent 9a0732d commit 8929c79

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

rust/kernel/init.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,6 +1275,57 @@ pub unsafe trait Init<T: ?Sized, E = Infallible>: Sized {
12751275
unsafe fn __init(self, slot: *mut T) -> Result<(), E>;
12761276
}
12771277

1278+
/// Chains a closure to the initializer to be called on successful initialization.
1279+
///
1280+
/// Returns a new initializer. If the closure returns `Err`, the object is
1281+
/// dropped.
1282+
// TODO: Once return_position_impl_trait_in_trait works, this should probably be
1283+
// a trait method and called `and_then()` or so.
1284+
pub fn chain<T: ?Sized, E>(
1285+
this: impl Init<T, E>,
1286+
f: impl FnOnce(&mut T) -> Result<(), E>,
1287+
) -> impl Init<T, E> {
1288+
unsafe {
1289+
init_from_closure(|slot: *mut T| {
1290+
this.__init(slot)?;
1291+
1292+
f(&mut *slot).map_err(|e| {
1293+
// SAFETY: The value was initialized above, and since we return
1294+
// `Err` here, the caller will consider the memory at `slot` to
1295+
// be uninitialized.
1296+
ptr::drop_in_place(slot);
1297+
e
1298+
})
1299+
})
1300+
}
1301+
}
1302+
1303+
/// Chains a closure to the pinned initializer to be called on successful
1304+
/// initialization.
1305+
///
1306+
/// Returns a new initializer. If the closure returns `Err`, the object is
1307+
/// dropped.
1308+
// TODO: Once return_position_impl_trait_in_trait works, this should probably be
1309+
// a trait method and called `and_then()` or so.
1310+
pub fn pin_chain<T: ?Sized, E>(
1311+
this: impl PinInit<T, E>,
1312+
f: impl FnOnce(&mut T) -> Result<(), E>,
1313+
) -> impl PinInit<T, E> {
1314+
unsafe {
1315+
init_from_closure(|slot: *mut T| {
1316+
this.__pinned_init(slot)?;
1317+
1318+
f(&mut *slot).map_err(|e| {
1319+
// SAFETY: The value was initialized above, and since we return
1320+
// `Err` here, the caller will consider the memory at `slot` to
1321+
// be uninitialized.
1322+
ptr::drop_in_place(slot);
1323+
e
1324+
})
1325+
})
1326+
}
1327+
}
1328+
12781329
// SAFETY: Every in-place initializer can also be used as a pin-initializer.
12791330
unsafe impl<T: ?Sized, E, I> PinInit<T, E> for I
12801331
where

0 commit comments

Comments
 (0)