feat: v1.10.9, add se supprot
This commit is contained in:
110
swift-rs/src-rs/types/array.rs
Normal file
110
swift-rs/src-rs/types/array.rs
Normal file
@@ -0,0 +1,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()
|
||||
}
|
||||
}
|
||||
75
swift-rs/src-rs/types/data.rs
Normal file
75
swift-rs/src-rs/types/data.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
use crate::{
|
||||
swift::{self, SwiftObject},
|
||||
Int,
|
||||
};
|
||||
|
||||
use super::{array::SRArray, SRObject};
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
type Data = SRArray<u8>;
|
||||
|
||||
/// Convenience type for working with byte buffers,
|
||||
/// analagous to `SRData` in Swift.
|
||||
///
|
||||
/// ```rust
|
||||
/// use swift_rs::{swift, SRData};
|
||||
///
|
||||
/// swift!(fn get_data() -> SRData);
|
||||
///
|
||||
/// let data = unsafe { get_data() };
|
||||
///
|
||||
/// assert_eq!(data.as_ref(), &[1, 2, 3])
|
||||
/// ```
|
||||
/// [_corresponding Swift code_](https://github.com/Brendonovich/swift-rs/blob/07269e511f1afb71e2fcfa89ca5d7338bceb20e8/tests/swift-pkg/doctests.swift#L68)
|
||||
#[repr(transparent)]
|
||||
pub struct SRData(SRObject<Data>);
|
||||
|
||||
impl SRData {
|
||||
///
|
||||
pub fn as_slice(&self) -> &[u8] {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn to_vec(&self) -> Vec<u8> {
|
||||
self.as_slice().to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl SwiftObject for SRData {
|
||||
type Shape = Data;
|
||||
|
||||
fn get_object(&self) -> &SRObject<Self::Shape> {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for SRData {
|
||||
type Target = [u8];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for SRData {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u8]> for SRData {
|
||||
fn from(value: &[u8]) -> Self {
|
||||
unsafe { swift::data_from_bytes(value.as_ptr(), value.len() as Int) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl serde::Serialize for SRData {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_bytes(self)
|
||||
}
|
||||
}
|
||||
11
swift-rs/src-rs/types/mod.rs
Normal file
11
swift-rs/src-rs/types/mod.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
mod array;
|
||||
mod data;
|
||||
mod object;
|
||||
mod scalars;
|
||||
mod string;
|
||||
|
||||
pub use array::*;
|
||||
pub use data::*;
|
||||
pub use object::*;
|
||||
pub use scalars::*;
|
||||
pub use string::*;
|
||||
75
swift-rs/src-rs/types/object.rs
Normal file
75
swift-rs/src-rs/types/object.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
use crate::swift::{self, SwiftObject};
|
||||
use std::{ffi::c_void, ops::Deref, ptr::NonNull};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[repr(C)]
|
||||
pub struct SRObjectImpl<T> {
|
||||
_nsobject_offset: u8,
|
||||
data: T,
|
||||
}
|
||||
|
||||
/// Wrapper for arbitrary `NSObject` types.
|
||||
///
|
||||
/// When returning an `NSObject`, its Rust type must be wrapped in `SRObject`.
|
||||
/// The type must also be annotated with `#[repr(C)]` to ensure its memory layout
|
||||
/// is identical to its Swift counterpart's.
|
||||
///
|
||||
/// ```rust
|
||||
/// use swift_rs::{swift, SRObject, Int, Bool};
|
||||
///
|
||||
/// #[repr(C)]
|
||||
/// struct CustomObject {
|
||||
/// a: Int,
|
||||
/// b: Bool
|
||||
/// }
|
||||
///
|
||||
/// swift!(fn get_custom_object() -> SRObject<CustomObject>);
|
||||
///
|
||||
/// let value = unsafe { get_custom_object() };
|
||||
///
|
||||
/// let reference: &CustomObject = value.as_ref();
|
||||
/// ```
|
||||
/// [_corresponding Swift code_](https://github.com/Brendonovich/swift-rs/blob/07269e511f1afb71e2fcfa89ca5d7338bceb20e8/tests/swift-pkg/doctests.swift#L49)
|
||||
#[repr(transparent)]
|
||||
pub struct SRObject<T>(pub(crate) NonNull<SRObjectImpl<T>>);
|
||||
|
||||
impl<T> SwiftObject for SRObject<T> {
|
||||
type Shape = T;
|
||||
|
||||
fn get_object(&self) -> &SRObject<Self::Shape> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for SRObject<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &T {
|
||||
unsafe { &self.0.as_ref().data }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> AsRef<T> for SRObject<T> {
|
||||
fn as_ref(&self) -> &T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Drop for SRObject<T> {
|
||||
fn drop(&mut self) {
|
||||
unsafe { swift::release_object(self.0.as_ref() as *const _ as *const c_void) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<T> serde::Serialize for SRObject<T>
|
||||
where
|
||||
T: serde::Serialize,
|
||||
{
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
self.deref().serialize(serializer)
|
||||
}
|
||||
}
|
||||
34
swift-rs/src-rs/types/scalars.rs
Normal file
34
swift-rs/src-rs/types/scalars.rs
Normal file
@@ -0,0 +1,34 @@
|
||||
/// Swift's [`Bool`](https://developer.apple.com/documentation/swift/bool) type
|
||||
pub type Bool = bool;
|
||||
|
||||
/// Swift's [`Int`](https://developer.apple.com/documentation/swift/int) type
|
||||
pub type Int = isize;
|
||||
/// Swift's [`Int8`](https://developer.apple.com/documentation/swift/int8) type
|
||||
pub type Int8 = i8;
|
||||
/// Swift's [`Int16`](https://developer.apple.com/documentation/swift/int16) type
|
||||
pub type Int16 = i16;
|
||||
/// Swift's [`Int32`](https://developer.apple.com/documentation/swift/int32) type
|
||||
pub type Int32 = i32;
|
||||
/// Swift's [`Int64`](https://developer.apple.com/documentation/swift/int64) type
|
||||
pub type Int64 = i64;
|
||||
|
||||
/// Swift's [`UInt`](https://developer.apple.com/documentation/swift/uint) type
|
||||
pub type UInt = usize;
|
||||
/// Swift's [`UInt8`](https://developer.apple.com/documentation/swift/uint8) type
|
||||
pub type UInt8 = u8;
|
||||
/// Swift's [`UInt16`](https://developer.apple.com/documentation/swift/uint16) type
|
||||
pub type UInt16 = u16;
|
||||
/// Swift's [`UInt32`](https://developer.apple.com/documentation/swift/uint32) type
|
||||
pub type UInt32 = u32;
|
||||
/// Swift's [`UInt64`](https://developer.apple.com/documentation/swift/uint64) type
|
||||
pub type UInt64 = u64;
|
||||
|
||||
/// Swift's [`Float`](https://developer.apple.com/documentation/swift/float) type
|
||||
pub type Float = f32;
|
||||
/// Swift's [`Double`](https://developer.apple.com/documentation/swift/double) type
|
||||
pub type Double = f64;
|
||||
|
||||
/// Swift's [`Float32`](https://developer.apple.com/documentation/swift/float32) type
|
||||
pub type Float32 = f32;
|
||||
/// Swift's [`Float64`](https://developer.apple.com/documentation/swift/float64) type
|
||||
pub type Float64 = f64;
|
||||
84
swift-rs/src-rs/types/string.rs
Normal file
84
swift-rs/src-rs/types/string.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use std::{
|
||||
fmt::{Display, Error, Formatter},
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
swift::{self, SwiftObject},
|
||||
Int, SRData, SRObject,
|
||||
};
|
||||
|
||||
/// String type that can be shared between Swift and Rust.
|
||||
///
|
||||
/// ```rust
|
||||
/// use swift_rs::{swift, SRString};
|
||||
///
|
||||
/// swift!(fn get_greeting(name: &SRString) -> SRString);
|
||||
///
|
||||
/// let greeting = unsafe { get_greeting(&"Brendan".into()) };
|
||||
///
|
||||
/// assert_eq!(greeting.as_str(), "Hello Brendan!");
|
||||
/// ```
|
||||
/// [_corresponding Swift code_](https://github.com/Brendonovich/swift-rs/blob/07269e511f1afb71e2fcfa89ca5d7338bceb20e8/tests/swift-pkg/doctests.swift#L56)
|
||||
#[repr(transparent)]
|
||||
pub struct SRString(SRData);
|
||||
|
||||
impl SRString {
|
||||
pub fn as_str(&self) -> &str {
|
||||
unsafe { std::str::from_utf8_unchecked(&self.0) }
|
||||
}
|
||||
}
|
||||
|
||||
impl SwiftObject for SRString {
|
||||
type Shape = <SRData as SwiftObject>::Shape;
|
||||
|
||||
fn get_object(&self) -> &SRObject<Self::Shape> {
|
||||
self.0.get_object()
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for SRString {
|
||||
type Target = str;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for SRString {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.0.as_ref()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for SRString {
|
||||
fn from(string: &str) -> Self {
|
||||
unsafe { swift::string_from_bytes(string.as_ptr(), string.len() as Int) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for SRString {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
|
||||
self.as_str().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl serde::Serialize for SRString {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
serializer.serialize_str(self.as_str())
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'a> serde::Deserialize<'a> for SRString {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'a>,
|
||||
{
|
||||
let string = String::deserialize(deserializer)?;
|
||||
Ok(SRString::from(string.as_str()))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user