diff options
| author | mat <27899617+mat-1@users.noreply.github.com> | 2022-10-07 20:12:36 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-10-07 20:12:36 -0500 |
| commit | bc3aa9467ae1e2d0ea1727093af9b0af14965e69 (patch) | |
| tree | 8db3b735daed484507129eb0683db88ddec14210 /azalea-buf | |
| parent | 695efef66fdf1e08f0cb6d8783c085875100fa2d (diff) | |
| download | azalea-drasl-bc3aa9467ae1e2d0ea1727093af9b0af14965e69.tar.xz | |
Replace impl Read with Cursor<&[u8]> (#26)
* Start getting rid of Cursor
* try to make the tests pass and fail
* make the tests pass
* remove unused uses
* fix clippy warnings
* fix potential OOM exploits
* fix OOM in az-nbt
* fix nbt benchmark
* fix a test
* start replacing it with Cursor<Vec<u8>>
* wip
* fix all the issues
* fix all tests
* fix nbt benchmark
* fix warnings
Diffstat (limited to 'azalea-buf')
| -rw-r--r-- | azalea-buf/azalea-buf-macros/src/lib.rs | 4 | ||||
| -rw-r--r-- | azalea-buf/src/definitions.rs | 4 | ||||
| -rw-r--r-- | azalea-buf/src/lib.rs | 73 | ||||
| -rw-r--r-- | azalea-buf/src/read.rs | 145 | ||||
| -rw-r--r-- | azalea-buf/src/serializable_uuid.rs | 6 |
5 files changed, 124 insertions, 108 deletions
diff --git a/azalea-buf/azalea-buf-macros/src/lib.rs b/azalea-buf/azalea-buf-macros/src/lib.rs index 288f2416..801b7b71 100644 --- a/azalea-buf/azalea-buf-macros/src/lib.rs +++ b/azalea-buf/azalea-buf-macros/src/lib.rs @@ -41,7 +41,7 @@ fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt quote! { impl azalea_buf::McBufReadable for #ident { - fn read_from(buf: &mut impl std::io::Read) -> Result<Self, azalea_buf::BufReadError> { + fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { #(#read_fields)* Ok(#ident { #(#read_field_names: #read_field_names),* @@ -105,7 +105,7 @@ fn create_impl_mcbufreadable(ident: &Ident, data: &Data) -> proc_macro2::TokenSt quote! { impl azalea_buf::McBufReadable for #ident { - fn read_from(buf: &mut impl std::io::Read) -> Result<Self, azalea_buf::BufReadError> + fn read_from(buf: &mut std::io::Cursor<&[u8]>) -> Result<Self, azalea_buf::BufReadError> { let id = azalea_buf::McBufVarReadable::var_read_from(buf)?; match id { diff --git a/azalea-buf/src/definitions.rs b/azalea-buf/src/definitions.rs index ae7a7407..77309c46 100644 --- a/azalea-buf/src/definitions.rs +++ b/azalea-buf/src/definitions.rs @@ -2,10 +2,10 @@ use std::ops::Deref; /// A Vec<u8> that isn't prefixed by a VarInt with the size. #[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct UnsizedByteArray(Vec<u8>); +pub struct UnsizedByteArray(pub Vec<u8>); impl Deref for UnsizedByteArray { - type Target = Vec<u8>; + type Target = [u8]; fn deref(&self) -> &Self::Target { &self.0 diff --git a/azalea-buf/src/lib.rs b/azalea-buf/src/lib.rs index b8daa325..2c42f2ca 100644 --- a/azalea-buf/src/lib.rs +++ b/azalea-buf/src/lib.rs @@ -12,7 +12,7 @@ mod write; pub use azalea_buf_macros::*; pub use definitions::*; -pub use read::{read_varint_async, BufReadError, McBufReadable, McBufVarReadable}; +pub use read::{BufReadError, McBufReadable, McBufVarReadable}; pub use serializable_uuid::*; pub use write::{McBufVarWritable, McBufWritable}; @@ -23,7 +23,7 @@ const MAX_STRING_LENGTH: u16 = 32767; #[cfg(test)] mod tests { use super::*; - use std::{collections::HashMap, io::Cursor}; + use std::collections::HashMap; #[test] fn test_write_varint() { @@ -74,44 +74,44 @@ mod tests { #[test] fn test_read_varint() { - let mut buf = Cursor::new(vec![0]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), 0); + let buf = &mut &vec![0][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), 0); - let mut buf = Cursor::new(vec![1]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), 1); + let buf = &mut &vec![1][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), 1); - let mut buf = Cursor::new(vec![2]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2); + let buf = &mut &vec![2][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), 2); - let mut buf = Cursor::new(vec![127]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), 127); + let buf = &mut &vec![127][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), 127); - let mut buf = Cursor::new(vec![128, 1]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), 128); + let buf = &mut &vec![128, 1][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), 128); - let mut buf = Cursor::new(vec![255, 1]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), 255); + let buf = &mut &vec![255, 1][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), 255); - let mut buf = Cursor::new(vec![221, 199, 1]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), 25565); + let buf = &mut &vec![221, 199, 1][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), 25565); - let mut buf = Cursor::new(vec![255, 255, 127]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2097151); + let buf = &mut &vec![255, 255, 127][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), 2097151); - let mut buf = Cursor::new(vec![255, 255, 255, 255, 7]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), 2147483647); + let buf = &mut &vec![255, 255, 255, 255, 7][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), 2147483647); - let mut buf = Cursor::new(vec![255, 255, 255, 255, 15]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), -1); + let buf = &mut &vec![255, 255, 255, 255, 15][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), -1); - let mut buf = Cursor::new(vec![128, 128, 128, 128, 8]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), -2147483648); + let buf = &mut &vec![128, 128, 128, 128, 8][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), -2147483648); } #[test] fn test_read_varint_longer() { - let mut buf = Cursor::new(vec![138, 56, 0, 135, 56, 123]); - assert_eq!(i32::var_read_from(&mut buf).unwrap(), 7178); + let buf = &mut &vec![138, 56, 0, 135, 56, 123][..]; + assert_eq!(i32::var_read_from(buf).unwrap(), 7178); } #[test] @@ -123,8 +123,8 @@ mod tests { dbg!(&buf); - let mut buf = Cursor::new(buf); - let result = Vec::<String>::read_from(&mut buf).unwrap(); + let buf = &mut &buf[..]; + let result = Vec::<String>::read_from(buf).unwrap(); assert_eq!(result, original_vec); } @@ -133,9 +133,9 @@ mod tests { let mut buf = Vec::new(); vec![1, 2, 3].var_write_into(&mut buf).unwrap(); - let mut buf = Cursor::new(buf); + let buf = &mut &buf[..]; - let result = Vec::<i32>::var_read_from(&mut buf).unwrap(); + let result = Vec::<i32>::var_read_from(buf).unwrap(); assert_eq!(result, vec![1, 2, 3]); } @@ -149,20 +149,19 @@ mod tests { let mut buf = Vec::new(); original_map.var_write_into(&mut buf).unwrap(); - let mut buf = Cursor::new(buf); + let buf = &mut &buf[..]; - let result = HashMap::<String, i32>::var_read_from(&mut buf).unwrap(); + let result = HashMap::<String, i32>::var_read_from(buf).unwrap(); assert_eq!(result, original_map); } #[test] fn test_long() { - let mut buf = Vec::new(); - 123456u64.write_into(&mut buf).unwrap(); - - let mut buf = Cursor::new(buf); + let buf: &mut Vec<u8> = &mut Vec::new(); + 123456u64.write_into(buf).unwrap(); - assert_eq!(u64::read_from(&mut buf).unwrap(), 123456); + let buf = &mut &buf[..]; + assert_eq!(u64::read_from(buf).unwrap(), 123456); } } diff --git a/azalea-buf/src/read.rs b/azalea-buf/src/read.rs index 78c858e4..29f351c6 100644 --- a/azalea-buf/src/read.rs +++ b/azalea-buf/src/read.rs @@ -1,8 +1,11 @@ use super::{UnsizedByteArray, MAX_STRING_LENGTH}; use byteorder::{ReadBytesExt, BE}; -use std::{collections::HashMap, hash::Hash, io::Read}; +use std::{ + collections::HashMap, + hash::Hash, + io::{Cursor, Read}, +}; use thiserror::Error; -use tokio::io::{AsyncRead, AsyncReadExt}; #[derive(Error, Debug)] pub enum BufReadError { @@ -26,6 +29,11 @@ pub enum BufReadError { UnexpectedEnumVariant { id: i32 }, #[error("Unexpected enum variant {id}")] UnexpectedStringEnumVariant { id: String }, + #[error("Tried to read {attempted_read} bytes but there were only {actual_read}")] + UnexpectedEof { + attempted_read: usize, + actual_read: usize, + }, #[error("{0}")] Custom(String), #[cfg(feature = "serde_json")] @@ -33,7 +41,20 @@ pub enum BufReadError { Deserialization(#[from] serde_json::Error), } -fn read_utf_with_len(buf: &mut impl Read, max_length: u32) -> Result<String, BufReadError> { +fn read_bytes<'a>(buf: &'a mut Cursor<&[u8]>, length: usize) -> Result<&'a [u8], BufReadError> { + if length > buf.get_ref().len() { + return Err(BufReadError::UnexpectedEof { + attempted_read: length, + actual_read: buf.get_ref().len(), + }); + } + let initial_position = buf.position() as usize; + buf.set_position(buf.position() + length as u64); + let data = &buf.get_ref()[initial_position..initial_position + length]; + Ok(data) +} + +fn read_utf_with_len(buf: &mut Cursor<&[u8]>, max_length: u32) -> Result<String, BufReadError> { let length = u32::var_read_from(buf)?; // i don't know why it's multiplied by 4 but it's like that in mojang's code so if length as u32 > max_length * 4 { @@ -43,12 +64,10 @@ fn read_utf_with_len(buf: &mut impl Read, max_length: u32) -> Result<String, Buf }); } - // this is probably quite inefficient, idk how to do it better - let mut string = String::new(); - let mut buffer = vec![0; length as usize]; - buf.read_exact(&mut buffer) - .map_err(|_| BufReadError::InvalidUtf8)?; - string.push_str(std::str::from_utf8(&buffer).map_err(|_| BufReadError::InvalidUtf8)?); + let buffer = read_bytes(buf, length as usize)?; + let string = std::str::from_utf8(buffer) + .map_err(|_| BufReadError::InvalidUtf8)? + .to_string(); if string.len() > length as usize { return Err(BufReadError::StringLengthTooLong { length, max_length }); } @@ -58,37 +77,37 @@ fn read_utf_with_len(buf: &mut impl Read, max_length: u32) -> Result<String, Buf // fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67 /// Read a single varint from the reader and return the value, along with the number of bytes read -pub async fn read_varint_async( - reader: &mut (dyn AsyncRead + Unpin + Send), -) -> Result<i32, BufReadError> { - let mut buffer = [0]; - let mut ans = 0; - for i in 0..5 { - reader.read_exact(&mut buffer).await?; - ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i); - if buffer[0] & 0b1000_0000 == 0 { - break; - } - } - Ok(ans) -} +// pub async fn read_varint_async( +// reader: &mut (dyn AsyncRead + Unpin + Send), +// ) -> Result<i32, BufReadError> { +// let mut buffer = [0]; +// let mut ans = 0; +// for i in 0..5 { +// reader.read_exact(&mut buffer).await?; +// ans |= ((buffer[0] & 0b0111_1111) as i32) << (7 * i); +// if buffer[0] & 0b1000_0000 == 0 { +// break; +// } +// } +// Ok(ans) +// } pub trait McBufReadable where Self: Sized, { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError>; + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>; } pub trait McBufVarReadable where Self: Sized, { - fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError>; + fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError>; } impl McBufReadable for i32 { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(buf.read_i32::<BE>()?) } } @@ -96,7 +115,7 @@ impl McBufReadable for i32 { impl McBufVarReadable for i32 { // fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L67 /// Read a single varint from the reader and return the value - fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let mut buffer = [0]; let mut ans = 0; for i in 0..5 { @@ -112,7 +131,7 @@ impl McBufVarReadable for i32 { impl McBufVarReadable for i64 { // fast varints modified from https://github.com/luojia65/mc-varint/blob/master/src/lib.rs#L54 - fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let mut buffer = [0]; let mut ans = 0; for i in 0..8 { @@ -127,25 +146,26 @@ impl McBufVarReadable for i64 { } } impl McBufVarReadable for u64 { - fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { i64::var_read_from(buf).map(|i| i as u64) } } impl McBufReadable for UnsizedByteArray { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { // read to end of the buffer - let mut bytes = vec![]; - buf.read_to_end(&mut bytes) - .map_err(|_| BufReadError::CouldNotReadBytes)?; - Ok(bytes.into()) + let data = buf.get_ref()[buf.position() as usize..].to_vec(); + buf.set_position((buf.position()) + data.len() as u64); + Ok(UnsizedByteArray(data)) } } impl<T: McBufReadable + Send> McBufReadable for Vec<T> { - default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + default fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let length = u32::var_read_from(buf)? as usize; - let mut contents = Vec::with_capacity(length); + // we don't set the capacity here so we can't get exploited into + // allocating a bunch + let mut contents = vec![]; for _ in 0..length { contents.push(T::read_from(buf)?); } @@ -154,9 +174,9 @@ impl<T: McBufReadable + Send> McBufReadable for Vec<T> { } impl<K: McBufReadable + Send + Eq + Hash, V: McBufReadable + Send> McBufReadable for HashMap<K, V> { - default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + default fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let length = i32::var_read_from(buf)? as usize; - let mut contents = HashMap::with_capacity(length); + let mut contents = HashMap::new(); for _ in 0..length { contents.insert(K::read_from(buf)?, V::read_from(buf)?); } @@ -167,9 +187,9 @@ impl<K: McBufReadable + Send + Eq + Hash, V: McBufReadable + Send> McBufReadable impl<K: McBufReadable + Send + Eq + Hash, V: McBufVarReadable + Send> McBufVarReadable for HashMap<K, V> { - default fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + default fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let length = i32::var_read_from(buf)? as usize; - let mut contents = HashMap::with_capacity(length); + let mut contents = HashMap::new(); for _ in 0..length { contents.insert(K::read_from(buf)?, V::var_read_from(buf)?); } @@ -178,55 +198,52 @@ impl<K: McBufReadable + Send + Eq + Hash, V: McBufVarReadable + Send> McBufVarRe } impl McBufReadable for Vec<u8> { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let length = i32::var_read_from(buf)? as usize; - let mut buffer = vec![0; length]; - buf.read_exact(&mut buffer) - .map_err(|_| BufReadError::CouldNotReadBytes)?; - Ok(buffer) + read_bytes(buf, length).map(|b| b.to_vec()) } } impl McBufReadable for String { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { read_utf_with_len(buf, MAX_STRING_LENGTH.into()) } } impl McBufReadable for u32 { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(i32::read_from(buf)? as u32) } } impl McBufVarReadable for u32 { - fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(i32::var_read_from(buf)? as u32) } } impl McBufReadable for u16 { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { i16::read_from(buf).map(|i| i as u16) } } impl McBufReadable for i16 { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(buf.read_i16::<BE>()?) } } impl McBufVarReadable for u16 { - fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(i32::var_read_from(buf)? as u16) } } impl<T: McBufVarReadable> McBufVarReadable for Vec<T> { - fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let length = i32::var_read_from(buf)? as usize; - let mut contents = Vec::with_capacity(length); + let mut contents = Vec::new(); for _ in 0..length { contents.push(T::var_read_from(buf)?); } @@ -235,49 +252,49 @@ impl<T: McBufVarReadable> McBufVarReadable for Vec<T> { } impl McBufReadable for i64 { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(buf.read_i64::<BE>()?) } } impl McBufReadable for u64 { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { i64::read_from(buf).map(|i| i as u64) } } impl McBufReadable for bool { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(u8::read_from(buf)? != 0) } } impl McBufReadable for u8 { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(buf.read_u8()?) } } impl McBufReadable for i8 { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { u8::read_from(buf).map(|i| i as i8) } } impl McBufReadable for f32 { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(buf.read_f32::<BE>()?) } } impl McBufReadable for f64 { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(buf.read_f64::<BE>()?) } } impl<T: McBufReadable> McBufReadable for Option<T> { - default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + default fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let present = bool::read_from(buf)?; Ok(if present { Some(T::read_from(buf)?) @@ -288,7 +305,7 @@ impl<T: McBufReadable> McBufReadable for Option<T> { } impl<T: McBufVarReadable> McBufVarReadable for Option<T> { - default fn var_read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + default fn var_read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let present = bool::read_from(buf)?; Ok(if present { Some(T::var_read_from(buf)?) @@ -300,13 +317,13 @@ impl<T: McBufVarReadable> McBufVarReadable for Option<T> { // [String; 4] impl<T: McBufReadable, const N: usize> McBufReadable for [T; N] { - default fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + default fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { let mut contents = Vec::with_capacity(N); for _ in 0..N { contents.push(T::read_from(buf)?); } contents.try_into().map_err(|_| { - panic!("Panic is not possible since the Vec is the same size as the array") + unreachable!("Panic is not possible since the Vec is the same size as the array") }) } } diff --git a/azalea-buf/src/serializable_uuid.rs b/azalea-buf/src/serializable_uuid.rs index 66cdda73..dc251269 100644 --- a/azalea-buf/src/serializable_uuid.rs +++ b/azalea-buf/src/serializable_uuid.rs @@ -1,5 +1,5 @@ use crate::{read::BufReadError, McBufReadable, McBufWritable}; -use std::io::{Read, Write}; +use std::io::{Cursor, Write}; use uuid::Uuid; pub trait SerializableUuid { @@ -33,7 +33,7 @@ impl SerializableUuid for Uuid { } impl McBufReadable for Uuid { - fn read_from(buf: &mut impl Read) -> Result<Self, BufReadError> { + fn read_from(buf: &mut Cursor<&[u8]>) -> Result<Self, BufReadError> { Ok(Uuid::from_int_array([ u32::read_from(buf)?, u32::read_from(buf)?, @@ -80,7 +80,7 @@ mod tests { u.write_into(&mut buf).unwrap(); println!("{:?}", buf); assert_eq!(buf.len(), 16); - let u2 = Uuid::read_from(&mut buf.as_slice()).unwrap(); + let u2 = Uuid::read_from(&mut Cursor::new(&buf)).unwrap(); assert_eq!(u, u2); } } |
