11//! Data structures to represent account information.
22
33use core:: {
4- convert:: Infallible ,
54 marker:: PhantomData ,
65 mem:: ManuallyDrop ,
76 ptr:: { write, NonNull } ,
@@ -662,25 +661,36 @@ impl<'a, T: ?Sized> Ref<'a, T> {
662661 pub fn map < U : ?Sized , F > ( orig : Ref < ' a , T > , f : F ) -> Ref < ' a , U >
663662 where
664663 F : FnOnce ( & T ) -> & U ,
665- {
666- Self :: try_map :: < _ , _ , Infallible > ( orig, |x| Ok ( f ( x) ) ) . unwrap ( )
667- }
668-
669- /// Maps a reference to a new type in a fallible map, returning an error if the map fails.
670- #[ inline]
671- pub fn try_map < U : ?Sized , F , E > ( orig : Ref < ' a , T > , f : F ) -> Result < Ref < ' a , U > , E >
672- where
673- F : FnOnce ( & T ) -> Result < & U , E > ,
674664 {
675665 // Avoid decrementing the borrow flag on Drop.
676666 let orig = ManuallyDrop :: new ( orig) ;
677-
678- Ok ( Ref {
679- value : NonNull :: from ( f ( & * orig) ?) ,
667+ Ref {
668+ value : NonNull :: from ( f ( & * orig) ) ,
680669 state : orig. state ,
681670 borrow_shift : orig. borrow_shift ,
682671 marker : PhantomData ,
683- } )
672+ }
673+ }
674+
675+ /// Tries to makes a new `Ref` for a component of the borrowed data.
676+ /// On failure, the original guard is returned alongside with the error
677+ /// returned by the closure.
678+ #[ inline]
679+ pub fn try_map < U : ?Sized , E > (
680+ orig : Ref < ' a , T > ,
681+ f : impl FnOnce ( & T ) -> Result < & U , E > ,
682+ ) -> Result < Ref < ' a , U > , ( Self , E ) > {
683+ // Avoid decrementing the borrow flag on Drop.
684+ let orig = ManuallyDrop :: new ( orig) ;
685+ match f ( & * orig) {
686+ Ok ( value) => Ok ( Ref {
687+ value : NonNull :: from ( value) ,
688+ state : orig. state ,
689+ borrow_shift : orig. borrow_shift ,
690+ marker : PhantomData ,
691+ } ) ,
692+ Err ( e) => Err ( ( ManuallyDrop :: into_inner ( orig) , e) ) ,
693+ }
684694 }
685695
686696 /// Filters and maps a reference to a new type.
@@ -743,26 +753,36 @@ impl<'a, T: ?Sized> RefMut<'a, T> {
743753 pub fn map < U : ?Sized , F > ( orig : RefMut < ' a , T > , f : F ) -> RefMut < ' a , U >
744754 where
745755 F : FnOnce ( & mut T ) -> & mut U ,
746- {
747- Self :: try_map :: < _ , _ , Infallible > ( orig, |x| Ok ( f ( x) ) ) . unwrap ( )
748- }
749-
750- /// Maps a mutable reference to a new type in a fallible map, returning an error if the map fails.
751- #[ inline]
752- pub fn try_map < U : ?Sized , F , E > ( orig : RefMut < ' a , T > , f : F ) -> Result < RefMut < ' a , U > , E >
753- where
754- F : FnOnce ( & mut T ) -> Result < & mut U , E > ,
755756 {
756757 // Avoid decrementing the borrow flag on Drop.
757758 let mut orig = ManuallyDrop :: new ( orig) ;
758- let value = f ( & mut * orig) ?;
759-
760- Ok ( RefMut {
761- value : NonNull :: from ( value) ,
759+ RefMut {
760+ value : NonNull :: from ( f ( & mut * orig) ) ,
762761 state : orig. state ,
763762 borrow_bitmask : orig. borrow_bitmask ,
764763 marker : PhantomData ,
765- } )
764+ }
765+ }
766+
767+ /// Tries to makes a new `RefMut` for a component of the borrowed data.
768+ /// On failure, the original guard is returned alongside with the error
769+ /// returned by the closure.
770+ #[ inline]
771+ pub fn try_map < U : ?Sized , E > (
772+ orig : RefMut < ' a , T > ,
773+ f : impl FnOnce ( & mut T ) -> Result < & mut U , E > ,
774+ ) -> Result < RefMut < ' a , U > , ( Self , E ) > {
775+ // Avoid decrementing the borrow flag on Drop.
776+ let mut orig = ManuallyDrop :: new ( orig) ;
777+ match f ( & mut * orig) {
778+ Ok ( value) => Ok ( RefMut {
779+ value : NonNull :: from ( value) ,
780+ state : orig. state ,
781+ borrow_bitmask : orig. borrow_bitmask ,
782+ marker : PhantomData ,
783+ } ) ,
784+ Err ( e) => Err ( ( ManuallyDrop :: into_inner ( orig) , e) ) ,
785+ }
766786 }
767787
768788 /// Filters and maps a mutable reference to a new type.
@@ -773,17 +793,13 @@ impl<'a, T: ?Sized> RefMut<'a, T> {
773793 {
774794 // Avoid decrementing the mutable borrow flag on Drop.
775795 let mut orig = ManuallyDrop :: new ( orig) ;
776-
777796 match f ( & mut * orig) {
778- Some ( value) => {
779- let value = NonNull :: from ( value) ;
780- Ok ( RefMut {
781- value,
782- state : orig. state ,
783- borrow_bitmask : orig. borrow_bitmask ,
784- marker : PhantomData ,
785- } )
786- }
797+ Some ( value) => Ok ( RefMut {
798+ value : NonNull :: from ( value) ,
799+ state : orig. state ,
800+ borrow_bitmask : orig. borrow_bitmask ,
801+ marker : PhantomData ,
802+ } ) ,
787803 None => Err ( ManuallyDrop :: into_inner ( orig) ) ,
788804 }
789805 }
@@ -841,6 +857,19 @@ mod tests {
841857 assert_eq ! ( state, NOT_BORROWED - ( 1 << DATA_BORROW_SHIFT ) ) ;
842858 assert_eq ! ( * new_ref, 3 ) ;
843859
860+ let Ok ( new_ref) = Ref :: try_map :: < _ , u8 > ( new_ref, |_| Ok ( & 4 ) ) else {
861+ unreachable ! ( )
862+ } ;
863+
864+ assert_eq ! ( state, NOT_BORROWED - ( 1 << DATA_BORROW_SHIFT ) ) ;
865+ assert_eq ! ( * new_ref, 4 ) ;
866+
867+ let ( new_ref, err) = Ref :: try_map :: < u8 , u8 > ( new_ref, |_| Err ( 5 ) ) . unwrap_err ( ) ;
868+ assert_eq ! ( state, NOT_BORROWED - ( 1 << DATA_BORROW_SHIFT ) ) ;
869+ assert_eq ! ( err, 5 ) ;
870+ // Unchanged
871+ assert_eq ! ( * new_ref, 4 ) ;
872+
844873 let new_ref = Ref :: filter_map ( new_ref, |_| Option :: < & u8 > :: None ) ;
845874
846875 assert_eq ! ( state, NOT_BORROWED - ( 1 << DATA_BORROW_SHIFT ) ) ;
0 commit comments