skia_safe/interop/
string.rs

1#![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}