1use std::collections::{HashMap, HashSet};
7use std::hash::Hash;
8use std::marker::PhantomData;
9
10use rusteal_ffi::{FPropertyHandle, UObjectHandle, RustealErrorCode};
11
12const MAX_ELEM_BUF: usize = 4096;
16
17use crate::error::{check_ffi, ffi_infallible, RustealError, RustealResult};
18use crate::ffi_dispatch;
19use crate::object_ref::UObjectRef;
20use crate::struct_ref::UStructRef;
21use crate::traits::{UeClass, UeStruct};
22
23pub unsafe trait ContainerElement: Sized {
35 const BUF_SIZE: u32;
38
39 const RAW_COPYABLE: bool = false;
42
43 unsafe fn read_from_buf(buf: *const u8, written: u32) -> Self;
49
50 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32;
56}
57
58macro_rules! impl_container_element_primitive {
63 ($ty:ty) => {
64 unsafe impl ContainerElement for $ty {
65 const BUF_SIZE: u32 = std::mem::size_of::<$ty>() as u32;
66 const RAW_COPYABLE: bool = true;
67
68 #[inline]
69 unsafe fn read_from_buf(buf: *const u8, _written: u32) -> Self { unsafe {
70 (buf as *const $ty).read_unaligned()
71 }}
72
73 #[inline]
74 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 { unsafe {
75 (buf as *mut $ty).write_unaligned(*self);
76 std::mem::size_of::<$ty>() as u32
77 }}
78 }
79 };
80}
81
82impl_container_element_primitive!(bool);
83impl_container_element_primitive!(i8);
84impl_container_element_primitive!(u8);
85impl_container_element_primitive!(i16);
86impl_container_element_primitive!(u16);
87impl_container_element_primitive!(i32);
88impl_container_element_primitive!(u32);
89impl_container_element_primitive!(i64);
90impl_container_element_primitive!(u64);
91impl_container_element_primitive!(f32);
92impl_container_element_primitive!(f64);
93
94unsafe impl ContainerElement for UObjectHandle {
96 const BUF_SIZE: u32 = std::mem::size_of::<UObjectHandle>() as u32;
97
98 #[inline]
99 unsafe fn read_from_buf(buf: *const u8, _written: u32) -> Self { unsafe {
100 (buf as *const UObjectHandle).read_unaligned()
101 }}
102
103 #[inline]
104 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 { unsafe {
105 (buf as *mut UObjectHandle).write_unaligned(*self);
106 std::mem::size_of::<UObjectHandle>() as u32
107 }}
108}
109
110unsafe impl ContainerElement for rusteal_ffi::FNameHandle {
112 const BUF_SIZE: u32 = 8;
113 const RAW_COPYABLE: bool = true;
114
115 #[inline]
116 unsafe fn read_from_buf(buf: *const u8, _written: u32) -> Self { unsafe {
117 (buf as *const rusteal_ffi::FNameHandle).read_unaligned()
118 }}
119
120 #[inline]
121 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 { unsafe {
122 (buf as *mut rusteal_ffi::FNameHandle).write_unaligned(*self);
123 8
124 }}
125}
126
127unsafe impl<T: UeClass> ContainerElement for UObjectRef<T> {
129 const BUF_SIZE: u32 = std::mem::size_of::<UObjectHandle>() as u32;
130
131 #[inline]
132 unsafe fn read_from_buf(buf: *const u8, _written: u32) -> Self { unsafe {
133 let handle = (buf as *const UObjectHandle).read_unaligned();
134 UObjectRef::from_raw(handle)
135 }}
136
137 #[inline]
138 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 { unsafe {
139 (buf as *mut UObjectHandle).write_unaligned(self.raw());
140 std::mem::size_of::<UObjectHandle>() as u32
141 }}
142}
143
144unsafe impl ContainerElement for String {
146 const BUF_SIZE: u32 = 4096;
148
149 unsafe fn read_from_buf(buf: *const u8, written: u32) -> Self { unsafe {
150 if written < 4 {
151 return String::new();
152 }
153 let len = (buf as *const u32).read_unaligned() as usize;
154 let data_len = (written as usize).saturating_sub(4).min(len);
155 let slice = std::slice::from_raw_parts(buf.add(4), data_len);
156 String::from_utf8_lossy(slice).into_owned()
157 }}
158
159 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 { unsafe {
160 let bytes = self.as_bytes();
161 let len = bytes.len() as u32;
162 (buf as *mut u32).write_unaligned(len);
163 std::ptr::copy_nonoverlapping(bytes.as_ptr(), buf.add(4), bytes.len());
164 4 + len
165 }}
166}
167
168#[derive(Clone, Copy)]
177pub struct UeArray<T: ContainerElement> {
178 owner: UObjectHandle,
179 prop: FPropertyHandle,
180 _marker: PhantomData<T>,
181}
182
183impl<T: ContainerElement> UeArray<T> {
184 #[inline]
186 pub fn new(owner: UObjectHandle, prop: FPropertyHandle) -> Self {
187 UeArray {
188 owner,
189 prop,
190 _marker: PhantomData,
191 }
192 }
193
194 pub fn len(&self) -> RustealResult<usize> {
196 let n = unsafe { ffi_dispatch::container_array_len(self.owner, self.prop) };
197 if n < 0 {
198 return Err(RustealError::ObjectDestroyed);
199 }
200 Ok(n as usize)
201 }
202
203 pub fn is_empty(&self) -> RustealResult<bool> {
205 Ok(self.len()? == 0)
206 }
207
208 pub fn get(&self, index: usize) -> RustealResult<T> {
210 let mut buf = [0u8; MAX_ELEM_BUF];
211 let mut written: u32 = 0;
212 check_ffi(unsafe {
213 ffi_dispatch::container_array_get(
214 self.owner,
215 self.prop,
216 index as i32,
217 buf.as_mut_ptr(),
218 T::BUF_SIZE,
219 &mut written,
220 )
221 })?;
222 Ok(unsafe { T::read_from_buf(buf.as_ptr(), written) })
223 }
224
225 pub fn set(&self, index: usize, val: &T) -> RustealResult<()> {
227 let mut buf = [0u8; MAX_ELEM_BUF];
228 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
230 check_ffi(unsafe {
231 ffi_dispatch::container_array_set(
232 self.owner,
233 self.prop,
234 index as i32,
235 buf.as_ptr(),
236 written,
237 )
238 })
239 }
240
241 pub fn push(&self, val: &T) -> RustealResult<()> {
243 let mut buf = [0u8; MAX_ELEM_BUF];
244 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
246 check_ffi(unsafe {
247 ffi_dispatch::container_array_add(self.owner, self.prop, buf.as_ptr(), written)
248 })
249 }
250
251 pub fn remove(&self, index: usize) -> RustealResult<()> {
253 check_ffi(unsafe {
254 ffi_dispatch::container_array_remove(self.owner, self.prop, index as i32)
255 })
256 }
257
258 pub fn clear(&self) -> RustealResult<()> {
260 check_ffi(unsafe { ffi_dispatch::container_array_clear(self.owner, self.prop) })
261 }
262
263 pub fn iter(&self) -> UeArrayIter<'_, T> {
265 let len = self.len().unwrap_or(0);
266 UeArrayIter {
267 array: self,
268 index: 0,
269 len,
270 }
271 }
272}
273
274impl<'a, T: ContainerElement> IntoIterator for &'a UeArray<T> {
275 type Item = RustealResult<T>;
276 type IntoIter = UeArrayIter<'a, T>;
277
278 fn into_iter(self) -> Self::IntoIter {
279 self.iter()
280 }
281}
282
283pub struct UeArrayIter<'a, T: ContainerElement> {
285 array: &'a UeArray<T>,
286 index: usize,
287 len: usize,
288}
289
290impl<T: ContainerElement> Iterator for UeArrayIter<'_, T> {
291 type Item = RustealResult<T>;
292
293 fn next(&mut self) -> Option<Self::Item> {
294 if self.index >= self.len {
295 return None;
296 }
297 let result = self.array.get(self.index);
298 self.index += 1;
299 Some(result)
300 }
301
302 fn size_hint(&self) -> (usize, Option<usize>) {
303 let remaining = self.len.saturating_sub(self.index);
304 (remaining, Some(remaining))
305 }
306}
307
308impl<T: ContainerElement> ExactSizeIterator for UeArrayIter<'_, T> {}
309
310fn bulk_copy_with_retry(
316 estimate: usize,
317 call: impl Fn(*mut u8, u32, *mut u32, *mut i32) -> RustealErrorCode,
318) -> RustealResult<(Vec<u8>, i32)> {
319 let mut buf = vec![0u8; estimate.max(64)];
320 let mut written: u32 = 0;
321 let mut count: i32 = 0;
322 let code = call(buf.as_mut_ptr(), buf.len() as u32, &mut written, &mut count);
323 if code == RustealErrorCode::BufferTooSmall {
324 let needed = (written as usize).max(buf.len() * 2);
326 buf.resize(needed, 0);
327 check_ffi(call(
328 buf.as_mut_ptr(),
329 buf.len() as u32,
330 &mut written,
331 &mut count,
332 ))?;
333 } else {
334 check_ffi(code)?;
335 }
336 buf.truncate(written as usize);
337 Ok((buf, count))
338}
339
340pub struct BulkArrayIter<T: ContainerElement> {
351 buf: Vec<u8>,
352 count: usize,
353 index: usize,
354 offset: usize,
355 raw_elem_size: usize, _marker: PhantomData<T>,
357}
358
359impl<T: ContainerElement> Iterator for BulkArrayIter<T> {
360 type Item = T;
361
362 fn next(&mut self) -> Option<T> {
363 if self.index >= self.count {
364 return None;
365 }
366 if self.raw_elem_size > 0 {
367 let elem = unsafe {
369 T::read_from_buf(
370 self.buf.as_ptr().add(self.offset),
371 self.raw_elem_size as u32,
372 )
373 };
374 self.offset += self.raw_elem_size;
375 self.index += 1;
376 Some(elem)
377 } else {
378 if self.offset + 4 > self.buf.len() {
380 return None;
381 }
382 let written = u32::from_ne_bytes(
383 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
384 );
385 self.offset += 4;
386 let elem =
387 unsafe { T::read_from_buf(self.buf.as_ptr().add(self.offset), written) };
388 self.offset += written as usize;
389 self.index += 1;
390 Some(elem)
391 }
392 }
393
394 fn size_hint(&self) -> (usize, Option<usize>) {
395 let r = self.count - self.index;
396 (r, Some(r))
397 }
398}
399
400impl<T: ContainerElement> ExactSizeIterator for BulkArrayIter<T> {}
401
402pub struct BulkMapIter<K: ContainerElement, V: ContainerElement> {
404 buf: Vec<u8>,
405 count: usize,
406 index: usize,
407 offset: usize,
408 _marker: PhantomData<(K, V)>,
409}
410
411impl<K: ContainerElement, V: ContainerElement> Iterator for BulkMapIter<K, V> {
412 type Item = (K, V);
413
414 fn next(&mut self) -> Option<(K, V)> {
415 if self.index >= self.count {
416 return None;
417 }
418 if self.offset + 4 > self.buf.len() {
420 return None;
421 }
422 let key_written = u32::from_ne_bytes(
423 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
424 );
425 self.offset += 4;
426 let key =
427 unsafe { K::read_from_buf(self.buf.as_ptr().add(self.offset), key_written) };
428 self.offset += key_written as usize;
429
430 if self.offset + 4 > self.buf.len() {
432 return None;
433 }
434 let val_written = u32::from_ne_bytes(
435 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
436 );
437 self.offset += 4;
438 let val =
439 unsafe { V::read_from_buf(self.buf.as_ptr().add(self.offset), val_written) };
440 self.offset += val_written as usize;
441
442 self.index += 1;
443 Some((key, val))
444 }
445
446 fn size_hint(&self) -> (usize, Option<usize>) {
447 let r = self.count - self.index;
448 (r, Some(r))
449 }
450}
451
452impl<K: ContainerElement, V: ContainerElement> ExactSizeIterator for BulkMapIter<K, V> {}
453
454pub struct BulkSetIter<T: ContainerElement> {
456 buf: Vec<u8>,
457 count: usize,
458 index: usize,
459 offset: usize,
460 _marker: PhantomData<T>,
461}
462
463impl<T: ContainerElement> Iterator for BulkSetIter<T> {
464 type Item = T;
465
466 fn next(&mut self) -> Option<T> {
467 if self.index >= self.count {
468 return None;
469 }
470 if self.offset + 4 > self.buf.len() {
471 return None;
472 }
473 let written = u32::from_ne_bytes(
474 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
475 );
476 self.offset += 4;
477 let elem = unsafe { T::read_from_buf(self.buf.as_ptr().add(self.offset), written) };
478 self.offset += written as usize;
479 self.index += 1;
480 Some(elem)
481 }
482
483 fn size_hint(&self) -> (usize, Option<usize>) {
484 let r = self.count - self.index;
485 (r, Some(r))
486 }
487}
488
489impl<T: ContainerElement> ExactSizeIterator for BulkSetIter<T> {}
490
491impl<T: ContainerElement> UeArray<T> {
496 pub fn to_vec(&self) -> RustealResult<Vec<T>> {
498 let len = self.len()?;
499 if len == 0 {
500 return Ok(Vec::new());
501 }
502 let owner = self.owner;
503 let prop = self.prop;
504 let estimate = if T::RAW_COPYABLE {
506 len * T::BUF_SIZE as usize
507 } else {
508 len * (T::BUF_SIZE as usize + 4)
509 };
510 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
511 ffi_dispatch::container_array_copy_all(owner, prop, out, size, written, cnt)
512 })?;
513 let (actual_count, raw_elem_size) = if count < 0 {
515 ((-count) as usize, T::BUF_SIZE as usize)
516 } else {
517 (count as usize, 0)
518 };
519 Ok(BulkArrayIter::<T> {
520 buf,
521 count: actual_count,
522 index: 0,
523 offset: 0,
524 raw_elem_size,
525 _marker: PhantomData,
526 }
527 .collect())
528 }
529
530 pub fn bulk_iter(&self) -> RustealResult<BulkArrayIter<T>> {
532 let len = self.len()?;
533 if len == 0 {
534 return Ok(BulkArrayIter {
535 buf: Vec::new(),
536 count: 0,
537 index: 0,
538 offset: 0,
539 raw_elem_size: 0,
540 _marker: PhantomData,
541 });
542 }
543 let owner = self.owner;
544 let prop = self.prop;
545 let estimate = if T::RAW_COPYABLE {
546 len * T::BUF_SIZE as usize
547 } else {
548 len * (T::BUF_SIZE as usize + 4)
549 };
550 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
551 ffi_dispatch::container_array_copy_all(owner, prop, out, size, written, cnt)
552 })?;
553 let (actual_count, raw_elem_size) = if count < 0 {
554 ((-count) as usize, T::BUF_SIZE as usize)
555 } else {
556 (count as usize, 0)
557 };
558 Ok(BulkArrayIter {
559 buf,
560 count: actual_count,
561 index: 0,
562 offset: 0,
563 raw_elem_size,
564 _marker: PhantomData,
565 })
566 }
567
568 pub fn set_all(&self, items: &[T]) -> RustealResult<()> {
570 if items.is_empty() {
571 return self.clear();
572 }
573 if T::RAW_COPYABLE {
574 let elem_size = T::BUF_SIZE as usize;
576 let mut buf = vec![0u8; items.len() * elem_size];
577 for (i, item) in items.iter().enumerate() {
578 unsafe { item.write_to_buf(buf.as_mut_ptr().add(i * elem_size)); }
579 }
580 check_ffi(unsafe {
582 ffi_dispatch::container_array_set_all(
583 self.owner,
584 self.prop,
585 buf.as_ptr(),
586 buf.len() as u32,
587 -(items.len() as i32),
588 )
589 })
590 } else {
591 let mut buf = Vec::with_capacity(items.len() * (T::BUF_SIZE as usize + 4));
593 let mut elem_buf = [0u8; MAX_ELEM_BUF];
594 for item in items {
595 let written = unsafe { item.write_to_buf(elem_buf.as_mut_ptr()) };
596 buf.extend_from_slice(&written.to_ne_bytes());
597 buf.extend_from_slice(&elem_buf[..written as usize]);
598 }
599 check_ffi(unsafe {
600 ffi_dispatch::container_array_set_all(
601 self.owner,
602 self.prop,
603 buf.as_ptr(),
604 buf.len() as u32,
605 items.len() as i32,
606 )
607 })
608 }
609 }
610}
611
612#[derive(Clone, Copy)]
618pub struct UeMap<K: ContainerElement, V: ContainerElement> {
619 owner: UObjectHandle,
620 prop: FPropertyHandle,
621 _marker: PhantomData<(K, V)>,
622}
623
624impl<K: ContainerElement, V: ContainerElement> UeMap<K, V> {
625 #[inline]
626 pub fn new(owner: UObjectHandle, prop: FPropertyHandle) -> Self {
627 UeMap {
628 owner,
629 prop,
630 _marker: PhantomData,
631 }
632 }
633
634 pub fn len(&self) -> RustealResult<usize> {
636 let n = unsafe { ffi_dispatch::container_map_len(self.owner, self.prop) };
637 if n < 0 {
638 return Err(RustealError::ObjectDestroyed);
639 }
640 Ok(n as usize)
641 }
642
643 pub fn is_empty(&self) -> RustealResult<bool> {
644 Ok(self.len()? == 0)
645 }
646
647 pub fn find(&self, key: &K) -> RustealResult<V> {
650 let mut key_buf = [0u8; MAX_ELEM_BUF];
651 let key_written = unsafe { key.write_to_buf(key_buf.as_mut_ptr()) };
652 let mut val_buf = [0u8; MAX_ELEM_BUF];
653 let mut val_written: u32 = 0;
654
655 check_ffi(unsafe {
656 ffi_dispatch::container_map_find(
657 self.owner,
658 self.prop,
659 key_buf.as_ptr(),
660 key_written,
661 val_buf.as_mut_ptr(),
662 V::BUF_SIZE,
663 &mut val_written,
664 )
665 })?;
666 Ok(unsafe { V::read_from_buf(val_buf.as_ptr(), val_written) })
667 }
668
669 pub fn add(&self, key: &K, val: &V) -> RustealResult<()> {
671 let mut key_buf = [0u8; MAX_ELEM_BUF];
672 let key_written = unsafe { key.write_to_buf(key_buf.as_mut_ptr()) };
673 let mut val_buf = [0u8; MAX_ELEM_BUF];
674 let val_written = unsafe { val.write_to_buf(val_buf.as_mut_ptr()) };
675
676 check_ffi(unsafe {
677 ffi_dispatch::container_map_add(
678 self.owner,
679 self.prop,
680 key_buf.as_ptr(),
681 key_written,
682 val_buf.as_ptr(),
683 val_written,
684 )
685 })
686 }
687
688 pub fn remove(&self, key: &K) -> RustealResult<()> {
690 let mut key_buf = [0u8; MAX_ELEM_BUF];
691 let key_written = unsafe { key.write_to_buf(key_buf.as_mut_ptr()) };
692
693 check_ffi(unsafe {
694 ffi_dispatch::container_map_remove(
695 self.owner,
696 self.prop,
697 key_buf.as_ptr(),
698 key_written,
699 )
700 })
701 }
702
703 pub fn clear(&self) -> RustealResult<()> {
705 check_ffi(unsafe { ffi_dispatch::container_map_clear(self.owner, self.prop) })
706 }
707
708 pub fn get_pair(&self, logical_index: usize) -> RustealResult<(K, V)> {
710 let mut key_buf = [0u8; MAX_ELEM_BUF];
711 let mut key_written: u32 = 0;
712 let mut val_buf = [0u8; MAX_ELEM_BUF];
713 let mut val_written: u32 = 0;
714
715 check_ffi(unsafe {
716 ffi_dispatch::container_map_get_pair(
717 self.owner,
718 self.prop,
719 logical_index as i32,
720 key_buf.as_mut_ptr(),
721 K::BUF_SIZE,
722 &mut key_written,
723 val_buf.as_mut_ptr(),
724 V::BUF_SIZE,
725 &mut val_written,
726 )
727 })?;
728 Ok(unsafe {
729 (
730 K::read_from_buf(key_buf.as_ptr(), key_written),
731 V::read_from_buf(val_buf.as_ptr(), val_written),
732 )
733 })
734 }
735
736 pub fn iter(&self) -> UeMapIter<'_, K, V> {
738 let len = self.len().unwrap_or(0);
739 UeMapIter {
740 map: self,
741 index: 0,
742 len,
743 }
744 }
745}
746
747impl<'a, K: ContainerElement, V: ContainerElement> IntoIterator for &'a UeMap<K, V> {
748 type Item = RustealResult<(K, V)>;
749 type IntoIter = UeMapIter<'a, K, V>;
750
751 fn into_iter(self) -> Self::IntoIter {
752 self.iter()
753 }
754}
755
756pub struct UeMapIter<'a, K: ContainerElement, V: ContainerElement> {
758 map: &'a UeMap<K, V>,
759 index: usize,
760 len: usize,
761}
762
763impl<K: ContainerElement, V: ContainerElement> Iterator for UeMapIter<'_, K, V> {
764 type Item = RustealResult<(K, V)>;
765
766 fn next(&mut self) -> Option<Self::Item> {
767 if self.index >= self.len {
768 return None;
769 }
770 let result = self.map.get_pair(self.index);
771 self.index += 1;
772 Some(result)
773 }
774
775 fn size_hint(&self) -> (usize, Option<usize>) {
776 let remaining = self.len.saturating_sub(self.index);
777 (remaining, Some(remaining))
778 }
779}
780
781impl<K: ContainerElement, V: ContainerElement> ExactSizeIterator for UeMapIter<'_, K, V> {}
782
783impl<K: ContainerElement, V: ContainerElement> UeMap<K, V> {
788 pub fn bulk_iter(&self) -> RustealResult<BulkMapIter<K, V>> {
790 let len = self.len()?;
791 if len == 0 {
792 return Ok(BulkMapIter {
793 buf: Vec::new(),
794 count: 0,
795 index: 0,
796 offset: 0,
797 _marker: PhantomData,
798 });
799 }
800 let owner = self.owner;
801 let prop = self.prop;
802 let estimate = len * (K::BUF_SIZE as usize + V::BUF_SIZE as usize + 8);
803 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
804 ffi_dispatch::container_map_copy_all(owner, prop, out, size, written, cnt)
805 })?;
806 Ok(BulkMapIter {
807 buf,
808 count: count as usize,
809 index: 0,
810 offset: 0,
811 _marker: PhantomData,
812 })
813 }
814}
815
816impl<K: ContainerElement + Hash + Eq, V: ContainerElement> UeMap<K, V> {
817 pub fn to_hash_map(&self) -> RustealResult<HashMap<K, V>> {
819 let iter = self.bulk_iter()?;
820 let count = iter.count;
821 let mut map = HashMap::with_capacity(count);
822 for (k, v) in iter {
823 map.insert(k, v);
824 }
825 Ok(map)
826 }
827}
828
829#[derive(Clone, Copy)]
835pub struct UeSet<T: ContainerElement> {
836 owner: UObjectHandle,
837 prop: FPropertyHandle,
838 _marker: PhantomData<T>,
839}
840
841impl<T: ContainerElement> UeSet<T> {
842 #[inline]
843 pub fn new(owner: UObjectHandle, prop: FPropertyHandle) -> Self {
844 UeSet {
845 owner,
846 prop,
847 _marker: PhantomData,
848 }
849 }
850
851 pub fn len(&self) -> RustealResult<usize> {
853 let n = unsafe { ffi_dispatch::container_set_len(self.owner, self.prop) };
854 if n < 0 {
855 return Err(RustealError::ObjectDestroyed);
856 }
857 Ok(n as usize)
858 }
859
860 pub fn is_empty(&self) -> RustealResult<bool> {
861 Ok(self.len()? == 0)
862 }
863
864 pub fn contains(&self, val: &T) -> RustealResult<bool> {
866 let mut buf = [0u8; MAX_ELEM_BUF];
867 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
868 Ok(unsafe {
869 ffi_dispatch::container_set_contains(self.owner, self.prop, buf.as_ptr(), written)
870 })
871 }
872
873 pub fn add(&self, val: &T) -> RustealResult<()> {
875 let mut buf = [0u8; MAX_ELEM_BUF];
876 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
877 check_ffi(unsafe {
878 ffi_dispatch::container_set_add(self.owner, self.prop, buf.as_ptr(), written)
879 })
880 }
881
882 pub fn remove(&self, val: &T) -> RustealResult<()> {
884 let mut buf = [0u8; MAX_ELEM_BUF];
885 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
886 check_ffi(unsafe {
887 ffi_dispatch::container_set_remove(self.owner, self.prop, buf.as_ptr(), written)
888 })
889 }
890
891 pub fn clear(&self) -> RustealResult<()> {
893 check_ffi(unsafe { ffi_dispatch::container_set_clear(self.owner, self.prop) })
894 }
895
896 pub fn get_element(&self, logical_index: usize) -> RustealResult<T> {
898 let mut buf = [0u8; MAX_ELEM_BUF];
899 let mut written: u32 = 0;
900 check_ffi(unsafe {
901 ffi_dispatch::container_set_get_element(
902 self.owner,
903 self.prop,
904 logical_index as i32,
905 buf.as_mut_ptr(),
906 T::BUF_SIZE,
907 &mut written,
908 )
909 })?;
910 Ok(unsafe { T::read_from_buf(buf.as_ptr(), written) })
911 }
912
913 pub fn iter(&self) -> UeSetIter<'_, T> {
915 let len = self.len().unwrap_or(0);
916 UeSetIter {
917 set: self,
918 index: 0,
919 len,
920 }
921 }
922}
923
924impl<'a, T: ContainerElement> IntoIterator for &'a UeSet<T> {
925 type Item = RustealResult<T>;
926 type IntoIter = UeSetIter<'a, T>;
927
928 fn into_iter(self) -> Self::IntoIter {
929 self.iter()
930 }
931}
932
933pub struct UeSetIter<'a, T: ContainerElement> {
935 set: &'a UeSet<T>,
936 index: usize,
937 len: usize,
938}
939
940impl<T: ContainerElement> Iterator for UeSetIter<'_, T> {
941 type Item = RustealResult<T>;
942
943 fn next(&mut self) -> Option<Self::Item> {
944 if self.index >= self.len {
945 return None;
946 }
947 let result = self.set.get_element(self.index);
948 self.index += 1;
949 Some(result)
950 }
951
952 fn size_hint(&self) -> (usize, Option<usize>) {
953 let remaining = self.len.saturating_sub(self.index);
954 (remaining, Some(remaining))
955 }
956}
957
958impl<T: ContainerElement> ExactSizeIterator for UeSetIter<'_, T> {}
959
960impl<T: ContainerElement> UeSet<T> {
965 pub fn bulk_iter(&self) -> RustealResult<BulkSetIter<T>> {
967 let len = self.len()?;
968 if len == 0 {
969 return Ok(BulkSetIter {
970 buf: Vec::new(),
971 count: 0,
972 index: 0,
973 offset: 0,
974 _marker: PhantomData,
975 });
976 }
977 let owner = self.owner;
978 let prop = self.prop;
979 let estimate = len * (T::BUF_SIZE as usize + 4);
980 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
981 ffi_dispatch::container_set_copy_all(owner, prop, out, size, written, cnt)
982 })?;
983 Ok(BulkSetIter {
984 buf,
985 count: count as usize,
986 index: 0,
987 offset: 0,
988 _marker: PhantomData,
989 })
990 }
991}
992
993impl<T: ContainerElement + Hash + Eq> UeSet<T> {
994 pub fn to_hash_set(&self) -> RustealResult<HashSet<T>> {
996 let iter = self.bulk_iter()?;
997 let count = iter.count;
998 let mut set = HashSet::with_capacity(count);
999 for elem in iter {
1000 set.insert(elem);
1001 }
1002 Ok(set)
1003 }
1004}
1005
1006pub struct OwnedStruct<T: UeStruct> {
1016 data: Vec<u8>,
1017 needs_destroy: bool,
1018 _marker: PhantomData<T>,
1019}
1020
1021impl<T: UeStruct> Default for OwnedStruct<T> {
1022 fn default() -> Self {
1023 Self::new()
1024 }
1025}
1026
1027impl<T: UeStruct> OwnedStruct<T> {
1028 pub fn new() -> Self {
1035 let ustruct = T::static_struct();
1036 let size = unsafe { ffi_dispatch::reflection_get_struct_size(ustruct) };
1037 debug_assert!(size > 0, "get_struct_size returned 0 for {}", std::any::type_name::<T>());
1038
1039 let mut data = vec![0u8; size as usize];
1040 ffi_infallible(unsafe {
1041 ffi_dispatch::reflection_initialize_struct(ustruct, data.as_mut_ptr())
1042 });
1043 OwnedStruct {
1044 data,
1045 needs_destroy: true,
1046 _marker: PhantomData,
1047 }
1048 }
1049
1050 pub fn from_bytes(data: Vec<u8>) -> Self {
1055 OwnedStruct {
1056 data,
1057 needs_destroy: false,
1058 _marker: PhantomData,
1059 }
1060 }
1061
1062 pub fn copy_from(src: &UStructRef<T>) -> Self {
1065 let mut owned = Self::new();
1066 ffi_infallible(unsafe {
1067 ffi_dispatch::reflection_copy_struct(
1068 T::static_struct(),
1069 owned.data.as_mut_ptr(),
1070 src.as_ptr().0 as *const u8,
1071 )
1072 });
1073 owned
1074 }
1075
1076 pub fn as_ref(&self) -> UStructRef<T> {
1078 unsafe { UStructRef::from_raw(self.data.as_ptr() as *mut u8) }
1079 }
1080
1081 pub fn as_bytes(&self) -> &[u8] {
1083 &self.data
1084 }
1085
1086 pub fn to_bytes(&self) -> Vec<u8> {
1088 self.data.clone()
1089 }
1090}
1091
1092impl<T: UeStruct> Clone for OwnedStruct<T> {
1093 fn clone(&self) -> Self {
1094 OwnedStruct {
1095 data: self.data.clone(),
1096 needs_destroy: false,
1097 _marker: PhantomData,
1098 }
1099 }
1100}
1101
1102impl<T: UeStruct> Drop for OwnedStruct<T> {
1103 fn drop(&mut self) {
1104 if self.needs_destroy {
1105 unsafe {
1106 ffi_dispatch::reflection_destroy_struct(
1107 T::static_struct(),
1108 self.data.as_mut_ptr(),
1109 );
1110 }
1111 }
1112 }
1114}
1115
1116impl<T: UeStruct> std::fmt::Debug for OwnedStruct<T> {
1117 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1118 f.debug_struct("OwnedStruct").field("size", &self.data.len()).finish()
1119 }
1120}
1121
1122unsafe impl<T: UeStruct> ContainerElement for OwnedStruct<T> {
1126 const BUF_SIZE: u32 = 4096;
1127
1128 unsafe fn read_from_buf(buf: *const u8, written: u32) -> Self { unsafe {
1129 let data = vec![0u8; written as usize];
1130 std::ptr::copy_nonoverlapping(buf, data.as_ptr() as *mut u8, written as usize);
1131 OwnedStruct::from_bytes(data)
1132 }}
1133
1134 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 { unsafe {
1135 let bytes = self.to_bytes();
1136 let len = bytes.len();
1137 std::ptr::copy_nonoverlapping(bytes.as_ptr(), buf, len);
1138 len as u32
1139 }}
1140}