summaryrefslogtreecommitdiffstats
path: root/vendor/core-foundation/src/string.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:41:41 +0000
commit10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87 (patch)
treebdffd5d80c26cf4a7a518281a204be1ace85b4c1 /vendor/core-foundation/src/string.rs
parentReleasing progress-linux version 1.70.0+dfsg1-9~progress7.99u1. (diff)
downloadrustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.tar.xz
rustc-10ee2acdd26a7f1298c6f6d6b7af9b469fe29b87.zip
Merging upstream version 1.70.0+dfsg2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/core-foundation/src/string.rs')
-rw-r--r--vendor/core-foundation/src/string.rs197
1 files changed, 197 insertions, 0 deletions
diff --git a/vendor/core-foundation/src/string.rs b/vendor/core-foundation/src/string.rs
new file mode 100644
index 000000000..3f5994bc5
--- /dev/null
+++ b/vendor/core-foundation/src/string.rs
@@ -0,0 +1,197 @@
+// Copyright 2013 The Servo Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Immutable strings.
+
+pub use core_foundation_sys::string::*;
+
+use base::{CFIndexConvertible, TCFType};
+
+use core_foundation_sys::base::{Boolean, CFIndex, CFRange};
+use core_foundation_sys::base::{kCFAllocatorDefault, kCFAllocatorNull};
+use std::borrow::Cow;
+use std::fmt;
+use std::str::{self, FromStr};
+use std::ptr;
+use std::ffi::CStr;
+
+
+declare_TCFType!{
+ /// An immutable string in one of a variety of encodings.
+ CFString, CFStringRef
+}
+impl_TCFType!(CFString, CFStringRef, CFStringGetTypeID);
+
+impl FromStr for CFString {
+ type Err = ();
+
+ /// See also CFString::new for a variant of this which does not return a Result
+ #[inline]
+ fn from_str(string: &str) -> Result<CFString, ()> {
+ Ok(CFString::new(string))
+ }
+}
+
+impl<'a> From<&'a str> for CFString {
+ #[inline]
+ fn from(string: &'a str) -> CFString {
+ CFString::new(string)
+ }
+}
+
+impl<'a> From<&'a CFString> for Cow<'a, str> {
+ fn from(cf_str: &'a CFString) -> Cow<'a, str> {
+ unsafe {
+ // Do this without allocating if we can get away with it
+ let c_string = CFStringGetCStringPtr(cf_str.0, kCFStringEncodingUTF8);
+ if !c_string.is_null() {
+ let c_str = CStr::from_ptr(c_string);
+ Cow::Borrowed(str::from_utf8_unchecked(c_str.to_bytes()))
+ } else {
+ let char_len = cf_str.char_len();
+
+ // First, ask how big the buffer ought to be.
+ let mut bytes_required: CFIndex = 0;
+ CFStringGetBytes(cf_str.0,
+ CFRange { location: 0, length: char_len },
+ kCFStringEncodingUTF8,
+ 0,
+ false as Boolean,
+ ptr::null_mut(),
+ 0,
+ &mut bytes_required);
+
+ // Then, allocate the buffer and actually copy.
+ let mut buffer = vec![b'\x00'; bytes_required as usize];
+
+ let mut bytes_used: CFIndex = 0;
+ let chars_written = CFStringGetBytes(cf_str.0,
+ CFRange { location: 0, length: char_len },
+ kCFStringEncodingUTF8,
+ 0,
+ false as Boolean,
+ buffer.as_mut_ptr(),
+ buffer.len().to_CFIndex(),
+ &mut bytes_used);
+ assert_eq!(chars_written, char_len);
+
+ // This is dangerous; we over-allocate and null-terminate the string (during
+ // initialization).
+ assert_eq!(bytes_used, buffer.len().to_CFIndex());
+ Cow::Owned(String::from_utf8_unchecked(buffer))
+ }
+ }
+ }
+}
+
+impl fmt::Display for CFString {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ fmt.write_str(&Cow::from(self))
+ }
+}
+
+impl fmt::Debug for CFString {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "\"{}\"", self)
+ }
+}
+
+
+impl CFString {
+ /// Creates a new `CFString` instance from a Rust string.
+ #[inline]
+ pub fn new(string: &str) -> CFString {
+ unsafe {
+ let string_ref = CFStringCreateWithBytes(kCFAllocatorDefault,
+ string.as_ptr(),
+ string.len().to_CFIndex(),
+ kCFStringEncodingUTF8,
+ false as Boolean);
+ CFString::wrap_under_create_rule(string_ref)
+ }
+ }
+
+ /// Like `CFString::new`, but references a string that can be used as a backing store
+ /// by virtue of being statically allocated.
+ #[inline]
+ pub fn from_static_string(string: &'static str) -> CFString {
+ unsafe {
+ let string_ref = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
+ string.as_ptr(),
+ string.len().to_CFIndex(),
+ kCFStringEncodingUTF8,
+ false as Boolean,
+ kCFAllocatorNull);
+ TCFType::wrap_under_create_rule(string_ref)
+ }
+ }
+
+ /// Returns the number of characters in the string.
+ #[inline]
+ pub fn char_len(&self) -> CFIndex {
+ unsafe {
+ CFStringGetLength(self.0)
+ }
+ }
+}
+
+impl<'a> PartialEq<&'a str> for CFString {
+ fn eq(&self, other: &&str) -> bool {
+ unsafe {
+ let temp = CFStringCreateWithBytesNoCopy(kCFAllocatorDefault,
+ other.as_ptr(),
+ other.len().to_CFIndex(),
+ kCFStringEncodingUTF8,
+ false as Boolean,
+ kCFAllocatorNull);
+ self.eq(&CFString::wrap_under_create_rule(temp))
+ }
+ }
+}
+
+impl<'a> PartialEq<CFString> for &'a str {
+ #[inline]
+ fn eq(&self, other: &CFString) -> bool {
+ other.eq(self)
+ }
+}
+
+impl PartialEq<CFString> for String {
+ #[inline]
+ fn eq(&self, other: &CFString) -> bool {
+ other.eq(&self.as_str())
+ }
+}
+
+impl PartialEq<String> for CFString {
+ #[inline]
+ fn eq(&self, other: &String) -> bool {
+ self.eq(&other.as_str())
+ }
+}
+
+#[test]
+fn str_cmp() {
+ let cfstr = CFString::new("hello");
+ assert_eq!("hello", cfstr);
+ assert_eq!(cfstr, "hello");
+ assert_ne!(cfstr, "wrong");
+ assert_ne!("wrong", cfstr);
+ let hello = String::from("hello");
+ assert_eq!(hello, cfstr);
+ assert_eq!(cfstr, hello);
+}
+
+#[test]
+fn string_and_back() {
+ let original = "The quick brown fox jumped over the slow lazy dog.";
+ let cfstr = CFString::from_static_string(original);
+ let converted = cfstr.to_string();
+ assert_eq!(converted, original);
+}