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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
//! Provides C-compatible interfaces to `mangle` and `demangle` functions.
//!
//! Although the code is written such that it should be possible to mangle and demangle in-place
//! (using the same location for in- and out-pointers), the declaration of the parameter types
//! (using Rust references) prohibits such aliasing, so it is not safe to do so. If significant
//! cause is found to support processing in place, the Rust function declaration could potentially
//! be changed (without changing the C interface) to allow it.
use ;
use crate::;
/// Provides a C-compatible interface to the `mangle` function.
///
/// This function is compatible with the C function declaration:
/// ```c
/// int mangling_mangle(size_t insize, const char *inptr, size_t *outsize, char *outstr);
/// ```
///
/// This function:
/// - returns a zero value upon success and a non-zero value on failure,
/// - has well-defined behavior for any combination of null pointer arguments,
/// - writes a sequence of non-NUL bytes into a buffer provided by the caller,
/// - writes no more bytes than specified in `outsize`, and
/// - updates the size referenced by `outsize` with the number of bytes copied through `outstr`.
///
/// A failure is indicated with a non-zero exit code under the following conditions:
/// - a null pointer was passed in for the `inptr` argument but the `insize` is nonzero.
///
/// It is not an error to supply an output buffer that is too small; in such a case, the output
/// will simply be truncated to the provided length.
///
/// The output is never NUL-terminated. If NUL termination is desired, and the `outstr` buffer is
/// big enough, simply perform `outstr[*outsize] = '\0';` after `mangling_mangle`.
///
/// # Examples
/// Some of the examples below are shown in (doctested) Rust code to demonstrate correctness, but
/// it is not expected that Rust users will use the C interfaces.
///
/// Null pointers (`None` in the Rust interface) are not inherently erroneous:
/// ```
/// # use mangling::clib::*;
/// let success = mangling_mangle(0, None, None, None);
/// assert_eq!(0, success);
/// ```
/// This behavior can be used to determine the correct size of buffer to allocate (here
/// demonstrated with Rust code):
/// ```
/// # use mangling::clib::*;
/// # use std::os::raw::c_char;
/// let input = "hello, world";
/// let mut len = std::usize::MAX;
/// let inptr = unsafe { &*(input.as_ptr() as *const c_char) };
/// let success = mangling_mangle(input.len(), Some(inptr), Some(&mut len), None);
/// assert_eq!(0, success);
///
/// // Now the required buffer size is known in `len` and can be used for allocation
/// let mut v: Vec<u8> = Vec::with_capacity(len);
/// let outptr = unsafe { &mut *(v.as_mut_ptr() as *mut c_char) };
/// let success = mangling_mangle(input.len(), Some(inptr), Some(&mut len), Some(outptr));
/// unsafe { v.set_len(len); }
/// assert_eq!(&v[..], "_5hello02_2c205world".as_bytes());
/// assert_eq!(0, success);
/// ```
/// Similar C code might look like this:
/// ```c
/// size_t need = -1;
/// int rc = mangling_mangle(strlen(input), input, &need, NULL);
/// if (rc != 0) return;
/// char *buf = malloc(need);
/// rc = mangling_mangle(strlen(input), input, &need, buf);
/// ```
///
/// However, if the `insize` parameter indicates that some data should be expected, then a null
/// pointer is an error, though still safe:
/// ```
/// # use mangling::clib::*;
/// let success = mangling_mangle(1, None, None, None);
/// assert_ne!(0, success);
/// ```
///
/// In C, if the output buffer is sized safely according to the bounds specified in the `mangle`
/// documentation, then a mangling call can be as simple as the following:
/// ```c
/// char input[16] = "hello, world",
/// char result[1 + 5 * sizeof input]; // Worst-case length
/// size_t outsize = sizeof result;
/// int success = mangling_mangle(strlen(input), input, &outsize, result);
/// fwrite(result, 1, outsize, stdout);
/// ```
pub extern "C"
/// Provides a C-compatible interface to the `demangle` function.
///
/// This function is compatible with the C function declaration:
/// ```c
/// int mangling_demangle(size_t insize, const char *instr, size_t *outsize, char *outptr);
/// ```
///
/// This function:
/// - returns a zero value upon success and a non-zero value on failure,
/// - has well-defined behavior for any combination of null pointer arguments,
/// - places its output into a buffer provided by the caller,
/// - produces a sequence of arbitrary bytes, possibly including embedded NULs,
/// - writes no more bytes than specified by the caller via `outsize`,
/// - updates the size referenced by `outsize` with the number of bytes copied through `outptr`.
///
/// A failure is indicated with a non-zero exit code under the following conditions:
/// - the input string was not a valid mangled name.
///
/// It is not an error to supply an output buffer that is too small; in such a case, the output
/// will simply be truncated to the provided length.
///
/// A null input pointer (`None` in the Rust interface) is not an error *per se*, but since at best
/// (when `insize` is 0) it can represent only an empty string, which is never demanglable, failure
/// is reported:
/// ```
/// # use mangling::clib::*;
/// // Demangling an empty string is not meaningful, and must fail
/// let success = mangling_demangle(0, None, None, None);
/// assert_ne!(success, 0);
/// ```
///
/// # Example
/// In C:
/// ```c
/// char result[128];
/// size_t outsize = sizeof result;
/// int success = mangling_demangle(strlen(argv[1]), argv[1], &outsize, result);
/// fwrite(result, 1, outsize, stdout);
/// ```
pub extern "C"