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}