1use super::{EncodedManagedVecItem, ManagedVecItemPayload};
2use crate::{
3 abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName},
4 api::{ErrorApiImpl, InvalidSliceError, ManagedTypeApi},
5 codec::{
6 DecodeErrorHandler, EncodeErrorHandler, IntoMultiValue, NestedDecode, NestedDecodeInput,
7 NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode,
8 TopEncodeMultiOutput, TopEncodeOutput,
9 },
10 types::{
11 ManagedBuffer, ManagedBufferNestedDecodeInput, ManagedType, ManagedVecItem,
12 ManagedVecRefIterator, ManagedVecRefMut, MultiValueEncoded, MultiValueManagedVec,
13 },
14};
15use alloc::{format, vec::Vec};
16use core::{
17 borrow::Borrow,
18 cmp::Ordering,
19 fmt::Debug,
20 iter::FromIterator,
21 marker::PhantomData,
22 mem::{transmute_copy, ManuallyDrop, MaybeUninit},
23};
24
25pub(crate) const INDEX_OUT_OF_RANGE_MSG: &[u8] = b"ManagedVec index out of range";
26
27#[repr(transparent)]
31pub struct ManagedVec<M, T>
32where
33 M: ManagedTypeApi,
34 T: ManagedVecItem,
35{
36 pub(crate) buffer: ManagedBuffer<M>,
37 _phantom: PhantomData<T>,
38}
39
40impl<M, T> ManagedType<M> for ManagedVec<M, T>
41where
42 M: ManagedTypeApi,
43 T: ManagedVecItem,
44{
45 type OwnHandle = M::ManagedBufferHandle;
46
47 #[inline]
48 unsafe fn from_handle(handle: M::ManagedBufferHandle) -> Self {
49 ManagedVec {
50 buffer: ManagedBuffer::from_handle(handle),
51 _phantom: PhantomData,
52 }
53 }
54
55 fn get_handle(&self) -> M::ManagedBufferHandle {
56 self.buffer.get_handle()
57 }
58
59 unsafe fn forget_into_handle(self) -> Self::OwnHandle {
60 self.buffer.forget_into_handle()
61 }
62
63 fn transmute_from_handle_ref(handle_ref: &M::ManagedBufferHandle) -> &Self {
64 unsafe { core::mem::transmute(handle_ref) }
65 }
66
67 fn transmute_from_handle_ref_mut(handle_ref: &mut M::ManagedBufferHandle) -> &mut Self {
68 unsafe { core::mem::transmute(handle_ref) }
69 }
70}
71
72impl<M, T> ManagedVec<M, T>
73where
74 M: ManagedTypeApi,
75 T: ManagedVecItem,
76{
77 #[inline]
78 pub fn new() -> Self {
79 ManagedVec {
80 buffer: ManagedBuffer::new(),
81 _phantom: PhantomData,
82 }
83 }
84
85 #[inline]
86 pub(crate) fn new_from_raw_buffer(buffer: ManagedBuffer<M>) -> Self {
87 ManagedVec {
88 buffer,
89 _phantom: PhantomData,
90 }
91 }
92
93 pub unsafe fn new_uninit() -> Self {
99 ManagedVec {
100 buffer: ManagedBuffer::new_uninit(),
101 _phantom: PhantomData,
102 }
103 }
104}
105
106impl<M, T, I> From<Vec<I>> for ManagedVec<M, T>
107where
108 M: ManagedTypeApi,
109 T: ManagedVecItem,
110 I: Into<T>,
111{
112 fn from(v: Vec<I>) -> Self {
113 let mut result = Self::new();
114 for item in v.into_iter() {
115 result.push(item.into());
116 }
117 result
118 }
119}
120
121impl<M, T> Default for ManagedVec<M, T>
122where
123 M: ManagedTypeApi,
124 T: ManagedVecItem,
125{
126 #[inline]
127 fn default() -> Self {
128 Self::new()
129 }
130}
131
132impl<M, T> ManagedVec<M, T>
133where
134 M: ManagedTypeApi,
135 T: ManagedVecItem,
136{
137 #[inline]
139 pub fn byte_len(&self) -> usize {
140 self.buffer.len()
141 }
142
143 #[inline]
145 pub fn len(&self) -> usize {
146 self.byte_len() / T::payload_size()
147 }
148
149 #[inline]
150 pub fn is_empty(&self) -> bool {
151 self.byte_len() == 0
152 }
153
154 fn load_item_payload(&self, index: usize, payload: &mut T::PAYLOAD) -> bool {
158 let byte_index = index * T::payload_size();
159
160 if byte_index + T::payload_size() > self.byte_len() {
161 return false;
162 }
163
164 self.buffer
165 .load_slice(byte_index, payload.payload_slice_mut());
166
167 true
168 }
169
170 pub fn try_get(&self, index: usize) -> Option<T::Ref<'_>> {
171 let mut payload = T::PAYLOAD::new_buffer();
172 if self.load_item_payload(index, &mut payload) {
173 unsafe { Some(T::borrow_from_payload(&payload)) }
174 } else {
175 None
176 }
177 }
178
179 pub fn to_array_of_refs<const N: usize>(&self) -> Option<[T::Ref<'_>; N]> {
183 if self.len() != N {
184 return None;
185 }
186
187 let mut result_uninit =
188 unsafe { MaybeUninit::<[MaybeUninit<T::Ref<'_>>; N]>::uninit().assume_init() };
189
190 for (index, value) in self.iter().enumerate() {
191 unsafe {
193 result_uninit.get_unchecked_mut(index).write(value);
194 }
195 }
196
197 let result = unsafe { transmute_copy(&ManuallyDrop::new(result_uninit)) };
198 Some(result)
199 }
200
201 pub fn get(&self, index: usize) -> T::Ref<'_> {
204 match self.try_get(index) {
205 Some(result) => result,
206 None => M::error_api_impl().signal_error(INDEX_OUT_OF_RANGE_MSG),
207 }
208 }
209
210 pub fn is_single_item(&self) -> Option<T::Ref<'_>> {
214 let mut payload = T::PAYLOAD::new_buffer();
215 if self.len() == 1 {
216 let _ = self.load_item_payload(0, &mut payload);
217 unsafe { Some(T::borrow_from_payload(&payload)) }
218 } else {
219 None
220 }
221 }
222
223 pub fn get_mut(&mut self, index: usize) -> ManagedVecRefMut<'_, M, T> {
224 ManagedVecRefMut::new(self.get_handle(), index)
225 }
226
227 pub(super) unsafe fn get_unsafe(&self, index: usize) -> T {
228 let mut payload = T::PAYLOAD::new_buffer();
229 if self.load_item_payload(index, &mut payload) {
230 T::read_from_payload(&payload)
231 } else {
232 M::error_api_impl().signal_error(INDEX_OUT_OF_RANGE_MSG);
233 }
234 }
235
236 pub fn set(&mut self, index: usize, item: T) -> Result<(), InvalidSliceError> {
237 let byte_index = index * T::payload_size();
238 let mut payload = T::PAYLOAD::new_buffer();
239 item.save_to_payload(&mut payload);
240 self.buffer.set_slice(byte_index, payload.payload_slice())
241 }
242
243 pub fn slice(&self, start_index: usize, end_index: usize) -> Option<Self> {
246 let byte_start = start_index * T::payload_size();
247 let byte_end = end_index * T::payload_size();
248 let opt_buffer = self.buffer.copy_slice(byte_start, byte_end - byte_start);
249 opt_buffer.map(ManagedVec::new_from_raw_buffer)
250 }
251
252 pub fn push(&mut self, item: T) {
253 let mut payload = T::PAYLOAD::new_buffer();
254 item.save_to_payload(&mut payload);
255 self.buffer.append_bytes(payload.payload_slice());
256 }
257
258 pub fn remove(&mut self, index: usize) {
259 let len = self.len();
260 if index >= len {
261 M::error_api_impl().signal_error(INDEX_OUT_OF_RANGE_MSG);
262 }
263
264 let part_before = if index > 0 {
265 match self.slice(0, index) {
266 Some(s) => s,
267 None => M::error_api_impl().signal_error(INDEX_OUT_OF_RANGE_MSG),
268 }
269 } else {
270 ManagedVec::new()
271 };
272 let part_after = if index < len {
273 match self.slice(index + 1, len) {
274 Some(s) => s,
275 None => M::error_api_impl().signal_error(INDEX_OUT_OF_RANGE_MSG),
276 }
277 } else {
278 ManagedVec::new()
279 };
280
281 *self = part_before;
282 self.buffer.append(&part_after.buffer);
283 }
284
285 pub fn take(&mut self, index: usize) -> T {
286 let item = unsafe { self.get_unsafe(index) };
287 self.remove(index);
288 item
289 }
290
291 pub fn from_single_item(item: T) -> Self {
293 let mut result = ManagedVec::new();
294 result.push(item);
295 result
296 }
297
298 pub fn overwrite_with_single_item(&mut self, item: T) {
299 let mut payload = T::PAYLOAD::new_buffer();
300 item.save_to_payload(&mut payload);
301 self.buffer.overwrite(payload.payload_slice());
302 }
303
304 pub fn append_vec(&mut self, item: ManagedVec<M, T>) {
307 self.buffer.append(&item.buffer);
308 }
309
310 pub fn clear(&mut self) {
312 self.buffer.overwrite(&[]);
313 }
314
315 #[cfg(feature = "alloc")]
316 pub fn into_vec(self) -> Vec<T> {
317 let mut v = Vec::new();
318 for item in self.into_iter() {
319 v.push(item);
320 }
321 v
322 }
323
324 #[cfg(feature = "alloc")]
327 pub fn with_self_as_vec<R, F>(&mut self, f: F) -> R
328 where
329 F: FnOnce(&mut Vec<T>) -> R,
330 {
331 let new = ManagedVec::new();
332 let old = core::mem::replace(self, new);
333 let mut temp_vec = Vec::new();
334 for item in old.into_iter() {
335 temp_vec.push(item);
336 }
337 let result = f(&mut temp_vec);
338 for new_item in temp_vec {
339 self.push(new_item);
340 }
341 result
342 }
343
344 pub fn iter(&self) -> ManagedVecRefIterator<'_, M, T> {
345 ManagedVecRefIterator::new(self)
346 }
347
348 pub fn as_multi(&self) -> &MultiValueManagedVec<M, T> {
350 MultiValueManagedVec::transmute_from_handle_ref(&self.buffer.handle)
351 }
352}
353
354impl<M, T> ManagedVec<M, T>
355where
356 M: ManagedTypeApi,
357 T: ManagedVecItem + Debug,
358{
359 fn with_self_as_slice<R, F>(&self, f: F) -> R
360 where
361 F: FnOnce(&[EncodedManagedVecItem<T>]) -> R,
362 {
363 self.buffer.with_buffer_contents(|bytes| {
364 let item_len = bytes.len() / T::payload_size();
365 let values = Self::transmute_slice(bytes, item_len);
366 f(values)
367 })
368 }
369
370 fn with_self_as_slice_mut<F>(&mut self, f: F)
371 where
372 F: FnOnce(&mut [EncodedManagedVecItem<T>]) -> &[EncodedManagedVecItem<T>],
373 {
374 self.buffer.with_buffer_contents_mut(|bytes| {
375 let item_len = bytes.len() / T::payload_size();
376 let values = Self::transmute_slice_mut(bytes, item_len);
377
378 let result = f(values);
379 let result_len = result.len() * T::payload_size();
380 Self::transmute_slice(result, result_len)
381 });
382 }
383
384 fn transmute_slice<T1, T2>(from: &[T1], len: usize) -> &[T2] {
385 unsafe {
386 let ptr = from.as_ptr() as *const T2;
387 core::slice::from_raw_parts(ptr, len)
388 }
389 }
390
391 fn transmute_slice_mut<T1, T2>(from: &mut [T1], len: usize) -> &mut [T2] {
392 unsafe {
393 let ptr = from.as_mut_ptr() as *mut T2;
394 core::slice::from_raw_parts_mut(ptr, len)
395 }
396 }
397}
398
399impl<M, T> ManagedVec<M, T>
400where
401 M: ManagedTypeApi,
402 T: ManagedVecItem + Ord + Debug,
403{
404 #[deprecated(since = "0.54.5", note = "Please use method `sort_unstable` instead.")]
405 #[cfg(feature = "alloc")]
406 pub fn sort(&mut self) {
407 self.with_self_as_slice_mut(|slice| {
408 slice.sort();
409 slice
410 });
411 }
412
413 #[deprecated(
414 since = "0.54.5",
415 note = "Please use method `sort_unstable_by` instead."
416 )]
417 #[cfg(feature = "alloc")]
418 pub fn sort_by<F>(&mut self, mut compare: F)
419 where
420 F: FnMut(&T, &T) -> Ordering,
421 {
422 self.with_self_as_slice_mut(|slice| {
423 slice.sort_by(|a, b| compare(&a.decode(), &b.decode()));
424 slice
425 });
426 }
427
428 #[deprecated(
429 since = "0.54.5",
430 note = "Please use method `sort_unstable_by_key` instead."
431 )]
432 #[cfg(feature = "alloc")]
433 pub fn sort_by_key<K, F>(&mut self, mut f: F)
434 where
435 F: FnMut(&T) -> K,
436 K: Ord,
437 {
438 self.with_self_as_slice_mut(|slice| {
439 slice.sort_by_key(|a| f(&a.decode()));
440 slice
441 });
442 }
443
444 #[deprecated]
445 #[cfg(feature = "alloc")]
446 pub fn sort_by_cached_key<K, F>(&mut self, mut f: F)
447 where
448 F: FnMut(&T) -> K,
449 K: Ord,
450 {
451 self.with_self_as_slice_mut(|slice| {
452 slice.sort_by_cached_key(|a| f(&a.decode()));
453 slice
454 });
455 }
456
457 pub fn sort_unstable(&mut self) {
458 self.with_self_as_slice_mut(|slice| {
459 slice.sort_unstable();
460 slice
461 })
462 }
463
464 pub fn sort_unstable_by<F>(&mut self, mut compare: F)
465 where
466 F: FnMut(&T, &T) -> Ordering,
467 {
468 self.with_self_as_slice_mut(|slice| {
469 slice.sort_unstable_by(|a, b| compare(&a.decode(), &b.decode()));
470 slice
471 })
472 }
473
474 pub fn sort_unstable_by_key<K, F>(&mut self, mut f: F)
475 where
476 F: FnMut(&T) -> K,
477 K: Ord,
478 {
479 self.with_self_as_slice_mut(|slice| {
480 slice.sort_unstable_by_key(|a| f(&a.decode()));
481 slice
482 })
483 }
484
485 pub fn is_sorted(&self) -> bool {
486 self.with_self_as_slice(|slice| {
487 let mut slice_iter = slice.iter();
488 #[inline]
489 fn check<'a, T>(
490 last: &'a mut T,
491 mut compare: impl FnMut(&T, &T) -> Option<Ordering> + 'a,
492 ) -> impl FnMut(T) -> bool + 'a {
493 move |curr| {
494 if let Some(Ordering::Greater) | None = compare(last, &curr) {
495 return false;
496 }
497 *last = curr;
498 true
499 }
500 }
501
502 let mut last = match slice_iter.next() {
503 Some(e) => e,
504 None => return true,
505 };
506
507 slice_iter.all(check(&mut last, PartialOrd::partial_cmp))
508 })
509 }
510}
511
512impl<M, T> ManagedVec<M, T>
513where
514 M: ManagedTypeApi,
515 T: ManagedVecItem + PartialEq + Debug,
516{
517 pub fn dedup(&mut self) {
518 self.with_self_as_slice_mut(|slice| {
519 let same_bucket = |a, b| a == b;
520 let len = slice.len();
521 if len <= 1 {
522 return slice;
523 }
524
525 let ptr = slice.as_mut_ptr();
526 let mut next_read: usize = 1;
527 let mut next_write: usize = 1;
528 unsafe {
529 while next_read < len {
531 let ptr_read = ptr.add(next_read);
532 let prev_ptr_write = ptr.add(next_write - 1);
533 if !same_bucket(&mut *ptr_read, &mut *prev_ptr_write) {
534 if next_read != next_write {
535 let ptr_write = prev_ptr_write.add(1);
536 core::ptr::swap(ptr_read, ptr_write);
537 }
538 next_write += 1;
539 }
540 next_read += 1;
541 }
542 }
543
544 let (dedup, _) = slice.split_at_mut(next_write);
545 dedup
546 })
547 }
548}
549
550impl<M, T> Clone for ManagedVec<M, T>
551where
552 M: ManagedTypeApi,
553 T: ManagedVecItem + Clone,
554{
555 fn clone(&self) -> Self {
556 let mut result = ManagedVec::new();
557 for item in self.into_iter() {
558 result.push(item.borrow().clone())
559 }
560 result
561 }
562}
563
564impl<M, T> PartialEq for ManagedVec<M, T>
565where
566 M: ManagedTypeApi,
567 T: ManagedVecItem + PartialEq,
568{
569 #[inline]
570 fn eq(&self, other: &Self) -> bool {
571 if self.buffer == other.buffer {
572 return true;
573 }
574 let self_len = self.buffer.byte_len();
575 let other_len = other.buffer.byte_len();
576 if self_len != other_len {
577 return false;
578 }
579 let mut byte_index = 0;
580 while byte_index < self_len {
581 let mut self_payload = T::PAYLOAD::new_buffer();
582 self.buffer
583 .load_slice(byte_index, self_payload.payload_slice_mut());
584 let mut other_payload = T::PAYLOAD::new_buffer();
585 other
586 .buffer
587 .load_slice(byte_index, other_payload.payload_slice_mut());
588 let self_item = T::read_from_payload(&self_payload);
589 let other_item = T::read_from_payload(&other_payload);
590 if self_item != other_item {
591 return false;
592 }
593 byte_index += T::payload_size();
594 }
595 true
596 }
597}
598
599impl<M, T> Eq for ManagedVec<M, T>
600where
601 M: ManagedTypeApi,
602 T: ManagedVecItem + PartialEq,
603{
604}
605
606impl<M, T> ManagedVec<M, T>
607where
608 M: ManagedTypeApi,
609 T: ManagedVecItem + PartialEq,
610{
611 pub fn find(&self, item: &T) -> Option<usize> {
614 for (i, item_in_vec) in self.iter().enumerate() {
615 if item_in_vec.borrow() == item {
616 return Some(i);
617 }
618 }
619
620 None
621 }
622
623 #[inline]
626 pub fn contains(&self, item: &T) -> bool {
627 self.find(item).is_some()
628 }
629}
630
631impl<M, T> TopEncode for ManagedVec<M, T>
632where
633 M: ManagedTypeApi,
634 T: ManagedVecItem + NestedEncode,
635{
636 #[inline]
637 fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
638 where
639 O: TopEncodeOutput,
640 H: EncodeErrorHandler,
641 {
642 if T::SKIPS_RESERIALIZATION {
643 self.buffer.top_encode_or_handle_err(output, h)
644 } else {
645 let mut nested_buffer = output.start_nested_encode();
646 for item in self {
647 item.borrow()
648 .dep_encode_or_handle_err(&mut nested_buffer, h)?;
649 }
650 output.finalize_nested_encode(nested_buffer);
651 Ok(())
652 }
653 }
654}
655
656impl<M, T> NestedEncode for ManagedVec<M, T>
657where
658 M: ManagedTypeApi,
659 T: ManagedVecItem + NestedEncode,
660{
661 fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
662 where
663 O: NestedEncodeOutput,
664 H: EncodeErrorHandler,
665 {
666 self.len().dep_encode_or_handle_err(dest, h)?;
667 for item in self {
668 item.borrow().dep_encode_or_handle_err(dest, h)?;
669 }
670 Ok(())
671 }
672}
673
674impl<M, T> TopDecode for ManagedVec<M, T>
675where
676 M: ManagedTypeApi,
677 T: ManagedVecItem + NestedDecode,
678{
679 fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
680 where
681 I: TopDecodeInput,
682 H: DecodeErrorHandler,
683 {
684 let buffer = ManagedBuffer::top_decode_or_handle_err(input, h)?;
685 if T::SKIPS_RESERIALIZATION {
686 Ok(ManagedVec::new_from_raw_buffer(buffer))
687 } else {
688 let mut result = ManagedVec::new();
689 let mut nested_de_input = ManagedBufferNestedDecodeInput::new(buffer);
690 while nested_de_input.remaining_len() > 0 {
691 result.push(T::dep_decode_or_handle_err(&mut nested_de_input, h)?);
692 }
693 Ok(result)
694 }
695 }
696}
697
698impl<M, T> NestedDecode for ManagedVec<M, T>
699where
700 M: ManagedTypeApi,
701 T: ManagedVecItem + NestedDecode,
702{
703 fn dep_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
704 where
705 I: NestedDecodeInput,
706 H: DecodeErrorHandler,
707 {
708 let size = usize::dep_decode_or_handle_err(input, h)?;
709 let mut result = ManagedVec::new();
710 for _ in 0..size {
711 result.push(T::dep_decode_or_handle_err(input, h)?);
712 }
713 Ok(result)
714 }
715}
716
717impl<M, T> IntoMultiValue for ManagedVec<M, T>
718where
719 M: ManagedTypeApi,
720 T: ManagedVecItem + IntoMultiValue,
721{
722 type MultiValue = MultiValueEncoded<M, T::MultiValue>;
723
724 fn into_multi_value(self) -> Self::MultiValue {
725 let mut result = MultiValueEncoded::new();
726 for item in self.into_iter() {
727 result.push(item.into_multi_value());
728 }
729 result
730 }
731}
732
733impl<M, T, U> TypeAbiFrom<ManagedVec<M, U>> for ManagedVec<M, T>
734where
735 M: ManagedTypeApi,
736 U: ManagedVecItem,
737 T: ManagedVecItem + TypeAbiFrom<U>,
738{
739}
740
741impl<M, T, U> TypeAbiFrom<Vec<U>> for ManagedVec<M, T>
742where
743 M: ManagedTypeApi,
744 T: ManagedVecItem + TypeAbiFrom<U>,
745{
746}
747
748impl<M, T, U> TypeAbiFrom<ManagedVec<M, U>> for Vec<T>
749where
750 M: ManagedTypeApi,
751 U: ManagedVecItem,
752 T: TypeAbiFrom<U>,
753{
754}
755
756impl<M, T> TypeAbi for ManagedVec<M, T>
757where
758 M: ManagedTypeApi,
759 T: ManagedVecItem + TypeAbi,
760{
761 type Unmanaged = Vec<T::Unmanaged>;
762
763 fn type_name() -> TypeName {
765 <&[T] as TypeAbi>::type_name()
766 }
767
768 fn type_name_rust() -> TypeName {
769 format!("ManagedVec<$API, {}>", T::type_name_rust())
770 }
771
772 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
773 T::provide_type_descriptions(accumulator);
774 }
775}
776
777impl<M, T> core::fmt::Debug for ManagedVec<M, T>
778where
779 M: ManagedTypeApi,
780 T: ManagedVecItem + core::fmt::Debug + Clone,
781{
782 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
783 let mut dbg_list = f.debug_list();
784 for item in self.into_iter() {
785 dbg_list.entry(item.borrow());
786 }
787 dbg_list.finish()
788 }
789}
790
791impl<M> TopEncodeMultiOutput for ManagedVec<M, ManagedBuffer<M>>
792where
793 M: ManagedTypeApi,
794{
795 fn push_single_value<T, H>(&mut self, arg: &T, h: H) -> Result<(), H::HandledErr>
796 where
797 T: TopEncode,
798 H: EncodeErrorHandler,
799 {
800 let mut result = ManagedBuffer::new();
801 arg.top_encode_or_handle_err(&mut result, h)?;
802 self.push(result);
803 Ok(())
804 }
805}
806
807impl<M, V> FromIterator<V> for ManagedVec<M, V>
808where
809 M: ManagedTypeApi,
810 V: ManagedVecItem,
811{
812 fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
813 let mut result: ManagedVec<M, V> = ManagedVec::new();
814 iter.into_iter().for_each(|f| result.push(f));
815 result
816 }
817}
818
819impl<M, V> Extend<V> for ManagedVec<M, V>
820where
821 M: ManagedTypeApi,
822 V: ManagedVecItem,
823{
824 fn extend<T: IntoIterator<Item = V>>(&mut self, iter: T) {
825 for elem in iter {
826 self.push(elem);
827 }
828 }
829}