1use std::collections::{HashMap, HashSet};
7use std::hash::Hash;
8use std::marker::PhantomData;
9
10use uika_ffi::{FPropertyHandle, UObjectHandle, UikaErrorCode};
11
12const MAX_ELEM_BUF: usize = 4096;
16
17use crate::api::api;
18use crate::error::{check_ffi, ffi_infallible, UikaError, UikaResult};
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 uika_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 uika_ffi::FNameHandle).read_unaligned()
118 }}
119
120 #[inline]
121 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 { unsafe {
122 (buf as *mut uika_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) -> UikaResult<usize> {
196 let n = unsafe { ((*api().container).array_len)(self.owner, self.prop) };
197 if n < 0 {
198 return Err(UikaError::ObjectDestroyed);
199 }
200 Ok(n as usize)
201 }
202
203 pub fn is_empty(&self) -> UikaResult<bool> {
205 Ok(self.len()? == 0)
206 }
207
208 pub fn get(&self, index: usize) -> UikaResult<T> {
210 let mut buf = [0u8; MAX_ELEM_BUF];
211 let mut written: u32 = 0;
212 check_ffi(unsafe {
213 ((*api().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) -> UikaResult<()> {
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 ((*api().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) -> UikaResult<()> {
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 ((*api().container).array_add)(self.owner, self.prop, buf.as_ptr(), written)
248 })
249 }
250
251 pub fn remove(&self, index: usize) -> UikaResult<()> {
253 check_ffi(unsafe {
254 ((*api().container).array_remove)(self.owner, self.prop, index as i32)
255 })
256 }
257
258 pub fn clear(&self) -> UikaResult<()> {
260 check_ffi(unsafe { ((*api().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 = UikaResult<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 = UikaResult<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) -> UikaErrorCode,
318) -> UikaResult<(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 == UikaErrorCode::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 let written = u32::from_ne_bytes(
380 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
381 );
382 self.offset += 4;
383 let elem =
384 unsafe { T::read_from_buf(self.buf.as_ptr().add(self.offset), written) };
385 self.offset += written as usize;
386 self.index += 1;
387 Some(elem)
388 }
389 }
390
391 fn size_hint(&self) -> (usize, Option<usize>) {
392 let r = self.count - self.index;
393 (r, Some(r))
394 }
395}
396
397impl<T: ContainerElement> ExactSizeIterator for BulkArrayIter<T> {}
398
399pub struct BulkMapIter<K: ContainerElement, V: ContainerElement> {
401 buf: Vec<u8>,
402 count: usize,
403 index: usize,
404 offset: usize,
405 _marker: PhantomData<(K, V)>,
406}
407
408impl<K: ContainerElement, V: ContainerElement> Iterator for BulkMapIter<K, V> {
409 type Item = (K, V);
410
411 fn next(&mut self) -> Option<(K, V)> {
412 if self.index >= self.count {
413 return None;
414 }
415 let key_written = u32::from_ne_bytes(
417 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
418 );
419 self.offset += 4;
420 let key =
421 unsafe { K::read_from_buf(self.buf.as_ptr().add(self.offset), key_written) };
422 self.offset += key_written as usize;
423
424 let val_written = u32::from_ne_bytes(
426 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
427 );
428 self.offset += 4;
429 let val =
430 unsafe { V::read_from_buf(self.buf.as_ptr().add(self.offset), val_written) };
431 self.offset += val_written as usize;
432
433 self.index += 1;
434 Some((key, val))
435 }
436
437 fn size_hint(&self) -> (usize, Option<usize>) {
438 let r = self.count - self.index;
439 (r, Some(r))
440 }
441}
442
443impl<K: ContainerElement, V: ContainerElement> ExactSizeIterator for BulkMapIter<K, V> {}
444
445pub struct BulkSetIter<T: ContainerElement> {
447 buf: Vec<u8>,
448 count: usize,
449 index: usize,
450 offset: usize,
451 _marker: PhantomData<T>,
452}
453
454impl<T: ContainerElement> Iterator for BulkSetIter<T> {
455 type Item = T;
456
457 fn next(&mut self) -> Option<T> {
458 if self.index >= self.count {
459 return None;
460 }
461 let written = u32::from_ne_bytes(
462 self.buf[self.offset..self.offset + 4].try_into().unwrap(),
463 );
464 self.offset += 4;
465 let elem = unsafe { T::read_from_buf(self.buf.as_ptr().add(self.offset), written) };
466 self.offset += written as usize;
467 self.index += 1;
468 Some(elem)
469 }
470
471 fn size_hint(&self) -> (usize, Option<usize>) {
472 let r = self.count - self.index;
473 (r, Some(r))
474 }
475}
476
477impl<T: ContainerElement> ExactSizeIterator for BulkSetIter<T> {}
478
479impl<T: ContainerElement> UeArray<T> {
484 pub fn to_vec(&self) -> UikaResult<Vec<T>> {
486 let len = self.len()?;
487 if len == 0 {
488 return Ok(Vec::new());
489 }
490 let owner = self.owner;
491 let prop = self.prop;
492 let estimate = if T::RAW_COPYABLE {
494 len * T::BUF_SIZE as usize
495 } else {
496 len * (T::BUF_SIZE as usize + 4)
497 };
498 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
499 ((*api().container).array_copy_all)(owner, prop, out, size, written, cnt)
500 })?;
501 let (actual_count, raw_elem_size) = if count < 0 {
503 ((-count) as usize, T::BUF_SIZE as usize)
504 } else {
505 (count as usize, 0)
506 };
507 Ok(BulkArrayIter::<T> {
508 buf,
509 count: actual_count,
510 index: 0,
511 offset: 0,
512 raw_elem_size,
513 _marker: PhantomData,
514 }
515 .collect())
516 }
517
518 pub fn bulk_iter(&self) -> UikaResult<BulkArrayIter<T>> {
520 let len = self.len()?;
521 if len == 0 {
522 return Ok(BulkArrayIter {
523 buf: Vec::new(),
524 count: 0,
525 index: 0,
526 offset: 0,
527 raw_elem_size: 0,
528 _marker: PhantomData,
529 });
530 }
531 let owner = self.owner;
532 let prop = self.prop;
533 let estimate = if T::RAW_COPYABLE {
534 len * T::BUF_SIZE as usize
535 } else {
536 len * (T::BUF_SIZE as usize + 4)
537 };
538 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
539 ((*api().container).array_copy_all)(owner, prop, out, size, written, cnt)
540 })?;
541 let (actual_count, raw_elem_size) = if count < 0 {
542 ((-count) as usize, T::BUF_SIZE as usize)
543 } else {
544 (count as usize, 0)
545 };
546 Ok(BulkArrayIter {
547 buf,
548 count: actual_count,
549 index: 0,
550 offset: 0,
551 raw_elem_size,
552 _marker: PhantomData,
553 })
554 }
555
556 pub fn set_all(&self, items: &[T]) -> UikaResult<()> {
558 if items.is_empty() {
559 return self.clear();
560 }
561 if T::RAW_COPYABLE {
562 let elem_size = T::BUF_SIZE as usize;
564 let mut buf = vec![0u8; items.len() * elem_size];
565 for (i, item) in items.iter().enumerate() {
566 unsafe { item.write_to_buf(buf.as_mut_ptr().add(i * elem_size)); }
567 }
568 check_ffi(unsafe {
570 ((*api().container).array_set_all)(
571 self.owner,
572 self.prop,
573 buf.as_ptr(),
574 buf.len() as u32,
575 -(items.len() as i32),
576 )
577 })
578 } else {
579 let mut buf = Vec::with_capacity(items.len() * (T::BUF_SIZE as usize + 4));
581 let mut elem_buf = [0u8; MAX_ELEM_BUF];
582 for item in items {
583 let written = unsafe { item.write_to_buf(elem_buf.as_mut_ptr()) };
584 buf.extend_from_slice(&written.to_ne_bytes());
585 buf.extend_from_slice(&elem_buf[..written as usize]);
586 }
587 check_ffi(unsafe {
588 ((*api().container).array_set_all)(
589 self.owner,
590 self.prop,
591 buf.as_ptr(),
592 buf.len() as u32,
593 items.len() as i32,
594 )
595 })
596 }
597 }
598}
599
600#[derive(Clone, Copy)]
606pub struct UeMap<K: ContainerElement, V: ContainerElement> {
607 owner: UObjectHandle,
608 prop: FPropertyHandle,
609 _marker: PhantomData<(K, V)>,
610}
611
612impl<K: ContainerElement, V: ContainerElement> UeMap<K, V> {
613 #[inline]
614 pub fn new(owner: UObjectHandle, prop: FPropertyHandle) -> Self {
615 UeMap {
616 owner,
617 prop,
618 _marker: PhantomData,
619 }
620 }
621
622 pub fn len(&self) -> UikaResult<usize> {
624 let n = unsafe { ((*api().container).map_len)(self.owner, self.prop) };
625 if n < 0 {
626 return Err(UikaError::ObjectDestroyed);
627 }
628 Ok(n as usize)
629 }
630
631 pub fn is_empty(&self) -> UikaResult<bool> {
632 Ok(self.len()? == 0)
633 }
634
635 pub fn find(&self, key: &K) -> UikaResult<V> {
638 let mut key_buf = [0u8; MAX_ELEM_BUF];
639 let key_written = unsafe { key.write_to_buf(key_buf.as_mut_ptr()) };
640 let mut val_buf = [0u8; MAX_ELEM_BUF];
641 let mut val_written: u32 = 0;
642
643 check_ffi(unsafe {
644 ((*api().container).map_find)(
645 self.owner,
646 self.prop,
647 key_buf.as_ptr(),
648 key_written,
649 val_buf.as_mut_ptr(),
650 V::BUF_SIZE,
651 &mut val_written,
652 )
653 })?;
654 Ok(unsafe { V::read_from_buf(val_buf.as_ptr(), val_written) })
655 }
656
657 pub fn add(&self, key: &K, val: &V) -> UikaResult<()> {
659 let mut key_buf = [0u8; MAX_ELEM_BUF];
660 let key_written = unsafe { key.write_to_buf(key_buf.as_mut_ptr()) };
661 let mut val_buf = [0u8; MAX_ELEM_BUF];
662 let val_written = unsafe { val.write_to_buf(val_buf.as_mut_ptr()) };
663
664 check_ffi(unsafe {
665 ((*api().container).map_add)(
666 self.owner,
667 self.prop,
668 key_buf.as_ptr(),
669 key_written,
670 val_buf.as_ptr(),
671 val_written,
672 )
673 })
674 }
675
676 pub fn remove(&self, key: &K) -> UikaResult<()> {
678 let mut key_buf = [0u8; MAX_ELEM_BUF];
679 let key_written = unsafe { key.write_to_buf(key_buf.as_mut_ptr()) };
680
681 check_ffi(unsafe {
682 ((*api().container).map_remove)(
683 self.owner,
684 self.prop,
685 key_buf.as_ptr(),
686 key_written,
687 )
688 })
689 }
690
691 pub fn clear(&self) -> UikaResult<()> {
693 check_ffi(unsafe { ((*api().container).map_clear)(self.owner, self.prop) })
694 }
695
696 pub fn get_pair(&self, logical_index: usize) -> UikaResult<(K, V)> {
698 let mut key_buf = [0u8; MAX_ELEM_BUF];
699 let mut key_written: u32 = 0;
700 let mut val_buf = [0u8; MAX_ELEM_BUF];
701 let mut val_written: u32 = 0;
702
703 check_ffi(unsafe {
704 ((*api().container).map_get_pair)(
705 self.owner,
706 self.prop,
707 logical_index as i32,
708 key_buf.as_mut_ptr(),
709 K::BUF_SIZE,
710 &mut key_written,
711 val_buf.as_mut_ptr(),
712 V::BUF_SIZE,
713 &mut val_written,
714 )
715 })?;
716 Ok(unsafe {
717 (
718 K::read_from_buf(key_buf.as_ptr(), key_written),
719 V::read_from_buf(val_buf.as_ptr(), val_written),
720 )
721 })
722 }
723
724 pub fn iter(&self) -> UeMapIter<'_, K, V> {
726 let len = self.len().unwrap_or(0);
727 UeMapIter {
728 map: self,
729 index: 0,
730 len,
731 }
732 }
733}
734
735impl<'a, K: ContainerElement, V: ContainerElement> IntoIterator for &'a UeMap<K, V> {
736 type Item = UikaResult<(K, V)>;
737 type IntoIter = UeMapIter<'a, K, V>;
738
739 fn into_iter(self) -> Self::IntoIter {
740 self.iter()
741 }
742}
743
744pub struct UeMapIter<'a, K: ContainerElement, V: ContainerElement> {
746 map: &'a UeMap<K, V>,
747 index: usize,
748 len: usize,
749}
750
751impl<K: ContainerElement, V: ContainerElement> Iterator for UeMapIter<'_, K, V> {
752 type Item = UikaResult<(K, V)>;
753
754 fn next(&mut self) -> Option<Self::Item> {
755 if self.index >= self.len {
756 return None;
757 }
758 let result = self.map.get_pair(self.index);
759 self.index += 1;
760 Some(result)
761 }
762
763 fn size_hint(&self) -> (usize, Option<usize>) {
764 let remaining = self.len.saturating_sub(self.index);
765 (remaining, Some(remaining))
766 }
767}
768
769impl<K: ContainerElement, V: ContainerElement> ExactSizeIterator for UeMapIter<'_, K, V> {}
770
771impl<K: ContainerElement, V: ContainerElement> UeMap<K, V> {
776 pub fn bulk_iter(&self) -> UikaResult<BulkMapIter<K, V>> {
778 let len = self.len()?;
779 if len == 0 {
780 return Ok(BulkMapIter {
781 buf: Vec::new(),
782 count: 0,
783 index: 0,
784 offset: 0,
785 _marker: PhantomData,
786 });
787 }
788 let owner = self.owner;
789 let prop = self.prop;
790 let estimate = len * (K::BUF_SIZE as usize + V::BUF_SIZE as usize + 8);
791 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
792 ((*api().container).map_copy_all)(owner, prop, out, size, written, cnt)
793 })?;
794 Ok(BulkMapIter {
795 buf,
796 count: count as usize,
797 index: 0,
798 offset: 0,
799 _marker: PhantomData,
800 })
801 }
802}
803
804impl<K: ContainerElement + Hash + Eq, V: ContainerElement> UeMap<K, V> {
805 pub fn to_hash_map(&self) -> UikaResult<HashMap<K, V>> {
807 let iter = self.bulk_iter()?;
808 let count = iter.count;
809 let mut map = HashMap::with_capacity(count);
810 for (k, v) in iter {
811 map.insert(k, v);
812 }
813 Ok(map)
814 }
815}
816
817#[derive(Clone, Copy)]
823pub struct UeSet<T: ContainerElement> {
824 owner: UObjectHandle,
825 prop: FPropertyHandle,
826 _marker: PhantomData<T>,
827}
828
829impl<T: ContainerElement> UeSet<T> {
830 #[inline]
831 pub fn new(owner: UObjectHandle, prop: FPropertyHandle) -> Self {
832 UeSet {
833 owner,
834 prop,
835 _marker: PhantomData,
836 }
837 }
838
839 pub fn len(&self) -> UikaResult<usize> {
841 let n = unsafe { ((*api().container).set_len)(self.owner, self.prop) };
842 if n < 0 {
843 return Err(UikaError::ObjectDestroyed);
844 }
845 Ok(n as usize)
846 }
847
848 pub fn is_empty(&self) -> UikaResult<bool> {
849 Ok(self.len()? == 0)
850 }
851
852 pub fn contains(&self, val: &T) -> UikaResult<bool> {
854 let mut buf = [0u8; MAX_ELEM_BUF];
855 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
856 Ok(unsafe {
857 ((*api().container).set_contains)(self.owner, self.prop, buf.as_ptr(), written)
858 })
859 }
860
861 pub fn add(&self, val: &T) -> UikaResult<()> {
863 let mut buf = [0u8; MAX_ELEM_BUF];
864 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
865 check_ffi(unsafe {
866 ((*api().container).set_add)(self.owner, self.prop, buf.as_ptr(), written)
867 })
868 }
869
870 pub fn remove(&self, val: &T) -> UikaResult<()> {
872 let mut buf = [0u8; MAX_ELEM_BUF];
873 let written = unsafe { val.write_to_buf(buf.as_mut_ptr()) };
874 check_ffi(unsafe {
875 ((*api().container).set_remove)(self.owner, self.prop, buf.as_ptr(), written)
876 })
877 }
878
879 pub fn clear(&self) -> UikaResult<()> {
881 check_ffi(unsafe { ((*api().container).set_clear)(self.owner, self.prop) })
882 }
883
884 pub fn get_element(&self, logical_index: usize) -> UikaResult<T> {
886 let mut buf = [0u8; MAX_ELEM_BUF];
887 let mut written: u32 = 0;
888 check_ffi(unsafe {
889 ((*api().container).set_get_element)(
890 self.owner,
891 self.prop,
892 logical_index as i32,
893 buf.as_mut_ptr(),
894 T::BUF_SIZE,
895 &mut written,
896 )
897 })?;
898 Ok(unsafe { T::read_from_buf(buf.as_ptr(), written) })
899 }
900
901 pub fn iter(&self) -> UeSetIter<'_, T> {
903 let len = self.len().unwrap_or(0);
904 UeSetIter {
905 set: self,
906 index: 0,
907 len,
908 }
909 }
910}
911
912impl<'a, T: ContainerElement> IntoIterator for &'a UeSet<T> {
913 type Item = UikaResult<T>;
914 type IntoIter = UeSetIter<'a, T>;
915
916 fn into_iter(self) -> Self::IntoIter {
917 self.iter()
918 }
919}
920
921pub struct UeSetIter<'a, T: ContainerElement> {
923 set: &'a UeSet<T>,
924 index: usize,
925 len: usize,
926}
927
928impl<T: ContainerElement> Iterator for UeSetIter<'_, T> {
929 type Item = UikaResult<T>;
930
931 fn next(&mut self) -> Option<Self::Item> {
932 if self.index >= self.len {
933 return None;
934 }
935 let result = self.set.get_element(self.index);
936 self.index += 1;
937 Some(result)
938 }
939
940 fn size_hint(&self) -> (usize, Option<usize>) {
941 let remaining = self.len.saturating_sub(self.index);
942 (remaining, Some(remaining))
943 }
944}
945
946impl<T: ContainerElement> ExactSizeIterator for UeSetIter<'_, T> {}
947
948impl<T: ContainerElement> UeSet<T> {
953 pub fn bulk_iter(&self) -> UikaResult<BulkSetIter<T>> {
955 let len = self.len()?;
956 if len == 0 {
957 return Ok(BulkSetIter {
958 buf: Vec::new(),
959 count: 0,
960 index: 0,
961 offset: 0,
962 _marker: PhantomData,
963 });
964 }
965 let owner = self.owner;
966 let prop = self.prop;
967 let estimate = len * (T::BUF_SIZE as usize + 4);
968 let (buf, count) = bulk_copy_with_retry(estimate, |out, size, written, cnt| unsafe {
969 ((*api().container).set_copy_all)(owner, prop, out, size, written, cnt)
970 })?;
971 Ok(BulkSetIter {
972 buf,
973 count: count as usize,
974 index: 0,
975 offset: 0,
976 _marker: PhantomData,
977 })
978 }
979}
980
981impl<T: ContainerElement + Hash + Eq> UeSet<T> {
982 pub fn to_hash_set(&self) -> UikaResult<HashSet<T>> {
984 let iter = self.bulk_iter()?;
985 let count = iter.count;
986 let mut set = HashSet::with_capacity(count);
987 for elem in iter {
988 set.insert(elem);
989 }
990 Ok(set)
991 }
992}
993
994pub struct OwnedStruct<T: UeStruct> {
1004 data: Vec<u8>,
1005 needs_destroy: bool,
1006 _marker: PhantomData<T>,
1007}
1008
1009impl<T: UeStruct> OwnedStruct<T> {
1010 pub fn new() -> Self {
1017 let ustruct = T::static_struct();
1018 let size = unsafe { ((*api().reflection).get_struct_size)(ustruct) };
1019 debug_assert!(size > 0, "get_struct_size returned 0 for {}", std::any::type_name::<T>());
1020 let mut data = vec![0u8; size as usize];
1021 ffi_infallible(unsafe {
1022 ((*api().reflection).initialize_struct)(ustruct, data.as_mut_ptr())
1023 });
1024 OwnedStruct {
1025 data,
1026 needs_destroy: true,
1027 _marker: PhantomData,
1028 }
1029 }
1030
1031 pub fn from_bytes(data: Vec<u8>) -> Self {
1036 OwnedStruct {
1037 data,
1038 needs_destroy: false,
1039 _marker: PhantomData,
1040 }
1041 }
1042
1043 pub fn as_ref(&self) -> UStructRef<T> {
1045 unsafe { UStructRef::from_raw(self.data.as_ptr() as *mut u8) }
1046 }
1047
1048 pub fn as_bytes(&self) -> &[u8] {
1050 &self.data
1051 }
1052}
1053
1054impl<T: UeStruct> Clone for OwnedStruct<T> {
1055 fn clone(&self) -> Self {
1056 OwnedStruct {
1057 data: self.data.clone(),
1058 needs_destroy: false,
1059 _marker: PhantomData,
1060 }
1061 }
1062}
1063
1064impl<T: UeStruct> Drop for OwnedStruct<T> {
1065 fn drop(&mut self) {
1066 if self.needs_destroy {
1067 unsafe {
1068 ((*api().reflection).destroy_struct)(
1069 T::static_struct(),
1070 self.data.as_mut_ptr(),
1071 );
1072 }
1073 }
1074 }
1075}
1076
1077impl<T: UeStruct> std::fmt::Debug for OwnedStruct<T> {
1078 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1079 f.debug_struct("OwnedStruct")
1080 .field("size", &self.data.len())
1081 .finish()
1082 }
1083}
1084
1085unsafe impl<T: UeStruct> ContainerElement for OwnedStruct<T> {
1089 const BUF_SIZE: u32 = 4096;
1090
1091 unsafe fn read_from_buf(buf: *const u8, written: u32) -> Self { unsafe {
1092 let mut data = vec![0u8; written as usize];
1093 std::ptr::copy_nonoverlapping(buf, data.as_mut_ptr(), written as usize);
1094 OwnedStruct {
1095 data,
1096 needs_destroy: false,
1097 _marker: PhantomData,
1098 }
1099 }}
1100
1101 unsafe fn write_to_buf(&self, buf: *mut u8) -> u32 { unsafe {
1102 let len = self.data.len();
1103 std::ptr::copy_nonoverlapping(self.data.as_ptr(), buf, len);
1104 len as u32
1105 }}
1106}