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
use {
crate::{AwsAllocator, AwsCAllocator},
std::{
error::Error,
ffi::{c_void, CString},
ptr::null_mut,
slice::{from_raw_parts, from_raw_parts_mut},
},
};
pub struct AwsByteBuf {
pub(crate) inner: AwsCByteBuf,
}
impl AwsByteBuf {
pub fn new(
allocator: &AwsAllocator,
capacity: usize,
) -> Result<AwsByteBuf, Box<dyn Error + Send + Sync + 'static>> {
let mut buf = AwsCByteBuf {
len: 0,
buffer: null_mut(),
capacity,
allocator: allocator.as_ptr(),
};
let init_ok = unsafe { aws_byte_buf_init(&mut buf, allocator.as_ptr(), capacity) };
if init_ok != 0 {
return Err("Failed to initialize byte buffer".into());
}
Ok(AwsByteBuf {
inner: buf,
})
}
pub fn from_str(allocator: &AwsAllocator, s: &str) -> Result<AwsByteBuf, Box<dyn Error + Send + Sync + 'static>> {
let s = CString::new(s.as_bytes())?;
let s_bytes = s.into_bytes_with_nul();
let mut buf = AwsCByteBuf {
len: 0,
buffer: null_mut(),
capacity: 0,
allocator: allocator.as_ptr(),
};
let init_ok = unsafe { aws_byte_buf_init(&mut buf, allocator.as_ptr(), s_bytes.len()) };
if init_ok != 0 {
return Err("Failed to initialize byte buffer".into());
}
let dst = unsafe { from_raw_parts_mut(buf.buffer, buf.capacity) };
dst[..s_bytes.len()].copy_from_slice(&s_bytes[..s_bytes.len()]);
buf.len = s_bytes.len();
Ok(AwsByteBuf {
inner: buf,
})
}
pub fn secure_zero(&mut self) {
unsafe { aws_byte_buf_secure_zero(&mut self.inner) };
}
pub fn is_valid(&self) -> bool {
unsafe { aws_byte_buf_is_valid(&self.inner) }
}
pub fn to_string_lossy(&self) -> String {
let len = self.inner.len;
let mut s = unsafe { from_raw_parts(self.inner.buffer, len) };
if s[len - 1] == b'\0' {
s = s[..len - 1].as_ref();
}
String::from_utf8_lossy(s).into_owned()
}
}
impl Clone for AwsByteBuf {
fn clone(&self) -> Self {
let allocator = self.inner.allocator;
let mut buf = AwsCByteBuf {
len: 0,
buffer: null_mut(),
capacity: 0,
allocator,
};
let init_ok = unsafe { aws_byte_buf_init_copy(&mut buf, allocator, &self.inner) };
if init_ok != 0 {
panic!("Failed to initialize byte buffer");
}
AwsByteBuf {
inner: buf,
}
}
}
impl Drop for AwsByteBuf {
fn drop(&mut self) {
unsafe { aws_byte_buf_clean_up(&mut self.inner) };
}
}
#[repr(C)]
pub struct AwsCByteBuf {
pub len: usize,
pub buffer: *mut u8,
pub capacity: usize,
pub allocator: *const AwsCAllocator,
}
unsafe impl Send for AwsCByteBuf {}
unsafe impl Sync for AwsCByteBuf {}
#[repr(C)]
pub struct AwsCByteCursor {
pub len: usize,
pub ptr: *const u8,
}
unsafe impl Send for AwsCByteCursor {}
unsafe impl Sync for AwsCByteCursor {}
#[link(name = "aws-c-common")]
extern "C" {
pub fn aws_array_eq(array_a: *const c_void, len_a: usize, array_b: *const c_void, len_b: usize) -> bool;
pub fn aws_array_eq_ignore_case(array_a: *const c_void, len_a: usize, array_b: *const c_void, len_b: usize)
-> bool;
pub fn aws_array_eq_c_str(array: *const c_void, array_len: usize, c_str: *const u8) -> bool;
pub fn aws_array_eq_c_str_ignore_case(array: *const c_void, array_len: usize, c_str: *const u8) -> bool;
#[must_use = "returns an i32 that contains a result code (AWS_OP_SUCCESS or AWS_OP_ERR)"]
pub fn aws_byte_buf_init(buf: *mut AwsCByteBuf, allocator: *const AwsCAllocator, capacity: usize) -> i32;
#[must_use = "returns an i32 that contains a result code (AWS_OP_SUCCESS or AWS_OP_ERR)"]
pub fn aws_byte_buf_init_copy(
dest: *mut AwsCByteBuf,
allocator: *const AwsCAllocator,
src: *const AwsCByteBuf,
) -> i32;
#[must_use = "returns an i32 that contains a result code (AWS_OP_SUCCESS or AWS_OP_ERR)"]
pub fn aws_byte_buf_init_from_file(
out_buf: *mut AwsCByteBuf,
allocator: *const AwsCAllocator,
filename: *const u8,
) -> i32;
pub(crate) fn aws_byte_buf_is_valid(buf: *const AwsCByteBuf) -> bool;
pub fn aws_byte_cursor_is_valid(cursor: *const AwsCByteCursor) -> bool;
#[must_use = "returns an i32 that contains a result code (AWS_OP_SUCCESS or AWS_OP_ERR)"]
pub fn aws_byte_buf_init_copy_from_cursor(
buf: *mut AwsCByteBuf,
allocator: *const AwsCAllocator,
src: AwsCByteCursor,
) -> i32;
#[must_use = "returns an i32 that contains a result code (AWS_OP_SUCCESS or AWS_OP_ERR)"]
pub fn aws_byte_buf_init_cache_and_update_cursors(
buf: *mut AwsCByteBuf,
allocator: *const AwsCAllocator,
...
) -> i32;
pub fn aws_byte_buf_clean_up(buf: *mut AwsCByteBuf);
pub fn aws_byte_buf_clean_up_secure(buf: *mut AwsCByteBuf);
pub fn aws_byte_buf_reset(buf: *mut AwsCByteBuf, zero: bool);
pub fn aws_byte_buf_secure_zero(buf: *mut AwsCByteBuf);
pub fn aws_byte_buf_eq(a: *const AwsCByteBuf, b: *const AwsCByteBuf) -> bool;
pub fn aws_byte_buf_eq_ignore_case(a: *const AwsCByteBuf, b: *const AwsCByteBuf) -> bool;
pub fn aws_byte_buf_eq_c_str(a: *const AwsCByteBuf, b: *const u8) -> bool;
pub fn aws_byte_buf_eq_c_str_ignore_case(a: *const AwsCByteBuf, b: *const u8) -> bool;
pub fn aws_byte_cursor_next_split(
input_str: *const AwsCByteCursor,
split_on: u8,
substr: *const AwsCByteCursor,
) -> bool;
}