#[cfg(feature = "NSObjCRuntime")] use core::cmp; use core::ffi::c_void; use core::fmt; use core::ops::AddAssign; use core::panic::RefUnwindSafe; use core::panic::UnwindSafe; use core::str;
use objc2::msg_send; use objc2::rc::{autoreleasepool_leaking, Allocated, AutoreleasePool, Retained}; use objc2::runtime::__nsstring::{nsstring_len, nsstring_to_str, UTF8_ENCODING}; use objc2::{AnyThread, Message};
// Even if an exception occurs inside a string method, the state of the string // (should) still be perfectly safe to access. impl UnwindSafe for NSString {} impl RefUnwindSafe for NSString {}
impl NSString { /// The number of UTF-8 code units in `self`. #[doc(alias = "lengthOfBytesUsingEncoding")] #[doc(alias = "lengthOfBytesUsingEncoding:")] pubfn len(&self) -> usize { // SAFETY: This is an instance of `NSString` unsafe { nsstring_len(self) }
}
/// The number of UTF-16 code units in the string. /// /// See also [`NSString::len`]. #[doc(alias = "length")] pubfn len_utf16(&self) -> usize { self.length()
}
pubfn is_empty(&self) -> bool { // TODO: lengthOfBytesUsingEncoding: might sometimes return 0 for // other reasons, so this is not really correct! self.len() == 0
}
/// Convert the string into a [string slice](`prim@str`). /// /// The signature of this method can be a bit confusing, as it contains /// several lifetimes; the lifetime `'s` of the `NSString`, the lifetime /// `'p` of the current autorelease pool and the lifetime `'r` of the /// returned string slice. /// /// In general, this method converts the string to a newly allocated UTF-8 /// string, autoreleases the buffer, and returns a slice pointer to this /// internal buffer, which will become invalid once the autorelease pool /// is popped. So the lifetime of the return value is bound to the current /// autorelease pool. /// /// However, as an optimization, this method may choose to instead return /// an internal reference to the `NSString` when it can, and when the /// string is immutable, and that is why the lifetime of the returned /// string slice is also bound to the string itself. /// /// You should prefer the [`to_string`] method or the /// [`Display` implementation][display-impl] over this method when /// possible. /// /// [`to_string`]: alloc::string::ToString::to_string /// [display-impl]: NSString#impl-Display-for-NSString /// /// /// # Safety /// /// The pool must be the innermost pool, see [the documentation on /// `autoreleasepool`][autoreleasepool]. /// /// [autoreleasepool]: objc2::rc::autoreleasepool /// /// /// # Examples /// /// Get the string slice of the `NSString`, and compare it with another /// inside an autorelease pool. /// /// ``` /// use objc2_foundation::NSString; /// use objc2::rc::autoreleasepool; /// /// let string = NSString::from_str("foo"); /// autoreleasepool(|pool| { /// // SAFETY: The str is not used outside the autorelease pool. /// assert_eq!(unsafe { string.to_str(pool) }, "foo"); /// }); /// ``` #[doc(alias = "UTF8String")] pubunsafefn to_str<'r, 's: 'r, 'p: 'r>(&'s self, pool: AutoreleasePool<'p>) -> &'r str { // SAFETY: This is an instance of `NSString`. // // Caller upholds that the string is not moved outside the pool. unsafe { nsstring_to_str(self, pool) }
}
// TODO: Allow usecases where the NUL byte from `UTF8String` is kept?
/// Creates an immutable `NSString` by copying the given string slice. /// /// Prefer using the [`ns_string!`] macro when possible. /// /// [`ns_string!`]: crate::ns_string #[doc(alias = "initWithBytes")] #[doc(alias = "initWithBytes:length:encoding:")] #[allow(clippy::should_implement_trait)] // Not really sure of a better name pubfn from_str(string: &str) -> Retained<Self> { unsafe { init_with_str(Self::alloc(), string) }
}
// TODO: `initWithBytesNoCopy:length:encoding:` from `&'static str`.
}
impl NSMutableString { /// Creates a new [`NSMutableString`] by copying the given string slice. #[doc(alias = "initWithBytes:length:encoding:")] #[allow(clippy::should_implement_trait)] // Not really sure of a better name pubfn from_str(string: &str) -> Retained<Self> { unsafe { init_with_str(Self::alloc(), string) }
}
}
unsafefn init_with_str<T: Message>(obj: Allocated<T>, string: &str) -> Retained<T> { let bytes: *const c_void = string.as_ptr().cast(); // We use `msg_send!` instead of the generated method, since that // assumes the encoding is `usize`, whereas GNUStep assumes `i32`. unsafe {
msg_send![
obj,
initWithBytes: bytes,
length: string.len(),
encoding: UTF8_ENCODING,
]
}
}
impl fmt::Display for NSString { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // SAFETY: The object is an instance of `NSString`. unsafe { util::display_string(self, f) }
}
}
impl fmt::Debug for NSString { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // SAFETY: Same as for `display_string`: // - The object is an instance of `NSString`. // - We control the scope in which the string is alive, so we know // it is not moved outside the current autorelease pool.
autoreleasepool_leaking(|pool| fmt::Debug::fmt(unsafe { nsstring_to_str(self, pool) }, f))
}
}
impl fmt::Write for &NSMutableString { fn write_str(&mutself, s: &str) -> fmt::Result { let nsstring = NSString::from_str(s); self.appendString(&nsstring);
Ok(())
}
}
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.3Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.