swift_rs/types/array.rs
1use std::{ops::Deref, ptr::NonNull};
2
3use crate::swift::SwiftObject;
4
5use super::SRObject;
6
7/// Wrapper of [`SRArray`] exclusively for arrays of objects.
8/// Equivalent to `SRObjectArray` in Swift.
9// SRArray is wrapped in SRObject since the Swift implementation extends NSObject
10pub type SRObjectArray<T> = SRObject<SRArray<SRObject<T>>>;
11
12#[doc(hidden)]
13#[repr(C)]
14pub struct SRArrayImpl<T> {
15 data: NonNull<T>,
16 length: usize,
17}
18
19/// General array type for objects and scalars.
20///
21/// ## Returning Directly
22///
23/// When returning an `SRArray` from a Swift function,
24/// you will need to wrap it in an `NSObject` class since
25/// Swift doesn't permit returning generic types from `@_cdecl` functions.
26/// To account for the wrapping `NSObject`, the array must be wrapped
27/// in `SRObject` on the Rust side.
28///
29/// ```rust
30/// use swift_rs::{swift, SRArray, SRObject, Int};
31///
32/// swift!(fn get_int_array() -> SRObject<SRArray<Int>>);
33///
34/// let array = unsafe { get_int_array() };
35///
36/// assert_eq!(array.as_slice(), &[1, 2, 3])
37/// ```
38/// [_corresponding Swift code_](https://github.com/Brendonovich/swift-rs/blob/07269e511f1afb71e2fcfa89ca5d7338bceb20e8/tests/swift-pkg/doctests.swift#L19)
39///
40/// ## Returning in a Struct fIeld
41///
42/// When returning an `SRArray` from a custom struct that is itself an `NSObject`,
43/// the above work is already done for you.
44/// Assuming your custom struct is already wrapped in `SRObject` in Rust,
45/// `SRArray` will work normally.
46///
47/// ```rust
48/// use swift_rs::{swift, SRArray, SRObject, Int};
49///
50/// #[repr(C)]
51/// struct ArrayStruct {
52/// array: SRArray<Int>
53/// }
54///
55/// swift!(fn get_array_struct() -> SRObject<ArrayStruct>);
56///
57/// let data = unsafe { get_array_struct() };
58///
59/// assert_eq!(data.array.as_slice(), &[4, 5, 6]);
60/// ```
61/// [_corresponding Swift code_](https://github.com/Brendonovich/swift-rs/blob/07269e511f1afb71e2fcfa89ca5d7338bceb20e8/tests/swift-pkg/doctests.swift#L32)
62#[repr(transparent)]
63pub struct SRArray<T>(SRObject<SRArrayImpl<T>>);
64
65impl<T> SRArray<T> {
66 pub fn as_slice(&self) -> &[T] {
67 self.0.as_slice()
68 }
69}
70
71impl<T> SwiftObject for SRArray<T> {
72 type Shape = SRArrayImpl<T>;
73
74 fn get_object(&self) -> &SRObject<Self::Shape> {
75 &self.0
76 }
77}
78
79impl<T> Deref for SRArray<T> {
80 type Target = [T];
81
82 fn deref(&self) -> &Self::Target {
83 self.0.as_slice()
84 }
85}
86
87impl<T> SRArrayImpl<T> {
88 pub fn as_slice(&self) -> &[T] {
89 unsafe { std::slice::from_raw_parts(self.data.as_ref(), self.length) }
90 }
91}
92
93#[cfg(feature = "serde")]
94impl<T> serde::Serialize for SRArray<T>
95where
96 T: serde::Serialize,
97{
98 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
99 where
100 S: serde::Serializer,
101 {
102 use serde::ser::SerializeSeq;
103
104 let mut seq = serializer.serialize_seq(Some(self.len()))?;
105 for item in self.iter() {
106 seq.serialize_element(item)?;
107 }
108 seq.end()
109 }
110}