@@ -5,7 +5,8 @@ use std::{
55 cmp:: Ordering ,
66 fmt,
77 hash:: { Hash , Hasher } ,
8- ops:: Deref ,
8+ mem,
9+ ops:: { Bound , Deref , RangeBounds } ,
910 slice,
1011} ;
1112
@@ -64,6 +65,7 @@ impl Bytes {
6465
6566 // rustdoc-stripper-ignore-next
6667 /// Takes ownership of `data` and creates a new `Bytes` without copying.
68+ #[ doc( alias = "g_bytes_new" ) ]
6769 pub fn from_owned < T : AsRef < [ u8 ] > + Send + ' static > ( data : T ) -> Bytes {
6870 let data: Box < T > = Box :: new ( data) ;
6971 let ( size, data_ptr) = {
@@ -84,6 +86,56 @@ impl Bytes {
8486 ) )
8587 }
8688 }
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+ }
87139}
88140
89141unsafe impl Send for Bytes { }
@@ -274,4 +326,24 @@ mod tests {
274326 let b = Bytes :: from_owned ( vec ! [ 1 , 2 , 3 ] ) ;
275327 assert_eq ! ( b, [ 1u8 , 2u8 , 3u8 ] . as_ref( ) ) ;
276328 }
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+ }
277349}
0 commit comments