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