jni_glue/string_chars.rs
1use super::{*, jchar};
2use std::{char, slice, iter, mem::transmute};
3
4
5
6/// Represents an env.GetStringChars + env.GetStringLength query.
7/// Will automatically env.ReleaseStringChars when dropped.
8pub struct StringChars<'env> {
9 env: &'env Env,
10 string: jstring,
11 chars: *const jchar,
12 length: jsize, // in characters
13}
14
15impl<'env> StringChars<'env> {
16 /// Construct a StringChars from an Env + jstring.
17 pub unsafe fn from_env_jstring(env: &'env Env, string: jstring) -> Self {
18 debug_assert!(!string.is_null());
19
20 let chars = env.get_string_chars(string);
21 let length = env.get_string_length(string);
22
23 Self {
24 env,
25 string,
26 chars,
27 length,
28 }
29 }
30
31 /// Get an array of [jchar]s. Generally UTF16, but not guaranteed to be valid UTF16.
32 ///
33 /// [jchar]: struct.jchar.html
34 pub fn chars(&self) -> &[jchar] {
35 unsafe { slice::from_raw_parts(self.chars, self.length as usize) }
36 }
37
38 /// Get an array of [u16]s. Generally UTF16, but not guaranteed to be valid UTF16.
39 pub fn as_u16_slice(&self) -> &[u16] {
40 unsafe { transmute::<&[jchar], &[u16]>(self.chars()) }
41 }
42
43 /// std::char::[decode_utf16]\(...\)s these string characters.
44 ///
45 /// [decode_utf16]: https://doc.rust-lang.org/std/char/fn.decode_utf16.html
46 pub fn decode(&self) -> char::DecodeUtf16<iter::Cloned<slice::Iter<u16>>> {
47 char::decode_utf16(self.as_u16_slice().iter().cloned())
48 }
49
50 /// Returns a new [Ok]\([String]\), or an [Err]\([DecodeUtf16Error]\) if if it contained any invalid UTF16.
51 ///
52 /// [Ok]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Ok
53 /// [Err]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
54 /// [DecodeUtf16Error]: https://doc.rust-lang.org/std/char/struct.DecodeUtf16Error.html
55 /// [String]: https://doc.rust-lang.org/std/string/struct.String.html
56 /// [REPLACEMENT_CHARACTER]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html
57 pub fn to_string(&self) -> Result<String, char::DecodeUtf16Error> {
58 self.decode().collect()
59 }
60
61 /// Returns a new [String] with any invalid UTF16 characters replaced with [REPLACEMENT_CHARACTER]s (`'\u{FFFD}'`.)
62 ///
63 /// [String]: https://doc.rust-lang.org/std/string/struct.String.html
64 /// [REPLACEMENT_CHARACTER]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html
65 pub fn to_string_lossy(&self) -> String {
66 self.decode().map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER)).collect()
67 }
68}
69
70impl<'env> Drop for StringChars<'env> {
71 fn drop(&mut self) {
72 unsafe { self.env.release_string_chars(self.string, self.chars) };
73 }
74}