4
4
5
5
use core:: { ops:: Deref , pin:: Pin } ;
6
6
7
+ use alloc:: collections:: TryReserveError ;
8
+ use alloc:: string:: String ;
9
+ use alloc:: vec:: Vec ;
7
10
use alloc:: { alloc:: AllocError , sync:: Arc } ;
8
11
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
+
9
20
/// Trait which provides a fallible version of `pin()` for pointer types.
10
21
///
11
22
/// 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> {
24
35
Ok ( unsafe { Pin :: new_unchecked ( Arc :: try_new ( data) ?) } )
25
36
}
26
37
}
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