|
6 | 6 | use crate::bitmap::BitmapSlice;
|
7 | 7 | use crate::volatile_memory::copy_slice_impl::{copy_from_volatile_slice, copy_to_volatile_slice};
|
8 | 8 | use crate::{VolatileMemoryError, VolatileSlice};
|
9 |
| -use std::io::{ErrorKind, Stdout}; |
| 9 | +use std::io::{Cursor, ErrorKind, Stdout}; |
10 | 10 | use std::os::fd::AsRawFd;
|
11 | 11 |
|
12 | 12 | /// A version of the standard library's [`Read`] trait that operates on volatile memory instead of
|
@@ -280,11 +280,56 @@ impl ReadVolatile for &[u8] {
|
280 | 280 | }
|
281 | 281 | }
|
282 | 282 |
|
| 283 | +// ReadVolatile and WriteVolatile implementations for Cursor<T> is modelled after the standard |
| 284 | +// library's implementation (modulo having to inline `Cursor::remaining_slice`, as that's nightly only) |
| 285 | +impl<T> ReadVolatile for Cursor<T> |
| 286 | +where |
| 287 | + T: AsRef<[u8]>, |
| 288 | +{ |
| 289 | + fn read_volatile<B: BitmapSlice>( |
| 290 | + &mut self, |
| 291 | + buf: &mut VolatileSlice<B>, |
| 292 | + ) -> Result<usize, VolatileMemoryError> { |
| 293 | + let inner = self.get_ref().as_ref(); |
| 294 | + let len = self.position().min(inner.len() as u64); |
| 295 | + let n = ReadVolatile::read_volatile(&mut &inner[(len as usize)..], buf)?; |
| 296 | + self.set_position(self.position() + n as u64); |
| 297 | + Ok(n) |
| 298 | + } |
| 299 | + |
| 300 | + fn read_exact_volatile<B: BitmapSlice>( |
| 301 | + &mut self, |
| 302 | + buf: &mut VolatileSlice<B>, |
| 303 | + ) -> Result<(), VolatileMemoryError> { |
| 304 | + let inner = self.get_ref().as_ref(); |
| 305 | + let n = buf.len(); |
| 306 | + let len = self.position().min(inner.len() as u64); |
| 307 | + ReadVolatile::read_exact_volatile(&mut &inner[(len as usize)..], buf)?; |
| 308 | + self.set_position(self.position() + n as u64); |
| 309 | + Ok(()) |
| 310 | + } |
| 311 | +} |
| 312 | + |
| 313 | +impl WriteVolatile for Cursor<&mut [u8]> { |
| 314 | + fn write_volatile<B: BitmapSlice>( |
| 315 | + &mut self, |
| 316 | + buf: &VolatileSlice<B>, |
| 317 | + ) -> Result<usize, VolatileMemoryError> { |
| 318 | + let pos = self.position().min(self.get_ref().len() as u64); |
| 319 | + let n = WriteVolatile::write_volatile(&mut &mut self.get_mut()[(pos as usize)..], buf)?; |
| 320 | + self.set_position(self.position() + n as u64); |
| 321 | + Ok(n) |
| 322 | + } |
| 323 | + |
| 324 | + // no write_all provided in standard library, since our default for write_all is based on the |
| 325 | + // standard library's write_all, omitting it here as well will correctly mimic stdlib behavior. |
| 326 | +} |
| 327 | + |
283 | 328 | #[cfg(test)]
|
284 | 329 | mod tests {
|
285 | 330 | use crate::io::{ReadVolatile, WriteVolatile};
|
286 | 331 | use crate::{VolatileMemoryError, VolatileSlice};
|
287 |
| - use std::io::{ErrorKind, Read, Seek, Write}; |
| 332 | + use std::io::{Cursor, ErrorKind, Read, Seek, Write}; |
288 | 333 | use vmm_sys_util::tempfile::TempFile;
|
289 | 334 |
|
290 | 335 | // ---- Test ReadVolatile for &[u8] ----
|
@@ -450,4 +495,70 @@ mod tests {
|
450 | 495 | write_5_bytes_to_file(input);
|
451 | 496 | }
|
452 | 497 | }
|
| 498 | + |
| 499 | + #[test] |
| 500 | + fn test_read_volatile_for_cursor() { |
| 501 | + let read_buffer = [1, 2, 3, 4, 5, 6, 7]; |
| 502 | + let mut output = vec![0u8; 5]; |
| 503 | + |
| 504 | + let mut cursor = Cursor::new(read_buffer); |
| 505 | + |
| 506 | + // Read 4 bytes from cursor to volatile slice (amount read limited by volatile slice length) |
| 507 | + assert_eq!( |
| 508 | + cursor |
| 509 | + .read_volatile(&mut VolatileSlice::from(&mut output[..4])) |
| 510 | + .unwrap(), |
| 511 | + 4 |
| 512 | + ); |
| 513 | + assert_eq!(output, vec![1, 2, 3, 4, 0]); |
| 514 | + |
| 515 | + // Read next 3 bytes from cursor to volatile slice (amount read limited by length of remaining data in cursor) |
| 516 | + assert_eq!( |
| 517 | + cursor |
| 518 | + .read_volatile(&mut VolatileSlice::from(&mut output[..4])) |
| 519 | + .unwrap(), |
| 520 | + 3 |
| 521 | + ); |
| 522 | + assert_eq!(output, vec![5, 6, 7, 4, 0]); |
| 523 | + |
| 524 | + cursor.set_position(0); |
| 525 | + // Same as first test above, but with read_exact |
| 526 | + cursor |
| 527 | + .read_exact_volatile(&mut VolatileSlice::from(&mut output[..4])) |
| 528 | + .unwrap(); |
| 529 | + assert_eq!(output, vec![1, 2, 3, 4, 0]); |
| 530 | + |
| 531 | + // Same as above, but with read_exact. Should fail now, because we cannot fill a 4 byte buffer |
| 532 | + // with whats remaining in the cursor (3 bytes). Output should remain unchanged. |
| 533 | + assert!(cursor |
| 534 | + .read_exact_volatile(&mut VolatileSlice::from(&mut output[..4])) |
| 535 | + .is_err()); |
| 536 | + assert_eq!(output, vec![1, 2, 3, 4, 0]); |
| 537 | + } |
| 538 | + |
| 539 | + #[test] |
| 540 | + fn test_write_volatile_for_cursor() { |
| 541 | + let mut write_buffer = vec![0u8; 7]; |
| 542 | + let mut input = [1, 2, 3, 4]; |
| 543 | + |
| 544 | + let mut cursor = Cursor::new(write_buffer.as_mut_slice()); |
| 545 | + |
| 546 | + // Write 4 bytes from volatile slice to cursor (amount written limited by volatile slice length) |
| 547 | + assert_eq!( |
| 548 | + cursor |
| 549 | + .write_volatile(&VolatileSlice::from(input.as_mut_slice())) |
| 550 | + .unwrap(), |
| 551 | + 4 |
| 552 | + ); |
| 553 | + assert_eq!(cursor.get_ref(), &[1, 2, 3, 4, 0, 0, 0]); |
| 554 | + |
| 555 | + // Write 3 bytes from volatile slice to cursor (amount written limited by remaining space in cursor) |
| 556 | + assert_eq!( |
| 557 | + cursor |
| 558 | + .write_volatile(&VolatileSlice::from(input.as_mut_slice())) |
| 559 | + .unwrap(), |
| 560 | + 3 |
| 561 | + ); |
| 562 | + assert_eq!(cursor.get_ref(), &[1, 2, 3, 4, 1, 2, 3]); |
| 563 | + } |
453 | 564 | }
|
0 commit comments