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
use std::{
cmp::min,
convert::TryInto,
ptr::{null, null_mut},
};
use widestring::U16CStr;
pub fn clamp_small_int(n: usize) -> i16 {
min(n, i16::MAX as usize) as i16
}
pub fn clamp_int(n: usize) -> i32 {
min(n, i32::MAX as usize) as i32
}
pub fn mut_buf_ptr<T>(buffer: &mut [T]) -> *mut T {
if buffer.is_empty() {
null_mut()
} else {
buffer.as_mut_ptr()
}
}
pub fn buf_ptr<T>(buffer: &[T]) -> *const T {
if buffer.is_empty() {
null()
} else {
buffer.as_ptr()
}
}
pub struct OutputStringBuffer {
buffer: Vec<u16>,
actual_length: i16,
}
impl OutputStringBuffer {
pub fn with_buffer_size(max_str_len: usize) -> Self {
Self {
buffer: vec![0; max_str_len + 1],
actual_length: 0,
}
}
pub fn mut_buf_ptr(&mut self) -> *mut u16 {
mut_buf_ptr(&mut self.buffer)
}
pub fn buf_len(&self) -> i16 {
if self.buffer.is_empty() {
0
} else {
(self.buffer.len() - 1).try_into().unwrap()
}
}
pub fn mut_actual_len_ptr(&mut self) -> *mut i16 {
&mut self.actual_length as *mut i16
}
pub fn as_ucstr(&self) -> &U16CStr {
U16CStr::from_slice_with_nul(&self.buffer).unwrap()
}
pub fn to_utf8(&self) -> String {
self.as_ucstr().to_string().unwrap()
}
pub fn is_truncated(&self) -> bool {
let len: usize = self.actual_length.try_into().unwrap();
len >= self.buffer.len()
}
}