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,97 @@ 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
+ pub trait TryToOwned {
40
+ type Owned : core:: borrow:: Borrow < Self > ;
41
+
42
+ #[ must_use = "cloning is often expensive and is not expected to have side effects" ]
43
+ fn try_to_owned ( & self ) -> AllocResult < Self :: Owned > ;
44
+
45
+ fn try_clone_into ( & self , target : & mut Self :: Owned ) -> AllocResult {
46
+ * target = self . try_to_owned ( ) ?;
47
+ Ok ( ( ) )
48
+ }
49
+ }
50
+
51
+ impl < T : Clone > TryToOwned for [ T ] {
52
+ type Owned = Vec < T > ;
53
+
54
+ fn try_to_owned ( & self ) -> AllocResult < Vec < T > > {
55
+ let mut vec = Vec :: new ( ) ;
56
+ self . try_clone_into ( & mut vec) ?;
57
+ Ok ( vec)
58
+ }
59
+
60
+ fn try_clone_into ( & self , target : & mut Vec < T > ) -> AllocResult {
61
+ // Ensure target has enough capacity
62
+ target
63
+ . try_reserve_exact ( self . len ( ) . saturating_sub ( target. len ( ) ) )
64
+ . map_err ( |_| AllocError ) ?;
65
+
66
+ target. clear ( ) ;
67
+ assume_fallible ( || target. extend_from_slice ( self ) ) ;
68
+ Ok ( ( ) )
69
+ }
70
+ }
71
+
72
+ impl TryToOwned for str {
73
+ type Owned = String ;
74
+
75
+ fn try_to_owned ( & self ) -> AllocResult < String > {
76
+ let mut vec = String :: new ( ) ;
77
+ self . try_clone_into ( & mut vec) ?;
78
+ Ok ( vec)
79
+ }
80
+
81
+ fn try_clone_into ( & self , target : & mut String ) -> AllocResult {
82
+ // Ensure target has enough capacity
83
+ target
84
+ . try_reserve_exact ( self . len ( ) . saturating_sub ( target. len ( ) ) )
85
+ . map_err ( |_| AllocError ) ?;
86
+
87
+ target. clear ( ) ;
88
+ assume_fallible ( || target. push_str ( self ) ) ;
89
+ Ok ( ( ) )
90
+ }
91
+ }
92
+
93
+ pub trait VecExt < T > {
94
+ fn try_with_capacity ( capacity : usize ) -> CollectionResult < Self >
95
+ where
96
+ Self : Sized ;
97
+
98
+ fn try_extend_from_slice ( & mut self , other : & [ T ] ) -> CollectionResult
99
+ where
100
+ T : Clone ;
101
+
102
+ fn try_resize ( & mut self , new_len : usize , value : T ) -> CollectionResult
103
+ where
104
+ T : Clone ;
105
+ }
106
+
107
+ impl < T > VecExt < T > for alloc:: vec:: Vec < T > {
108
+ fn try_with_capacity ( capacity : usize ) -> CollectionResult < Self > {
109
+ let mut vec = Self :: new ( ) ;
110
+ vec. try_reserve_exact ( capacity) ?;
111
+ Ok ( vec)
112
+ }
113
+
114
+ fn try_extend_from_slice ( & mut self , other : & [ T ] ) -> CollectionResult
115
+ where
116
+ T : Clone ,
117
+ {
118
+ self . try_reserve ( other. len ( ) ) ?;
119
+ assume_fallible ( || self . extend_from_slice ( other) ) ;
120
+ Ok ( ( ) )
121
+ }
122
+
123
+ fn try_resize ( & mut self , new_len : usize , value : T ) -> CollectionResult
124
+ where
125
+ T : Clone ,
126
+ {
127
+ self . try_reserve ( new_len. saturating_sub ( self . len ( ) ) ) ?;
128
+ assume_fallible ( || self . resize ( new_len, value) ) ;
129
+ Ok ( ( ) )
130
+ }
131
+ }
0 commit comments