@@ -42,6 +42,12 @@ impl<T: ImplicitClone + 'static> FromIterator<T> for IArray<T> {
42
42
}
43
43
}
44
44
45
+ impl < T : ImplicitClone + ' static > Extend < T > for IArray < T > {
46
+ fn extend < I : IntoIterator < Item = T > > ( & mut self , iter : I ) {
47
+ self . insert_many ( self . len ( ) , iter) ;
48
+ }
49
+ }
50
+
45
51
impl < T : ImplicitClone + ' static > ImplicitClone for IArray < T > { }
46
52
47
53
impl < T : ImplicitClone + ' static > From < & ' static [ T ] > for IArray < T > {
@@ -160,6 +166,161 @@ impl<T: ImplicitClone + 'static> IArray<T> {
160
166
Self :: Rc ( a) => a. get ( index) . cloned ( ) ,
161
167
}
162
168
}
169
+
170
+ /// Makes a mutable reference into the array.
171
+ ///
172
+ /// If this array is an `Rc` with no other strong or weak references, returns
173
+ /// a mutable slice of the contained data without any cloning. Otherwise, it clones the
174
+ /// data into a new array and returns a mutable slice into that.
175
+ ///
176
+ /// # Example
177
+ ///
178
+ /// ```
179
+ /// # use implicit_clone::unsync::*;
180
+ /// # use std::rc::Rc;
181
+ /// // This will reuse the Rc storage
182
+ /// let mut v1 = IArray::<u8>::Rc(Rc::new([1,2,3]));
183
+ /// v1.make_mut()[1] = 123;
184
+ /// assert_eq!(&[1,123,3], v1.as_slice());
185
+ ///
186
+ /// // This will create a new copy
187
+ /// let mut v2 = IArray::<u8>::Static(&[1,2,3]);
188
+ /// v2.make_mut()[1] = 123;
189
+ /// assert_eq!(&[1,123,3], v2.as_slice());
190
+ /// ```
191
+ #[ inline]
192
+ pub fn make_mut ( & mut self ) -> & mut [ T ] {
193
+ // This code is somewhat weirdly written to work around https://github.com/rust-lang/rust/issues/54663 -
194
+ // we can't just check if this is an Rc with one reference with get_mut in an if branch and copy otherwise,
195
+ // since returning the mutable slice extends its lifetime for the rest of the function.
196
+ match self {
197
+ Self :: Rc ( ref mut rc) => {
198
+ if Rc :: get_mut ( rc) . is_none ( ) {
199
+ * rc = rc. iter ( ) . cloned ( ) . collect :: < Rc < [ T ] > > ( ) ;
200
+ }
201
+ Rc :: get_mut ( rc) . unwrap ( )
202
+ }
203
+ Self :: Static ( slice) => {
204
+ * self = Self :: Rc ( slice. iter ( ) . cloned ( ) . collect ( ) ) ;
205
+ match self {
206
+ Self :: Rc ( rc) => Rc :: get_mut ( rc) . unwrap ( ) ,
207
+ _ => unreachable ! ( ) ,
208
+ }
209
+ }
210
+ }
211
+ }
212
+
213
+ /// Inserts several objects into the array.
214
+ ///
215
+ /// This overwrites `self` to a new refcounted array with clones of the previous items,
216
+ /// with items from the `values` iterator inserted starting at the specified index, shifting
217
+ /// later items down.
218
+ ///
219
+ /// # Panics
220
+ ///
221
+ /// Panics if the index is greater than one more than the length of the array.
222
+ ///
223
+ /// # Example
224
+ ///
225
+ /// ```
226
+ /// # use implicit_clone::unsync::*;
227
+ /// let mut v = IArray::<u8>::Static(&[1,2,6]);
228
+ /// v.insert_many(2, [3,4,5]);
229
+ /// assert_eq!(&[1,2,3,4,5,6], v.as_slice());
230
+ /// ```
231
+ pub fn insert_many < I : IntoIterator < Item = T > > ( & mut self , index : usize , values : I ) {
232
+ let head = self . as_slice ( ) [ ..index] . iter ( ) . cloned ( ) ;
233
+ let tail = self . as_slice ( ) [ index..] . iter ( ) . cloned ( ) ;
234
+ let rc = head. chain ( values) . chain ( tail) . collect ( ) ;
235
+ * self = Self :: Rc ( rc) ;
236
+ }
237
+
238
+ /// Inserts an object into the array.
239
+ ///
240
+ /// This overwrites `self` to a new refcounted array with clones of the previous items,
241
+ /// with `value` inserted at the `index`, shifting later items down.
242
+ ///
243
+ /// [`Self::insert_many`] will be more efficient if inserting multiple items.
244
+ ///
245
+ /// # Panics
246
+ ///
247
+ /// Panics if the index is greater than one more than the length of the array.
248
+ ///
249
+ /// # Example
250
+ ///
251
+ /// ```
252
+ /// # use implicit_clone::unsync::*;
253
+ /// let mut v = IArray::<u8>::Static(&[1,2,4]);
254
+ /// v.insert(2, 3);
255
+ /// assert_eq!(&[1,2,3,4], v.as_slice());
256
+ /// ```
257
+ pub fn insert ( & mut self , index : usize , value : T ) {
258
+ self . insert_many ( index, std:: iter:: once ( value) ) ;
259
+ }
260
+
261
+ /// Adds an object to the end of the array.
262
+ ///
263
+ /// This overwrites `self` to a new refcounted array with clones of the previous items,
264
+ /// with `value` added at the end.
265
+ ///
266
+ /// [`Self::extend`] will be more efficient if inserting multiple items.
267
+ ///
268
+ /// # Example
269
+ ///
270
+ /// ```
271
+ /// # use implicit_clone::unsync::*;
272
+ /// let mut v = IArray::<u8>::Static(&[1,2,3]);
273
+ /// v.push(4);
274
+ /// assert_eq!(&[1,2,3,4], v.as_slice());
275
+ /// ```
276
+ pub fn push ( & mut self , value : T ) {
277
+ self . insert ( self . len ( ) , value) ;
278
+ }
279
+
280
+ /// Removes a range of items from the array.
281
+ ///
282
+ /// This overwrites `self` to a new refcounted array with clones of the previous items, excluding
283
+ /// the items covered by `range`, with later items shifted up.
284
+ ///
285
+ /// # Panics
286
+ ///
287
+ /// Panics if the range is out of bounds.
288
+ ///
289
+ /// # Example
290
+ ///
291
+ /// ```
292
+ /// # use implicit_clone::unsync::*;
293
+ /// let mut v = IArray::<u8>::Static(&[1,2,10,20,3]);
294
+ /// v.remove_range(2..4);
295
+ /// assert_eq!(&[1,2,3], v.as_slice());
296
+ /// ```
297
+ pub fn remove_range ( & mut self , range : std:: ops:: Range < usize > ) {
298
+ let head = self . as_slice ( ) [ ..range. start ] . iter ( ) . cloned ( ) ;
299
+ let tail = self . as_slice ( ) [ range. end ..] . iter ( ) . cloned ( ) ;
300
+ let rc = head. chain ( tail) . collect ( ) ;
301
+ * self = Self :: Rc ( rc) ;
302
+ }
303
+
304
+ /// Removes an item from the array.
305
+ ///
306
+ /// This overwrites `self` to a new refcounted array with clones of the previous items, excluding
307
+ /// the items at `index`, with later items shifted up.
308
+ ///
309
+ /// # Panics
310
+ ///
311
+ /// Panics if the index is out of bounds.
312
+ ///
313
+ /// # Example
314
+ ///
315
+ /// ```
316
+ /// # use implicit_clone::unsync::*;
317
+ /// let mut v = IArray::<u8>::Static(&[1,2,10,3]);
318
+ /// v.remove(2);
319
+ /// assert_eq!(&[1,2,3], v.as_slice());
320
+ /// ```
321
+ pub fn remove ( & mut self , index : usize ) {
322
+ self . remove_range ( index..index + 1 )
323
+ }
163
324
}
164
325
165
326
impl < ' a , T , U , const N : usize > PartialEq < & ' a [ U ; N ] > for IArray < T >
@@ -276,4 +437,11 @@ mod test_array {
276
437
const _ARRAY_F32: IArray < f32 > = IArray :: Static ( & [ ] ) ;
277
438
const _ARRAY_F64: IArray < f64 > = IArray :: Static ( & [ ] ) ;
278
439
}
440
+
441
+ #[ test]
442
+ fn extend ( ) {
443
+ let mut array = [ 1 , 2 , 3 ] . into_iter ( ) . collect :: < IArray < u32 > > ( ) ;
444
+ array. extend ( [ 4 , 5 , 6 ] ) ;
445
+ assert_eq ! ( & [ 1 , 2 , 3 , 4 , 5 , 6 ] , array. as_slice( ) ) ;
446
+ }
279
447
}
0 commit comments