44
55use core:: { ops:: Deref , pin:: Pin } ;
66
7+ use alloc:: collections:: TryReserveError ;
8+ use alloc:: string:: String ;
9+ use alloc:: vec:: Vec ;
710use alloc:: { alloc:: AllocError , sync:: Arc } ;
811
12+ type AllocResult < T = ( ) > = core:: result:: Result < T , AllocError > ;
13+ type CollectionResult < T = ( ) > = core:: result:: Result < T , TryReserveError > ;
14+
15+ #[ inline]
16+ fn assume_fallible < T , F : FnOnce ( ) -> T > ( f : F ) -> T {
17+ f ( )
18+ }
19+
920/// Trait which provides a fallible version of `pin()` for pointer types.
1021///
1122/// Common pointer types which implement a `pin()` method include [`Box`](alloc::boxed::Box) and [`Arc`].
@@ -24,3 +35,105 @@ impl<T> TryPin<Arc<T>> for Arc<T> {
2435 Ok ( unsafe { Pin :: new_unchecked ( Arc :: try_new ( data) ?) } )
2536 }
2637}
38+
39+ /// Faillible alternative to [`alloc::borrow::ToOwned`].
40+ pub trait TryToOwned {
41+ /// The resulting type after obtaining ownership.
42+ type Owned : core:: borrow:: Borrow < Self > ;
43+
44+ /// Faillible alternative to [`alloc::borrow::ToOwned::to_owned`].
45+ #[ must_use = "cloning is often expensive and is not expected to have side effects" ]
46+ fn try_to_owned ( & self ) -> AllocResult < Self :: Owned > ;
47+
48+ /// Faillible alternative to [`alloc::borrow::ToOwned::clone_into`].
49+ fn try_clone_into ( & self , target : & mut Self :: Owned ) -> AllocResult {
50+ * target = self . try_to_owned ( ) ?;
51+ Ok ( ( ) )
52+ }
53+ }
54+
55+ impl < T : Clone > TryToOwned for [ T ] {
56+ type Owned = Vec < T > ;
57+
58+ fn try_to_owned ( & self ) -> AllocResult < Vec < T > > {
59+ let mut vec = Vec :: new ( ) ;
60+ self . try_clone_into ( & mut vec) ?;
61+ Ok ( vec)
62+ }
63+
64+ fn try_clone_into ( & self , target : & mut Vec < T > ) -> AllocResult {
65+ // Ensure target has enough capacity
66+ target
67+ . try_reserve_exact ( self . len ( ) . saturating_sub ( target. len ( ) ) )
68+ . map_err ( |_| AllocError ) ?;
69+
70+ target. clear ( ) ;
71+ assume_fallible ( || target. extend_from_slice ( self ) ) ;
72+ Ok ( ( ) )
73+ }
74+ }
75+
76+ impl TryToOwned for str {
77+ type Owned = String ;
78+
79+ fn try_to_owned ( & self ) -> AllocResult < String > {
80+ let mut vec = String :: new ( ) ;
81+ self . try_clone_into ( & mut vec) ?;
82+ Ok ( vec)
83+ }
84+
85+ fn try_clone_into ( & self , target : & mut String ) -> AllocResult {
86+ // Ensure target has enough capacity
87+ target
88+ . try_reserve_exact ( self . len ( ) . saturating_sub ( target. len ( ) ) )
89+ . map_err ( |_| AllocError ) ?;
90+
91+ target. clear ( ) ;
92+ assume_fallible ( || target. push_str ( self ) ) ;
93+ Ok ( ( ) )
94+ }
95+ }
96+
97+ /// Trait which provides a fallible methods for [`Vec`].
98+ pub trait VecExt < T > {
99+ /// Faillible alternative to [`Vec::with_capacity`].
100+ fn try_with_capacity ( capacity : usize ) -> CollectionResult < Self >
101+ where
102+ Self : Sized ;
103+
104+ /// Faillible alternative to [`Vec::extend_from_slice`].
105+ fn try_extend_from_slice ( & mut self , other : & [ T ] ) -> CollectionResult
106+ where
107+ T : Clone ;
108+
109+ /// Faillible alternative to [`Vec::resize`].
110+ fn try_resize ( & mut self , new_len : usize , value : T ) -> CollectionResult
111+ where
112+ T : Clone ;
113+ }
114+
115+ impl < T > VecExt < T > for alloc:: vec:: Vec < T > {
116+ fn try_with_capacity ( capacity : usize ) -> CollectionResult < Self > {
117+ let mut vec = Self :: new ( ) ;
118+ vec. try_reserve_exact ( capacity) ?;
119+ Ok ( vec)
120+ }
121+
122+ fn try_extend_from_slice ( & mut self , other : & [ T ] ) -> CollectionResult
123+ where
124+ T : Clone ,
125+ {
126+ self . try_reserve ( other. len ( ) ) ?;
127+ assume_fallible ( || self . extend_from_slice ( other) ) ;
128+ Ok ( ( ) )
129+ }
130+
131+ fn try_resize ( & mut self , new_len : usize , value : T ) -> CollectionResult
132+ where
133+ T : Clone ,
134+ {
135+ self . try_reserve ( new_len. saturating_sub ( self . len ( ) ) ) ?;
136+ assume_fallible ( || self . resize ( new_len, value) ) ;
137+ Ok ( ( ) )
138+ }
139+ }
0 commit comments