use crate::util::*;
use crate::reprc::ReprCBoolU32;
use core::convert::Infallible;
use core::fmt::{ self, Debug, Display, Write as _ };
use core::str::FromStr;
sys! {
"swift"
pub fn apple_apis_swift_string_drop(ptr: Ptr);
pub fn apple_apis_swift_string_new() -> Ptr;
pub fn apple_apis_swift_string_extend(
ptr: Ptr,
iter: Ptr,
len: usize,
advance_iter: extern "C" fn(Ptr) -> ReprCBoolU32
);
pub fn apple_apis_swift_string_iter_chars(
ptr: Ptr,
opaque_this: Ptr,
next_char: extern "C" fn(Ptr, u32)
);
}
wrapper! {
pub struct String;
new: sys::apple_apis_swift_string_new;
drop: sys::apple_apis_swift_string_drop;
}
impl String {
#[allow(clippy::should_implement_trait)]
pub fn from_str(s: &str) -> Self {
let string = String::new();
string.push_str(s);
string
}
pub fn push_str(&self, string: &str) {
use core::str::Chars;
let len = string.len();
let mut iter: Chars<'_> = string.chars();
extern "C" fn advance_iter(ptr: Ptr) -> ReprCBoolU32 {
let iter = unsafe { &mut *ptr.cast::<Chars<'_>>() };
match iter.next() {
Some(c) => { ReprCBoolU32 { val_bool: true, val_u32: c as _ } }
None => { ReprCBoolU32 { val_bool: false, val_u32: 0 } }
}
}
unsafe {
sys::apple_apis_swift_string_extend(
self.as_ptr(),
(&raw mut iter).cast(),
len,
advance_iter
);
}
}
}
impl Debug for String {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_char('"')?;
Display::fmt(&self, f)?;
f.write_char('"')?;
Ok(())
}
}
impl Display for String {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
struct Data<'f, 'h> {
f: &'f mut fmt::Formatter<'h>,
result: Result<(), fmt::Error>
}
extern "C" fn next_char(opaque_this: Ptr, char: u32) {
let char = unsafe { char::try_from(char).unwrap_unchecked() };
let Data { f, result } = unsafe { &mut *opaque_this.cast::<Data<'_, '_>>() };
*result = result.and_then(|_| f.write_char(char))
}
let mut data = Data { f, result: Ok(()) };
unsafe {
sys::apple_apis_swift_string_iter_chars(
self.as_ptr(),
(&raw mut data).cast(),
next_char
)
}
data.result
}
}
impl FromStr for String {
type Err = Infallible;
fn from_str(s: &str) -> Result<String, Infallible> {
Ok(Self::from_str(s))
}
}