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 ContainerElement for crate::fname::FName {
129 const BUF_SIZE: u32 = 8;
130 const RAW_COPYABLE: bool = true;
131
132 #[inline]
133 unsafe fn read_from_buf(buf: *const u8, written: u32) -> Self {
134 crate::fname::FName(unsafe { rusteal_ffi::FNameHandle::read_from_buf(buf, written) })
135 }
136
137 #[inline]
138 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 {
139 unsafe { self.0.write_to_buf(buf) }
140 }
141}
142
143unsafe impl<T: UeClass> ContainerElement for UObjectRef<T> {
145 const BUF_SIZE: u32 = std::mem::size_of::<UObjectHandle>() as u32;
146
147 #[inline]
148 unsafe fn read_from_buf(buf: *const u8, _written: u32) -> Self { unsafe {
149 let handle = (buf as *const UObjectHandle).read_unaligned();
150 UObjectRef::from_raw(handle)
151 }}
152
153 #[inline]
154 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 { unsafe {
155 (buf as *mut UObjectHandle).write_unaligned(self.raw());
156 std::mem::size_of::<UObjectHandle>() as u32
157 }}
158}
159
160unsafe impl ContainerElement for String {
162 const BUF_SIZE: u32 = 4096;
164
165 unsafe fn read_from_buf(buf: *const u8, written: u32) -> Self { unsafe {
166 if written < 4 {
167 return String::new();
168 }
169 let len = (buf as *const u32).read_unaligned() as usize;
170 let data_len = (written as usize).saturating_sub(4).min(len);
171 let slice = std::slice::from_raw_parts(buf.add(4), data_len);
172 String::from_utf8_lossy(slice).into_owned()
173 }}
174
175 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 { unsafe {
176 let bytes = self.as_bytes();
177 let len = bytes.len() as u32;
178 (buf as *mut u32).write_unaligned(len);
179 std::ptr::copy_nonoverlapping(bytes.as_ptr(), buf.add(4), bytes.len());
180 4 + len
181 }}
182}
183
184#[derive(Clone, Copy)]
193pub struct UeArray<T: ContainerElement> {
194 owner: UObjectHandle,
195 prop: FPropertyHandle,
196 _marker: PhantomData<T>,
197}
198
199impl<T: ContainerElement> UeArray<T> {
200 #[inline]
202 pub fn new(owner: UObjectHandle, prop: FPropertyHandle) -> Self {
203 UeArray {
204 owner,
205 prop,
206 _marker: PhantomData,
207 }
208 }
209
210 pub fn len(&self) -> RustealResult<usize> {
212 let n = unsafe { ffi_dispatch::container_array_len(self.owner, self.prop) };
213 if n < 0 {
214 return Err(RustealError::ObjectDestroyed);
215 }
216 Ok(n as usize)
217 }
218
219 pub fn is_empty(&self) -> RustealResult<bool> {
221 Ok(self.len()? == 0)
222 }
223
224 pub fn get(&self, index: usize) -> RustealResult<T> {
226 let mut buf = [0u8; MAX_ELEM_BUF];
227 let mut written: u32 = 0;
228 check_ffi(unsafe {
229 ffi_dispatch::container_array_get(
230 self.owner,
231 self.prop,
232 index as i32,
233 buf.as_mut_ptr(),
234 T::BUF_SIZE,
235 &mut written,
236 )
237 })?;
238 Ok(unsafe { T::read_from_buf(buf.as_ptr(), written) })
239 }
240
241 pub fn set(&self, index: usize, 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_set(
248 self.owner,
249 self.prop,
250 index as i32,
251 buf.as_ptr(),
252 written,
253 )
254 })
255 }
256
257 pub fn push(&self, val: &T) -> RustealResult<()> {
259 let mut buf = [0u8; MAX_ELEM_BUF];
260 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
262 check_ffi(unsafe {
263 ffi_dispatch::container_array_add(self.owner, self.prop, buf.as_ptr(), written)
264 })
265 }
266
267 pub fn remove(&self, index: usize) -> RustealResult<()> {
269 check_ffi(unsafe {
270 ffi_dispatch::container_array_remove(self.owner, self.prop, index as i32)
271 })
272 }
273
274 pub fn clear(&self) -> RustealResult<()> {
276 check_ffi(unsafe { ffi_dispatch::container_array_clear(self.owner, self.prop) })
277 }
278
279 pub fn iter(&self) -> UeArrayIter<'_, T> {
281 let len = self.len().unwrap_or(0);
282 UeArrayIter {
283 array: self,
284 index: 0,
285 len,
286 }
287 }
288}
289
290impl<'a, T: ContainerElement> IntoIterator for &'a UeArray<T> {
291 type Item = RustealResult<T>;
292 type IntoIter = UeArrayIter<'a, T>;
293
294 fn into_iter(self) -> Self::IntoIter {
295 self.iter()
296 }
297}
298
299pub struct UeArrayIter<'a, T: ContainerElement> {
301 array: &'a UeArray<T>,
302 index: usize,
303 len: usize,
304}
305
306impl<T: ContainerElement> Iterator for UeArrayIter<'_, T> {
307 type Item = RustealResult<T>;
308
309 fn next(&mut self) -> Option<Self::Item> {
310 if self.index >= self.len {
311 return None;
312 }
313 let result = self.array.get(self.index);
314 self.index += 1;
315 Some(result)
316 }
317
318 fn size_hint(&self) -> (usize, Option<usize>) {
319 let remaining = self.len.saturating_sub(self.index);
320 (remaining, Some(remaining))
321 }
322}
323
324impl<T: ContainerElement> ExactSizeIterator for UeArrayIter<'_, T> {}
325
326fn bulk_copy_with_retry(
332 estimate: usize,
333 call: impl Fn(*mut u8, u32, *mut u32, *mut i32) -> RustealErrorCode,
334) -> RustealResult<(Vec<u8>, i32)> {
335 let mut buf = vec![0u8; estimate.max(64)];
336 let mut written: u32 = 0;
337 let mut count: i32 = 0;
338 let code = call(buf.as_mut_ptr(), buf.len() as u32, &mut written, &mut count);
339 if code == RustealErrorCode::BufferTooSmall {
340 let needed = (written as usize).max(buf.len() * 2);
342 buf.resize(needed, 0);
343 check_ffi(call(
344 buf.as_mut_ptr(),
345 buf.len() as u32,
346 &mut written,
347 &mut count,
348 ))?;
349 } else {
350 check_ffi(code)?;
351 }
352 buf.truncate(written as usize);
353 Ok((buf, count))
354}
355
356pub struct BulkArrayIter<T: ContainerElement> {
367 buf: Vec<u8>,
368 count: usize,
369 index: usize,
370 offset: usize,
371 raw_elem_size: usize, _marker: PhantomData<T>,
373}
374
375impl<T: ContainerElement> Iterator for BulkArrayIter<T> {
376 type Item = T;
377
378 fn next(&mut self) -> Option<T> {
379 if self.index >= self.count {
380 return None;
381 }
382 if self.raw_elem_size > 0 {
383 let elem = unsafe {
385 T::read_from_buf(
386 self.buf.as_ptr().add(self.offset),
387 self.raw_elem_size as u32,
388 )
389 };
390 self.offset += self.raw_elem_size;
391 self.index += 1;
392 Some(elem)
393 } else {
394 if self.offset + 4 > self.buf.len() {
396 return None;
397 }
398 let written = u32::from_ne_bytes(
399 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
400 );
401 self.offset += 4;
402 let elem =
403 unsafe { T::read_from_buf(self.buf.as_ptr().add(self.offset), written) };
404 self.offset += written as usize;
405 self.index += 1;
406 Some(elem)
407 }
408 }
409
410 fn size_hint(&self) -> (usize, Option<usize>) {
411 let r = self.count - self.index;
412 (r, Some(r))
413 }
414}
415
416impl<T: ContainerElement> ExactSizeIterator for BulkArrayIter<T> {}
417
418pub struct BulkMapIter<K: ContainerElement, V: ContainerElement> {
420 buf: Vec<u8>,
421 count: usize,
422 index: usize,
423 offset: usize,
424 _marker: PhantomData<(K, V)>,
425}
426
427impl<K: ContainerElement, V: ContainerElement> Iterator for BulkMapIter<K, V> {
428 type Item = (K, V);
429
430 fn next(&mut self) -> Option<(K, V)> {
431 if self.index >= self.count {
432 return None;
433 }
434 if self.offset + 4 > self.buf.len() {
436 return None;
437 }
438 let key_written = u32::from_ne_bytes(
439 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
440 );
441 self.offset += 4;
442 let key =
443 unsafe { K::read_from_buf(self.buf.as_ptr().add(self.offset), key_written) };
444 self.offset += key_written as usize;
445
446 if self.offset + 4 > self.buf.len() {
448 return None;
449 }
450 let val_written = u32::from_ne_bytes(
451 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
452 );
453 self.offset += 4;
454 let val =
455 unsafe { V::read_from_buf(self.buf.as_ptr().add(self.offset), val_written) };
456 self.offset += val_written as usize;
457
458 self.index += 1;
459 Some((key, val))
460 }
461
462 fn size_hint(&self) -> (usize, Option<usize>) {
463 let r = self.count - self.index;
464 (r, Some(r))
465 }
466}
467
468impl<K: ContainerElement, V: ContainerElement> ExactSizeIterator for BulkMapIter<K, V> {}
469
470pub struct BulkSetIter<T: ContainerElement> {
472 buf: Vec<u8>,
473 count: usize,
474 index: usize,
475 offset: usize,
476 _marker: PhantomData<T>,
477}
478
479impl<T: ContainerElement> Iterator for BulkSetIter<T> {
480 type Item = T;
481
482 fn next(&mut self) -> Option<T> {
483 if self.index >= self.count {
484 return None;
485 }
486 if self.offset + 4 > self.buf.len() {
487 return None;
488 }
489 let written = u32::from_ne_bytes(
490 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
491 );
492 self.offset += 4;
493 let elem = unsafe { T::read_from_buf(self.buf.as_ptr().add(self.offset), written) };
494 self.offset += written as usize;
495 self.index += 1;
496 Some(elem)
497 }
498
499 fn size_hint(&self) -> (usize, Option<usize>) {
500 let r = self.count - self.index;
501 (r, Some(r))
502 }
503}
504
505impl<T: ContainerElement> ExactSizeIterator for BulkSetIter<T> {}
506
507impl<T: ContainerElement> UeArray<T> {
512 pub fn to_vec(&self) -> RustealResult<Vec<T>> {
514 let len = self.len()?;
515 if len == 0 {
516 return Ok(Vec::new());
517 }
518 let owner = self.owner;
519 let prop = self.prop;
520 let estimate = if T::RAW_COPYABLE {
522 len * T::BUF_SIZE as usize
523 } else {
524 len * (T::BUF_SIZE as usize + 4)
525 };
526 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
527 ffi_dispatch::container_array_copy_all(owner, prop, out, size, written, cnt)
528 })?;
529 let (actual_count, raw_elem_size) = if count < 0 {
531 ((-count) as usize, T::BUF_SIZE as usize)
532 } else {
533 (count as usize, 0)
534 };
535 Ok(BulkArrayIter::<T> {
536 buf,
537 count: actual_count,
538 index: 0,
539 offset: 0,
540 raw_elem_size,
541 _marker: PhantomData,
542 }
543 .collect())
544 }
545
546 pub fn bulk_iter(&self) -> RustealResult<BulkArrayIter<T>> {
548 let len = self.len()?;
549 if len == 0 {
550 return Ok(BulkArrayIter {
551 buf: Vec::new(),
552 count: 0,
553 index: 0,
554 offset: 0,
555 raw_elem_size: 0,
556 _marker: PhantomData,
557 });
558 }
559 let owner = self.owner;
560 let prop = self.prop;
561 let estimate = if T::RAW_COPYABLE {
562 len * T::BUF_SIZE as usize
563 } else {
564 len * (T::BUF_SIZE as usize + 4)
565 };
566 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
567 ffi_dispatch::container_array_copy_all(owner, prop, out, size, written, cnt)
568 })?;
569 let (actual_count, raw_elem_size) = if count < 0 {
570 ((-count) as usize, T::BUF_SIZE as usize)
571 } else {
572 (count as usize, 0)
573 };
574 Ok(BulkArrayIter {
575 buf,
576 count: actual_count,
577 index: 0,
578 offset: 0,
579 raw_elem_size,
580 _marker: PhantomData,
581 })
582 }
583
584 pub fn set_all(&self, items: &[T]) -> RustealResult<()> {
586 if items.is_empty() {
587 return self.clear();
588 }
589 if T::RAW_COPYABLE {
590 let elem_size = T::BUF_SIZE as usize;
592 let mut buf = vec![0u8; items.len() * elem_size];
593 for (i, item) in items.iter().enumerate() {
594 unsafe { item.write_to_buf(buf.as_mut_ptr().add(i * elem_size)); }
595 }
596 check_ffi(unsafe {
598 ffi_dispatch::container_array_set_all(
599 self.owner,
600 self.prop,
601 buf.as_ptr(),
602 buf.len() as u32,
603 -(items.len() as i32),
604 )
605 })
606 } else {
607 let mut buf = Vec::with_capacity(items.len() * (T::BUF_SIZE as usize + 4));
609 let mut elem_buf = [0u8; MAX_ELEM_BUF];
610 for item in items {
611 let written = unsafe { item.write_to_buf(elem_buf.as_mut_ptr()) };
612 buf.extend_from_slice(&written.to_ne_bytes());
613 buf.extend_from_slice(&elem_buf[..written as usize]);
614 }
615 check_ffi(unsafe {
616 ffi_dispatch::container_array_set_all(
617 self.owner,
618 self.prop,
619 buf.as_ptr(),
620 buf.len() as u32,
621 items.len() as i32,
622 )
623 })
624 }
625 }
626}
627
628#[derive(Clone, Copy)]
634pub struct UeMap<K: ContainerElement, V: ContainerElement> {
635 owner: UObjectHandle,
636 prop: FPropertyHandle,
637 _marker: PhantomData<(K, V)>,
638}
639
640impl<K: ContainerElement, V: ContainerElement> UeMap<K, V> {
641 #[inline]
642 pub fn new(owner: UObjectHandle, prop: FPropertyHandle) -> Self {
643 UeMap {
644 owner,
645 prop,
646 _marker: PhantomData,
647 }
648 }
649
650 pub fn len(&self) -> RustealResult<usize> {
652 let n = unsafe { ffi_dispatch::container_map_len(self.owner, self.prop) };
653 if n < 0 {
654 return Err(RustealError::ObjectDestroyed);
655 }
656 Ok(n as usize)
657 }
658
659 pub fn is_empty(&self) -> RustealResult<bool> {
660 Ok(self.len()? == 0)
661 }
662
663 pub fn find(&self, key: &K) -> RustealResult<V> {
666 let mut key_buf = [0u8; MAX_ELEM_BUF];
667 let key_written = unsafe { key.write_to_buf(key_buf.as_mut_ptr()) };
668 let mut val_buf = [0u8; MAX_ELEM_BUF];
669 let mut val_written: u32 = 0;
670
671 check_ffi(unsafe {
672 ffi_dispatch::container_map_find(
673 self.owner,
674 self.prop,
675 key_buf.as_ptr(),
676 key_written,
677 val_buf.as_mut_ptr(),
678 V::BUF_SIZE,
679 &mut val_written,
680 )
681 })?;
682 Ok(unsafe { V::read_from_buf(val_buf.as_ptr(), val_written) })
683 }
684
685 pub fn add(&self, key: &K, val: &V) -> RustealResult<()> {
687 let mut key_buf = [0u8; MAX_ELEM_BUF];
688 let key_written = unsafe { key.write_to_buf(key_buf.as_mut_ptr()) };
689 let mut val_buf = [0u8; MAX_ELEM_BUF];
690 let val_written = unsafe { val.write_to_buf(val_buf.as_mut_ptr()) };
691
692 check_ffi(unsafe {
693 ffi_dispatch::container_map_add(
694 self.owner,
695 self.prop,
696 key_buf.as_ptr(),
697 key_written,
698 val_buf.as_ptr(),
699 val_written,
700 )
701 })
702 }
703
704 pub fn remove(&self, key: &K) -> RustealResult<()> {
706 let mut key_buf = [0u8; MAX_ELEM_BUF];
707 let key_written = unsafe { key.write_to_buf(key_buf.as_mut_ptr()) };
708
709 check_ffi(unsafe {
710 ffi_dispatch::container_map_remove(
711 self.owner,
712 self.prop,
713 key_buf.as_ptr(),
714 key_written,
715 )
716 })
717 }
718
719 pub fn clear(&self) -> RustealResult<()> {
721 check_ffi(unsafe { ffi_dispatch::container_map_clear(self.owner, self.prop) })
722 }
723
724 pub fn get_pair(&self, logical_index: usize) -> RustealResult<(K, V)> {
726 let mut key_buf = [0u8; MAX_ELEM_BUF];
727 let mut key_written: u32 = 0;
728 let mut val_buf = [0u8; MAX_ELEM_BUF];
729 let mut val_written: u32 = 0;
730
731 check_ffi(unsafe {
732 ffi_dispatch::container_map_get_pair(
733 self.owner,
734 self.prop,
735 logical_index as i32,
736 key_buf.as_mut_ptr(),
737 K::BUF_SIZE,
738 &mut key_written,
739 val_buf.as_mut_ptr(),
740 V::BUF_SIZE,
741 &mut val_written,
742 )
743 })?;
744 Ok(unsafe {
745 (
746 K::read_from_buf(key_buf.as_ptr(), key_written),
747 V::read_from_buf(val_buf.as_ptr(), val_written),
748 )
749 })
750 }
751
752 pub fn iter(&self) -> UeMapIter<'_, K, V> {
754 let len = self.len().unwrap_or(0);
755 UeMapIter {
756 map: self,
757 index: 0,
758 len,
759 }
760 }
761}
762
763impl<'a, K: ContainerElement, V: ContainerElement> IntoIterator for &'a UeMap<K, V> {
764 type Item = RustealResult<(K, V)>;
765 type IntoIter = UeMapIter<'a, K, V>;
766
767 fn into_iter(self) -> Self::IntoIter {
768 self.iter()
769 }
770}
771
772pub struct UeMapIter<'a, K: ContainerElement, V: ContainerElement> {
774 map: &'a UeMap<K, V>,
775 index: usize,
776 len: usize,
777}
778
779impl<K: ContainerElement, V: ContainerElement> Iterator for UeMapIter<'_, K, V> {
780 type Item = RustealResult<(K, V)>;
781
782 fn next(&mut self) -> Option<Self::Item> {
783 if self.index >= self.len {
784 return None;
785 }
786 let result = self.map.get_pair(self.index);
787 self.index += 1;
788 Some(result)
789 }
790
791 fn size_hint(&self) -> (usize, Option<usize>) {
792 let remaining = self.len.saturating_sub(self.index);
793 (remaining, Some(remaining))
794 }
795}
796
797impl<K: ContainerElement, V: ContainerElement> ExactSizeIterator for UeMapIter<'_, K, V> {}
798
799impl<K: ContainerElement, V: ContainerElement> UeMap<K, V> {
804 pub fn bulk_iter(&self) -> RustealResult<BulkMapIter<K, V>> {
806 let len = self.len()?;
807 if len == 0 {
808 return Ok(BulkMapIter {
809 buf: Vec::new(),
810 count: 0,
811 index: 0,
812 offset: 0,
813 _marker: PhantomData,
814 });
815 }
816 let owner = self.owner;
817 let prop = self.prop;
818 let estimate = len * (K::BUF_SIZE as usize + V::BUF_SIZE as usize + 8);
819 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
820 ffi_dispatch::container_map_copy_all(owner, prop, out, size, written, cnt)
821 })?;
822 Ok(BulkMapIter {
823 buf,
824 count: count as usize,
825 index: 0,
826 offset: 0,
827 _marker: PhantomData,
828 })
829 }
830}
831
832impl<K: ContainerElement + Hash + Eq, V: ContainerElement> UeMap<K, V> {
833 pub fn to_hash_map(&self) -> RustealResult<HashMap<K, V>> {
835 let iter = self.bulk_iter()?;
836 let count = iter.count;
837 let mut map = HashMap::with_capacity(count);
838 for (k, v) in iter {
839 map.insert(k, v);
840 }
841 Ok(map)
842 }
843}
844
845#[derive(Clone, Copy)]
851pub struct UeSet<T: ContainerElement> {
852 owner: UObjectHandle,
853 prop: FPropertyHandle,
854 _marker: PhantomData<T>,
855}
856
857impl<T: ContainerElement> UeSet<T> {
858 #[inline]
859 pub fn new(owner: UObjectHandle, prop: FPropertyHandle) -> Self {
860 UeSet {
861 owner,
862 prop,
863 _marker: PhantomData,
864 }
865 }
866
867 pub fn len(&self) -> RustealResult<usize> {
869 let n = unsafe { ffi_dispatch::container_set_len(self.owner, self.prop) };
870 if n < 0 {
871 return Err(RustealError::ObjectDestroyed);
872 }
873 Ok(n as usize)
874 }
875
876 pub fn is_empty(&self) -> RustealResult<bool> {
877 Ok(self.len()? == 0)
878 }
879
880 pub fn contains(&self, val: &T) -> RustealResult<bool> {
882 let mut buf = [0u8; MAX_ELEM_BUF];
883 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
884 Ok(unsafe {
885 ffi_dispatch::container_set_contains(self.owner, self.prop, buf.as_ptr(), written)
886 })
887 }
888
889 pub fn add(&self, val: &T) -> RustealResult<()> {
891 let mut buf = [0u8; MAX_ELEM_BUF];
892 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
893 check_ffi(unsafe {
894 ffi_dispatch::container_set_add(self.owner, self.prop, buf.as_ptr(), written)
895 })
896 }
897
898 pub fn remove(&self, val: &T) -> RustealResult<()> {
900 let mut buf = [0u8; MAX_ELEM_BUF];
901 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
902 check_ffi(unsafe {
903 ffi_dispatch::container_set_remove(self.owner, self.prop, buf.as_ptr(), written)
904 })
905 }
906
907 pub fn clear(&self) -> RustealResult<()> {
909 check_ffi(unsafe { ffi_dispatch::container_set_clear(self.owner, self.prop) })
910 }
911
912 pub fn get_element(&self, logical_index: usize) -> RustealResult<T> {
914 let mut buf = [0u8; MAX_ELEM_BUF];
915 let mut written: u32 = 0;
916 check_ffi(unsafe {
917 ffi_dispatch::container_set_get_element(
918 self.owner,
919 self.prop,
920 logical_index as i32,
921 buf.as_mut_ptr(),
922 T::BUF_SIZE,
923 &mut written,
924 )
925 })?;
926 Ok(unsafe { T::read_from_buf(buf.as_ptr(), written) })
927 }
928
929 pub fn iter(&self) -> UeSetIter<'_, T> {
931 let len = self.len().unwrap_or(0);
932 UeSetIter {
933 set: self,
934 index: 0,
935 len,
936 }
937 }
938}
939
940impl<'a, T: ContainerElement> IntoIterator for &'a UeSet<T> {
941 type Item = RustealResult<T>;
942 type IntoIter = UeSetIter<'a, T>;
943
944 fn into_iter(self) -> Self::IntoIter {
945 self.iter()
946 }
947}
948
949pub struct UeSetIter<'a, T: ContainerElement> {
951 set: &'a UeSet<T>,
952 index: usize,
953 len: usize,
954}
955
956impl<T: ContainerElement> Iterator for UeSetIter<'_, T> {
957 type Item = RustealResult<T>;
958
959 fn next(&mut self) -> Option<Self::Item> {
960 if self.index >= self.len {
961 return None;
962 }
963 let result = self.set.get_element(self.index);
964 self.index += 1;
965 Some(result)
966 }
967
968 fn size_hint(&self) -> (usize, Option<usize>) {
969 let remaining = self.len.saturating_sub(self.index);
970 (remaining, Some(remaining))
971 }
972}
973
974impl<T: ContainerElement> ExactSizeIterator for UeSetIter<'_, T> {}
975
976impl<T: ContainerElement> UeSet<T> {
981 pub fn bulk_iter(&self) -> RustealResult<BulkSetIter<T>> {
983 let len = self.len()?;
984 if len == 0 {
985 return Ok(BulkSetIter {
986 buf: Vec::new(),
987 count: 0,
988 index: 0,
989 offset: 0,
990 _marker: PhantomData,
991 });
992 }
993 let owner = self.owner;
994 let prop = self.prop;
995 let estimate = len * (T::BUF_SIZE as usize + 4);
996 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
997 ffi_dispatch::container_set_copy_all(owner, prop, out, size, written, cnt)
998 })?;
999 Ok(BulkSetIter {
1000 buf,
1001 count: count as usize,
1002 index: 0,
1003 offset: 0,
1004 _marker: PhantomData,
1005 })
1006 }
1007}
1008
1009impl<T: ContainerElement + Hash + Eq> UeSet<T> {
1010 pub fn to_hash_set(&self) -> RustealResult<HashSet<T>> {
1012 let iter = self.bulk_iter()?;
1013 let count = iter.count;
1014 let mut set = HashSet::with_capacity(count);
1015 for elem in iter {
1016 set.insert(elem);
1017 }
1018 Ok(set)
1019 }
1020}
1021
1022pub struct OwnedStruct<T: UeStruct> {
1032 data: Vec<u8>,
1033 needs_destroy: bool,
1034 _marker: PhantomData<T>,
1035}
1036
1037impl<T: UeStruct> Default for OwnedStruct<T> {
1038 fn default() -> Self {
1039 Self::new()
1040 }
1041}
1042
1043impl<T: UeStruct> OwnedStruct<T> {
1044 pub fn new() -> Self {
1051 let ustruct = T::static_struct();
1052 let size = unsafe { ffi_dispatch::reflection_get_struct_size(ustruct) };
1053 debug_assert!(size > 0, "get_struct_size returned 0 for {}", std::any::type_name::<T>());
1054
1055 let mut data = vec![0u8; size as usize];
1056 ffi_infallible(unsafe {
1057 ffi_dispatch::reflection_initialize_struct(ustruct, data.as_mut_ptr())
1058 });
1059 OwnedStruct {
1060 data,
1061 needs_destroy: true,
1062 _marker: PhantomData,
1063 }
1064 }
1065
1066 pub fn from_bytes(data: Vec<u8>) -> Self {
1071 OwnedStruct {
1072 data,
1073 needs_destroy: false,
1074 _marker: PhantomData,
1075 }
1076 }
1077
1078 pub fn copy_from(src: &UStructRef<T>) -> Self {
1081 let mut owned = Self::new();
1082 ffi_infallible(unsafe {
1083 ffi_dispatch::reflection_copy_struct(
1084 T::static_struct(),
1085 owned.data.as_mut_ptr(),
1086 src.as_ptr().0 as *const u8,
1087 )
1088 });
1089 owned
1090 }
1091
1092 pub fn as_ref(&self) -> UStructRef<T> {
1094 unsafe { UStructRef::from_raw(self.data.as_ptr() as *mut u8) }
1095 }
1096
1097 pub fn as_bytes(&self) -> &[u8] {
1099 &self.data
1100 }
1101
1102 pub fn to_bytes(&self) -> Vec<u8> {
1104 self.data.clone()
1105 }
1106}
1107
1108impl<T: UeStruct> Clone for OwnedStruct<T> {
1109 fn clone(&self) -> Self {
1110 OwnedStruct {
1111 data: self.data.clone(),
1112 needs_destroy: false,
1113 _marker: PhantomData,
1114 }
1115 }
1116}
1117
1118impl<T: UeStruct> Drop for OwnedStruct<T> {
1119 fn drop(&mut self) {
1120 if self.needs_destroy {
1121 unsafe {
1122 ffi_dispatch::reflection_destroy_struct(
1123 T::static_struct(),
1124 self.data.as_mut_ptr(),
1125 );
1126 }
1127 }
1128 }
1130}
1131
1132impl<T: UeStruct> std::fmt::Debug for OwnedStruct<T> {
1133 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1134 f.debug_struct("OwnedStruct").field("size", &self.data.len()).finish()
1135 }
1136}
1137
1138unsafe impl<T: UeStruct> ContainerElement for OwnedStruct<T> {
1142 const BUF_SIZE: u32 = 4096;
1143
1144 unsafe fn read_from_buf(buf: *const u8, written: u32) -> Self { unsafe {
1145 let data = vec![0u8; written as usize];
1146 std::ptr::copy_nonoverlapping(buf, data.as_ptr() as *mut u8, written as usize);
1147 OwnedStruct::from_bytes(data)
1148 }}
1149
1150 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 { unsafe {
1151 let bytes = self.to_bytes();
1152 let len = bytes.len();
1153 std::ptr::copy_nonoverlapping(bytes.as_ptr(), buf, len);
1154 len as u32
1155 }}
1156}