• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use std::{
2     borrow::{Borrow, Cow, ToOwned},
3     ffi,
4     os::raw::c_char,
5 };
6 
7 use cesu8::{from_java_cesu8, to_java_cesu8};
8 use log::debug;
9 
10 use crate::wrapper::strings::ffi_str;
11 
12 /// Wrapper for `std::ffi::CString` that also takes care of encoding between
13 /// UTF-8 and Java's Modified UTF-8. As with `CString`, this implements `Deref`
14 /// to `&JNIStr`.
15 pub struct JNIString {
16     internal: ffi::CString,
17 }
18 
19 /// Wrapper for `std::ffi::CStr` that also takes care of encoding between
20 /// UTF-8 and Java's Modified UTF-8.
21 pub struct JNIStr {
22     internal: ffi::CStr,
23 }
24 
25 impl ::std::ops::Deref for JNIString {
26     type Target = JNIStr;
27 
deref(&self) -> &Self::Target28     fn deref(&self) -> &Self::Target {
29         unsafe { &*(self.internal.as_bytes_with_nul() as *const [u8] as *const ffi_str::JNIStr) }
30     }
31 }
32 
33 impl ::std::ops::Deref for JNIStr {
34     type Target = ffi::CStr;
35 
deref(&self) -> &Self::Target36     fn deref(&self) -> &Self::Target {
37         &self.internal
38     }
39 }
40 
41 impl<T> From<T> for JNIString
42 where
43     T: AsRef<str>,
44 {
from(other: T) -> Self45     fn from(other: T) -> Self {
46         let enc = to_java_cesu8(other.as_ref()).into_owned();
47         JNIString {
48             internal: unsafe { ffi::CString::from_vec_unchecked(enc) },
49         }
50     }
51 }
52 
53 impl<'a> From<&'a JNIStr> for Cow<'a, str> {
from(other: &'a JNIStr) -> Cow<'a, str>54     fn from(other: &'a JNIStr) -> Cow<'a, str> {
55         let bytes = other.to_bytes();
56         match from_java_cesu8(bytes) {
57             Ok(s) => s,
58             Err(e) => {
59                 debug!("error decoding java cesu8: {:#?}", e);
60                 String::from_utf8_lossy(bytes)
61             }
62         }
63     }
64 }
65 
66 impl From<JNIString> for String {
from(other: JNIString) -> String67     fn from(other: JNIString) -> String {
68         Cow::from(other.borrowed()).into_owned()
69     }
70 }
71 
72 impl JNIString {
73     /// Get the borrowed version of the JNIString. Equivalent to
74     /// `CString::borrowed`.
borrowed(&self) -> &JNIStr75     pub fn borrowed(&self) -> &JNIStr {
76         self
77     }
78 }
79 
80 impl JNIStr {
81     /// Construct a reference to a `JNIStr` from a pointer. Equivalent to `CStr::from_ptr`.
82     ///
83     /// # Safety
84     ///
85     /// Expects a valid pointer to a null-terminated C string and does not perform any lifetime
86     /// checks for the resulting value.
from_ptr<'a>(ptr: *const c_char) -> &'a JNIStr87     pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a JNIStr {
88         &*(ffi::CStr::from_ptr(ptr) as *const ffi::CStr as *const ffi_str::JNIStr)
89     }
90 }
91 
92 // impls for CoW
93 impl Borrow<JNIStr> for JNIString {
borrow(&self) -> &JNIStr94     fn borrow(&self) -> &JNIStr {
95         self
96     }
97 }
98 
99 impl ToOwned for JNIStr {
100     type Owned = JNIString;
101 
to_owned(&self) -> JNIString102     fn to_owned(&self) -> JNIString {
103         unsafe {
104             JNIString {
105                 internal: ffi::CString::from_vec_unchecked(self.to_bytes().to_vec()),
106             }
107         }
108     }
109 }
110