Skip to content
This repository was archived by the owner on Jun 8, 2021. It is now read-only.

Commit 8424ef0

Browse files
authored
Merge pull request #480 from elmarco/byte-array
Add ByteArray binding
2 parents 3dd95f3 + 15ff33d commit 8424ef0

File tree

3 files changed

+268
-0
lines changed

3 files changed

+268
-0
lines changed

Gir.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ ignore = [
3131

3232
manual = [
3333
"GLib.Bytes",
34+
"GLib.ByteArray",
3435
"GLib.Error",
3536
"GLib.Variant",
3637
"GLib.VariantType",

src/byte_array.rs

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
// Copyright 2019, The Gtk-rs Project Developers.
2+
// See the COPYRIGHT file at the top-level directory of this distribution.
3+
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>
4+
5+
//! # Examples
6+
//!
7+
//! ```
8+
//! use glib::prelude::*; // or `use gtk::prelude::*;`
9+
//! use glib::ByteArray;
10+
//!
11+
//! let ba = ByteArray::from(b"def");
12+
//! ba.append(b"ghi").prepend(b"abc");
13+
//! ba.remove_range(3, 3);
14+
//! assert_eq!(ba, "abcghi".as_bytes());
15+
//! ```
16+
17+
use glib_sys;
18+
use std::borrow::Borrow;
19+
use std::cmp::Ordering;
20+
use std::fmt;
21+
use std::hash::{Hash, Hasher};
22+
use std::mem;
23+
use std::ops::Deref;
24+
use std::slice;
25+
use translate::*;
26+
use std::ptr::NonNull;
27+
28+
use Bytes;
29+
30+
glib_wrapper! {
31+
pub struct ByteArray(Shared<glib_sys::GByteArray>);
32+
33+
match fn {
34+
ref => |ptr| glib_sys::g_byte_array_ref(ptr),
35+
unref => |ptr| glib_sys::g_byte_array_unref(ptr),
36+
get_type => || glib_sys::g_byte_array_get_type(),
37+
}
38+
}
39+
40+
impl ByteArray {
41+
pub fn new() -> ByteArray {
42+
unsafe { from_glib_full(glib_sys::g_byte_array_new()) }
43+
}
44+
45+
pub fn with_capacity(size: usize) -> ByteArray {
46+
unsafe { from_glib_full(glib_sys::g_byte_array_sized_new(size as u32)) }
47+
}
48+
49+
pub fn into_gbytes(self) -> Bytes {
50+
unsafe {
51+
let ret = from_glib_full(glib_sys::g_byte_array_free_to_bytes(mut_override(
52+
self.to_glib_none().0,
53+
)));
54+
mem::forget(self);
55+
ret
56+
}
57+
}
58+
59+
pub fn append<T: ?Sized + AsRef<[u8]>>(&self, data: &T) -> &Self {
60+
let bytes = data.as_ref();
61+
unsafe {
62+
glib_sys::g_byte_array_append(
63+
self.to_glib_none().0,
64+
bytes.as_ptr() as *const _,
65+
bytes.len() as u32,
66+
);
67+
}
68+
self
69+
}
70+
71+
pub fn prepend<T: ?Sized + AsRef<[u8]>>(&self, data: &T) -> &Self {
72+
let bytes = data.as_ref();
73+
unsafe {
74+
glib_sys::g_byte_array_prepend(
75+
self.to_glib_none().0,
76+
bytes.as_ptr() as *const _,
77+
bytes.len() as u32,
78+
);
79+
}
80+
self
81+
}
82+
83+
pub fn remove_index(&self, index: usize) {
84+
unsafe {
85+
glib_sys::g_byte_array_remove_index(self.to_glib_none().0, index as u32);
86+
}
87+
}
88+
89+
pub fn remove_index_fast(&self, index: usize) {
90+
unsafe {
91+
glib_sys::g_byte_array_remove_index_fast(self.to_glib_none().0, index as u32);
92+
}
93+
}
94+
95+
pub fn remove_range(&self, index: usize, length: usize) {
96+
unsafe {
97+
glib_sys::g_byte_array_remove_range(self.to_glib_none().0, index as u32, length as u32);
98+
}
99+
}
100+
101+
pub fn set_size(&self, size: usize) {
102+
unsafe {
103+
glib_sys::g_byte_array_set_size(self.to_glib_none().0, size as u32);
104+
}
105+
}
106+
107+
pub fn sort<F: FnMut(&u8, &u8) -> Ordering>(&self, compare_func: F) {
108+
unsafe {
109+
let mut func = compare_func;
110+
let func_obj: &mut (FnMut(&u8, &u8) -> Ordering) = &mut func;
111+
let func_ptr =
112+
&func_obj as *const &mut (FnMut(&u8, &u8) -> Ordering) as glib_sys::gpointer;
113+
114+
glib_sys::g_byte_array_sort_with_data(
115+
self.to_glib_none().0,
116+
Some(compare_func_trampoline),
117+
func_ptr,
118+
);
119+
}
120+
}
121+
}
122+
123+
unsafe extern "C" fn compare_func_trampoline(
124+
a: glib_sys::gconstpointer,
125+
b: glib_sys::gconstpointer,
126+
func: glib_sys::gpointer,
127+
) -> i32 {
128+
let func = func as *mut &mut (FnMut(&u8, &u8) -> Ordering);
129+
130+
let a = &*(a as *const u8);
131+
let b = &*(b as *const u8);
132+
133+
match (*func)(&a, &b) {
134+
Ordering::Less => -1,
135+
Ordering::Equal => 0,
136+
Ordering::Greater => 1,
137+
}
138+
}
139+
140+
impl AsRef<[u8]> for ByteArray {
141+
fn as_ref(&self) -> &[u8] {
142+
&*self
143+
}
144+
}
145+
146+
impl<'a, T: ?Sized + Borrow<[u8]> + 'a> From<&'a T> for ByteArray {
147+
fn from(value: &'a T) -> ByteArray {
148+
let ba = ByteArray::new();
149+
ba.append(value.borrow());
150+
ba
151+
}
152+
}
153+
154+
impl Deref for ByteArray {
155+
type Target = [u8];
156+
157+
fn deref(&self) -> &[u8] {
158+
unsafe {
159+
let mut ptr = (*self.to_glib_none().0).data;
160+
let len = (*self.to_glib_none().0).len as usize;
161+
debug_assert!(!ptr.is_null() || len == 0);
162+
if ptr.is_null() {
163+
ptr = NonNull::dangling().as_ptr();
164+
}
165+
slice::from_raw_parts(ptr as *const u8, len)
166+
}
167+
}
168+
}
169+
170+
impl Default for ByteArray {
171+
fn default() -> Self {
172+
Self::new()
173+
}
174+
}
175+
176+
impl fmt::Debug for ByteArray {
177+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
178+
f.debug_struct("ByteArray")
179+
.field("ptr", &self.to_glib_none().0)
180+
.field("data", &&self[..])
181+
.finish()
182+
}
183+
}
184+
185+
macro_rules! impl_cmp {
186+
($lhs:ty, $rhs: ty) => {
187+
impl<'a, 'b> PartialEq<$rhs> for $lhs {
188+
#[inline]
189+
fn eq(&self, other: &$rhs) -> bool {
190+
self[..].eq(&other[..])
191+
}
192+
}
193+
194+
impl<'a, 'b> PartialEq<$lhs> for $rhs {
195+
#[inline]
196+
fn eq(&self, other: &$lhs) -> bool {
197+
self[..].eq(&other[..])
198+
}
199+
}
200+
201+
impl<'a, 'b> PartialOrd<$rhs> for $lhs {
202+
#[inline]
203+
fn partial_cmp(&self, other: &$rhs) -> Option<Ordering> {
204+
self[..].partial_cmp(&other[..])
205+
}
206+
}
207+
208+
impl<'a, 'b> PartialOrd<$lhs> for $rhs {
209+
#[inline]
210+
fn partial_cmp(&self, other: &$lhs) -> Option<Ordering> {
211+
self[..].partial_cmp(&other[..])
212+
}
213+
}
214+
};
215+
}
216+
217+
impl_cmp!(ByteArray, [u8]);
218+
impl_cmp!(ByteArray, &'a [u8]);
219+
impl_cmp!(&'a ByteArray, [u8]);
220+
impl_cmp!(ByteArray, Vec<u8>);
221+
impl_cmp!(&'a ByteArray, Vec<u8>);
222+
223+
impl PartialEq for ByteArray {
224+
fn eq(&self, other: &Self) -> bool {
225+
self[..] == other[..]
226+
}
227+
}
228+
229+
impl Eq for ByteArray {}
230+
231+
impl Hash for ByteArray {
232+
fn hash<H: Hasher>(&self, state: &mut H) {
233+
self.len().hash(state);
234+
Hash::hash_slice(&self[..], state)
235+
}
236+
}
237+
#[cfg(test)]
238+
mod tests {
239+
use super::*;
240+
use std::collections::HashSet;
241+
242+
#[test]
243+
fn various() {
244+
let ba: ByteArray = Default::default();
245+
ba.append("foo").append("bar").prepend("baz");
246+
ba.remove_index(0);
247+
ba.remove_index_fast(1);
248+
ba.remove_range(1, 2);
249+
ba.set_size(20);
250+
ba.sort(|a, b| a.cmp(b));
251+
let abc: &[u8] = b"abc";
252+
assert_eq!(ByteArray::from(abc), "abc".as_bytes());
253+
}
254+
255+
#[test]
256+
fn hash() {
257+
let b1 = ByteArray::from(b"this is a test");
258+
let b2 = ByteArray::from(b"this is a test");
259+
let b3 = ByteArray::from(b"test");
260+
let mut set = HashSet::new();
261+
set.insert(b1);
262+
assert!(set.contains(&b2));
263+
assert!(!set.contains(&b3));
264+
}
265+
}

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pub extern crate gobject_sys;
9393
pub extern crate futures;
9494

9595
use std::ffi::CStr;
96+
pub use byte_array::ByteArray;
9697
pub use bytes::Bytes;
9798
pub use string::String;
9899
pub use closure::Closure;
@@ -174,6 +175,7 @@ mod auto;
174175
pub use gobject::*;
175176
mod gobject;
176177

178+
mod byte_array;
177179
mod bytes;
178180
mod string;
179181
pub mod char;

0 commit comments

Comments
 (0)