@@ -1392,6 +1392,93 @@ where
13921392 unsafe { pin_init_from_closure ( init) }
13931393}
13941394
1395+ /// Construct an initializer in a closure and run it.
1396+ ///
1397+ /// Returns an initializer that first runs the closure and then the initializer returned by it.
1398+ ///
1399+ /// See also [init_scope].
1400+ ///
1401+ /// # Examples
1402+ ///
1403+ /// ```
1404+ /// # use pin_init::*;
1405+ /// # #[pin_data]
1406+ /// # struct Foo { a: u64, b: isize }
1407+ /// # struct Bar { a: u32, b: isize }
1408+ /// # fn lookup_bar() -> Result<Bar, Error> { todo!() }
1409+ /// # struct Error;
1410+ /// fn init_foo() -> impl PinInit<Foo, Error> {
1411+ /// pin_init_scope(|| {
1412+ /// let bar = lookup_bar()?;
1413+ /// Ok(try_pin_init!(Foo { a: bar.a.into(), b: bar.b }? Error))
1414+ /// })
1415+ /// }
1416+ /// ```
1417+ ///
1418+ /// This initializer will first execute `lookup_bar()`, match on it, if it returned an error, the
1419+ /// initializer itself will fail with that error. If it returned `Ok`, then it will run the
1420+ /// initializer returned by the `try_init!` invocation.
1421+ pub fn pin_init_scope < T , E , F , I > ( make_init : F ) -> impl PinInit < T , E >
1422+ where
1423+ F : FnOnce ( ) -> Result < I , E > ,
1424+ I : PinInit < T , E > ,
1425+ {
1426+ // SAFETY:
1427+ // - If `make_init` returns `Err`, `Err` is returned and `slot` is completely uninitialized,
1428+ // - If `make_init` returns `Ok`, safety requirement are fulfilled by `init.__pinned_init`.
1429+ // - The safety requirements of `init.__pinned_init` are fulfilled, since it's being called
1430+ // from an initializer.
1431+ unsafe {
1432+ pin_init_from_closure ( move |slot : * mut T | -> Result < ( ) , E > {
1433+ let init = make_init ( ) ?;
1434+ init. __pinned_init ( slot)
1435+ } )
1436+ }
1437+ }
1438+
1439+ /// Construct an initializer in a closure and run it.
1440+ ///
1441+ /// Returns an initializer that first runs the closure and then the initializer returned by it.
1442+ ///
1443+ /// See also [pin_init_scope].
1444+ ///
1445+ /// # Examples
1446+ ///
1447+ /// ```
1448+ /// # use pin_init::*;
1449+ /// # struct Foo { a: u64, b: isize }
1450+ /// # struct Bar { a: u32, b: isize }
1451+ /// # fn lookup_bar() -> Result<Bar, Error> { todo!() }
1452+ /// # struct Error;
1453+ /// fn init_foo() -> impl Init<Foo, Error> {
1454+ /// init_scope(|| {
1455+ /// let bar = lookup_bar()?;
1456+ /// Ok(try_init!(Foo { a: bar.a.into(), b: bar.b }? Error))
1457+ /// })
1458+ /// }
1459+ /// ```
1460+ ///
1461+ /// This initializer will first execute `lookup_bar()`, match on it, if it returned an error, the
1462+ /// initializer itself will fail with that error. If it returned `Ok`, then it will run the
1463+ /// initializer returned by the `try_init!` invocation.
1464+ pub fn init_scope < T , E , F , I > ( make_init : F ) -> impl Init < T , E >
1465+ where
1466+ F : FnOnce ( ) -> Result < I , E > ,
1467+ I : Init < T , E > ,
1468+ {
1469+ // SAFETY:
1470+ // - If `make_init` returns `Err`, `Err` is returned and `slot` is completely uninitialized,
1471+ // - If `make_init` returns `Ok`, safety requirement are fulfilled by `init.__init`.
1472+ // - The safety requirements of `init.__init` are fulfilled, since it's being called from an
1473+ // initializer.
1474+ unsafe {
1475+ init_from_closure ( move |slot : * mut T | -> Result < ( ) , E > {
1476+ let init = make_init ( ) ?;
1477+ init. __init ( slot)
1478+ } )
1479+ }
1480+ }
1481+
13951482// SAFETY: the `__init` function always returns `Ok(())` and initializes every field of `slot`.
13961483unsafe impl < T > Init < T > for T {
13971484 unsafe fn __init ( self , slot : * mut T ) -> Result < ( ) , Infallible > {
0 commit comments