@@ -5,7 +5,8 @@ use std::{
5
5
cmp:: Ordering ,
6
6
fmt,
7
7
hash:: { Hash , Hasher } ,
8
- ops:: Deref ,
8
+ mem,
9
+ ops:: { Bound , Deref , RangeBounds } ,
9
10
slice,
10
11
} ;
11
12
@@ -64,6 +65,7 @@ impl Bytes {
64
65
65
66
// rustdoc-stripper-ignore-next
66
67
/// Takes ownership of `data` and creates a new `Bytes` without copying.
68
+ #[ doc( alias = "g_bytes_new" ) ]
67
69
pub fn from_owned < T : AsRef < [ u8 ] > + Send + ' static > ( data : T ) -> Bytes {
68
70
let data: Box < T > = Box :: new ( data) ;
69
71
let ( size, data_ptr) = {
@@ -84,6 +86,56 @@ impl Bytes {
84
86
) )
85
87
}
86
88
}
89
+
90
+ // rustdoc-stripper-ignore-next
91
+ /// Returns the underlying data of the `Bytes`.
92
+ ///
93
+ /// If there is no other reference to `self` then this does not copy the data, otherwise
94
+ /// it is copied into newly allocated heap memory.
95
+ #[ doc( alias = "g_bytes_unref_to_data" ) ]
96
+ pub fn into_data ( self ) -> crate :: collections:: Slice < u8 > {
97
+ unsafe {
98
+ let mut size = mem:: MaybeUninit :: uninit ( ) ;
99
+ let ret = ffi:: g_bytes_unref_to_data ( self . into_glib_ptr ( ) , size. as_mut_ptr ( ) ) ;
100
+ crate :: collections:: Slice :: from_glib_full_num ( ret as * mut u8 , size. assume_init ( ) )
101
+ }
102
+ }
103
+
104
+ fn calculate_offset_size ( & self , range : impl RangeBounds < usize > ) -> ( usize , usize ) {
105
+ let len = self . len ( ) ;
106
+
107
+ let start_offset = match range. start_bound ( ) {
108
+ Bound :: Included ( v) => * v,
109
+ Bound :: Excluded ( v) => v. checked_add ( 1 ) . expect ( "Invalid start offset" ) ,
110
+ Bound :: Unbounded => 0 ,
111
+ } ;
112
+ assert ! ( start_offset < len, "Start offset after valid range" ) ;
113
+
114
+ let end_offset = match range. end_bound ( ) {
115
+ Bound :: Included ( v) => v. checked_add ( 1 ) . expect ( "Invalid end offset" ) ,
116
+ Bound :: Excluded ( v) => * v,
117
+ Bound :: Unbounded => len,
118
+ } ;
119
+ assert ! ( end_offset <= len, "End offset after valid range" ) ;
120
+
121
+ let size = end_offset. saturating_sub ( start_offset) ;
122
+
123
+ ( start_offset, size)
124
+ }
125
+
126
+ // rustdoc-stripper-ignore-next
127
+ /// Creates a new `Bytes` that references the given `range` of `bytes`.
128
+ #[ doc( alias = "g_bytes_new_from_bytes" ) ]
129
+ pub fn from_bytes ( bytes : & Self , range : impl RangeBounds < usize > ) -> Self {
130
+ let ( offset, size) = bytes. calculate_offset_size ( range) ;
131
+ unsafe {
132
+ from_glib_full ( ffi:: g_bytes_new_from_bytes (
133
+ bytes. to_glib_none ( ) . 0 ,
134
+ offset,
135
+ size,
136
+ ) )
137
+ }
138
+ }
87
139
}
88
140
89
141
unsafe impl Send for Bytes { }
@@ -274,4 +326,24 @@ mod tests {
274
326
let b = Bytes :: from_owned ( vec ! [ 1 , 2 , 3 ] ) ;
275
327
assert_eq ! ( b, [ 1u8 , 2u8 , 3u8 ] . as_ref( ) ) ;
276
328
}
329
+
330
+ #[ test]
331
+ fn from_bytes ( ) {
332
+ let b1 = Bytes :: from_owned ( vec ! [ 1 , 2 , 3 ] ) ;
333
+ let b2 = Bytes :: from_bytes ( & b1, 1 ..=1 ) ;
334
+ assert_eq ! ( b2, [ 2u8 ] . as_ref( ) ) ;
335
+ let b2 = Bytes :: from_bytes ( & b1, 1 ..) ;
336
+ assert_eq ! ( b2, [ 2u8 , 3u8 ] . as_ref( ) ) ;
337
+ let b2 = Bytes :: from_bytes ( & b1, ..2 ) ;
338
+ assert_eq ! ( b2, [ 1u8 , 2u8 ] . as_ref( ) ) ;
339
+ let b2 = Bytes :: from_bytes ( & b1, ..) ;
340
+ assert_eq ! ( b2, [ 1u8 , 2u8 , 3u8 ] . as_ref( ) ) ;
341
+ }
342
+
343
+ #[ test]
344
+ pub fn into_data ( ) {
345
+ let b = Bytes :: from ( b"this is a test" ) ;
346
+ let d = b. into_data ( ) ;
347
+ assert_eq ! ( d. as_slice( ) , b"this is a test" ) ;
348
+ }
277
349
}
0 commit comments