1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use Deref;
use c_char;
use CStr;
use *;
/// An error indicating that nul byte was not in the expected position
///
/// The `str` used to create a `Mutf8CStr` did not have a nul byte, positioned at the end.
///
/// This error is created by the `Mutf8CStr::from_str_nul_terminated` method. See its documentation for more.
/// A nul-terminated Modified UTF-8 string, valid for use with JNI
/// Representation of a borrowed Mutf8 C string.
///
/// This type represents a borrowed reference to a nul-terminated
/// array of bytes. It can be constructed safely from a <code>&[[u8]]</code>
/// slice, or unsafely from a raw `*const c_char`. It can then be
/// converted to a Rust <code>&[str]</code> by performing UTF-8 validation, or
/// into an owned [`String`]/[`CString`]/[`Mutf8CString`].
///
/// `&Mutf8CStr` is to [`Mutf8CString`] as <code>&[str]</code> is to [`String`]: the former
/// in each pair are borrowed references; the latter are owned
/// strings.
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead, safe wrappers of FFI
/// functions may leverage the unsafe [`Mutf8CStr::from_ptr`] constructor to provide
/// a safe interface to other consumers.
///
/// [`CString`]: ::std::ffi::CString
/// [`String`]: ::std::string::String
///
/// # Examples
///
/// Inspecting a foreign C string:
///
/// ```ignore (extern-declaration)
/// use std::ffi::CStr;
/// use std::os::raw::c_char;
///
/// extern "C" { fn my_jni_string() -> *const c_char; }
///
/// unsafe {
/// let slice = Mutf8CStr::from_ptr(my_string());
/// println!("string buffer size without nul terminator: {}", slice.to_bytes().len());
/// }
/// ```
///
/// Passing a Rust-originating C string:
///
/// ```ignore (extern-declaration)
/// use std::ffi::{CString, CStr};
/// use std::os::raw::c_char;
///
/// fn work(data: &Mutf8CStr) {
/// extern "C" { fn work_with(data: *const c_char); }
///
/// unsafe { work_with(data.as_ptr()) }
/// }
///
/// let s = Mutf8CString::new("data data data data").expect("CString::new failed");
/// work(&s);
/// ```
///
/// Converting a foreign C string into a Rust `String`:
///
/// ```ignore (extern-declaration)
/// use std::ffi::CStr;
/// use std::os::raw::c_char;
///
/// extern "C" { fn my_jni_string() -> *const c_char; }
///
/// fn my_string_safe() -> String {
/// let cstr = unsafe { Mutf8CStr::from_ptr(my_string()) };
/// // Get copy-on-write Cow<'_, str>, then guarantee a freshly-owned String allocation
/// Mutf8CString::from_utf8_lossy(cstr.to_bytes()).to_string()
/// }
///
/// println!("string: {}", my_string_safe());
/// ```
///
/// [str]: prim@str "str"