skia_safe/interop/
string.rs1#![allow(dead_code)]
2use std::{fmt, str};
3
4use crate::prelude::*;
5use skia_bindings::{self as sb, SkString};
6
7pub type String = Handle<SkString>;
8unsafe_send_sync!(String);
9
10impl NativeDrop for SkString {
11 fn drop(&mut self) {
12 unsafe {
13 sb::C_SkString_destruct(self);
14 }
15 }
16}
17
18impl NativeClone for SkString {
19 fn clone(&self) -> Self {
20 construct(|unitialized| unsafe { sb::C_SkString_CopyConstruct(unitialized, self) })
21 }
22}
23
24impl AsRef<str> for String {
25 fn as_ref(&self) -> &str {
26 self.as_str()
27 }
28}
29
30impl fmt::Display for String {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 self.as_str().fmt(f)
33 }
34}
35
36impl Default for String {
37 fn default() -> Self {
38 Self::from_str("")
39 }
40}
41
42impl fmt::Debug for String {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 self.as_str().fmt(f)
45 }
46}
47
48impl String {
49 #[allow(clippy::should_implement_trait)]
50 pub fn from_str(str: impl AsRef<str>) -> String {
51 let bytes = str.as_ref().as_bytes();
52 Handle::from_native_c(unsafe { SkString::new3(bytes.as_ptr() as _, bytes.len()) })
53 }
54
55 pub fn as_str(&self) -> &str {
56 self.native().as_str()
57 }
58}
59
60pub trait AsStr {
61 fn as_str(&self) -> &str;
62}
63
64impl AsStr for Handle<SkString> {
65 fn as_str(&self) -> &str {
66 self.native().as_str()
67 }
68}
69
70impl AsStr for SkString {
71 fn as_str(&self) -> &str {
72 let mut size = 0;
73 let slice = unsafe {
74 let ptr = sb::C_SkString_c_str_size(self, &mut size) as *const u8;
75 safer::from_raw_parts(ptr, size)
76 };
77 std::str::from_utf8(slice).unwrap_or_default()
78 }
79}
80
81impl AsStr for sb::std_string_view {
82 fn as_str(&self) -> &str {
83 let slice = unsafe {
84 let mut size = 0;
85 let ptr = sb::C_string_view_ptr_size(self, &mut size) as *const u8;
86 safer::from_raw_parts(ptr, size)
87 };
88 str::from_utf8(slice).unwrap_or_default()
89 }
90}
91
92impl AsStr for sb::std_string {
93 fn as_str(&self) -> &str {
94 let slice = unsafe {
95 let mut size = 0;
96 let ptr = sb::C_string_ptr_size(self, &mut size) as *const u8;
97 safer::from_raw_parts(ptr, size)
98 };
99 str::from_utf8(slice).unwrap_or_default()
100 }
101}
102
103pub trait SetStr {
104 fn set_str(&mut self, str: impl AsRef<str>);
105}
106
107impl SetStr for Handle<SkString> {
108 fn set_str(&mut self, str: impl AsRef<str>) {
109 self.native_mut().set_str(str)
110 }
111}
112
113impl SetStr for SkString {
114 fn set_str(&mut self, str: impl AsRef<str>) {
115 let bytes = str.as_ref().as_bytes();
116 unsafe { self.set1(bytes.as_ptr() as _, bytes.len()) }
117 }
118}
119
120pub trait FromStrs {
121 fn from_strs(strings: &[impl AsRef<str>]) -> Self;
122}
123
124impl FromStrs for Vec<String> {
125 fn from_strs(strings: &[impl AsRef<str>]) -> Self {
126 strings
127 .iter()
128 .map(|s| String::from_str(s.as_ref()))
129 .collect()
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::{SetStr, String};
136
137 #[test]
138 fn string_from_rust_and_back() {
139 let str = "Hello";
140 let string = String::from_str(str);
141 assert_eq!(str, string.as_str())
142 }
143
144 #[test]
145 fn set_string() {
146 let mut hello = String::from_str("Hello");
147 hello.set_str(String::from_str("World"));
148 assert_eq!("World", hello.as_str());
149 }
150}