X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=vendor%2Fobject%2Fsrc%2Fwrite%2Futil.rs;h=bb6b8597bb872e04e6084ed707469b5122d8c3ed;hb=136023e0d2a1df774e51528802f856b3e8c9ad35;hp=c108f47485a7e46931806bf742ccf06f07f4a453;hpb=17df50a58d5a9bb4f74c08ec63674fae2b6e3bcc;p=rustc.git diff --git a/vendor/object/src/write/util.rs b/vendor/object/src/write/util.rs index c108f47485..bb6b8597bb 100644 --- a/vendor/object/src/write/util.rs +++ b/vendor/object/src/write/util.rs @@ -1,4 +1,92 @@ -use crate::pod::WritableBuffer; +use std::vec::Vec; + +use crate::pod::{bytes_of, bytes_of_slice, Pod}; + +/// Trait for writable buffer. +#[allow(clippy::len_without_is_empty)] +pub trait WritableBuffer { + /// Returns position/offset for data to be written at. + fn len(&self) -> usize; + + /// Reserves specified number of bytes in the buffer. + fn reserve(&mut self, additional: usize) -> Result<(), ()>; + + /// Writes the specified value at the end of the buffer + /// until the buffer has the specified length. + fn resize(&mut self, new_len: usize, value: u8); + + /// Writes the specified slice of bytes at the end of the buffer. + fn write_bytes(&mut self, val: &[u8]); + + /// Writes the specified `Pod` type at the end of the buffer. + fn write_pod(&mut self, val: &T) + where + Self: Sized, + { + self.write_bytes(bytes_of(val)) + } + + /// Writes the specified `Pod` slice at the end of the buffer. + fn write_pod_slice(&mut self, val: &[T]) + where + Self: Sized, + { + self.write_bytes(bytes_of_slice(val)) + } +} + +impl<'a> dyn WritableBuffer + 'a { + /// Writes the specified `Pod` type at the end of the buffer. + pub fn write(&mut self, val: &T) { + self.write_bytes(bytes_of(val)) + } + + /// Writes the specified `Pod` slice at the end of the buffer. + pub fn write_slice(&mut self, val: &[T]) { + self.write_bytes(bytes_of_slice(val)) + } +} + +impl WritableBuffer for Vec { + #[inline] + fn len(&self) -> usize { + self.len() + } + + #[inline] + fn reserve(&mut self, additional: usize) -> Result<(), ()> { + self.reserve(additional); + Ok(()) + } + + #[inline] + fn resize(&mut self, new_len: usize, value: u8) { + self.resize(new_len, value); + } + + #[inline] + fn write_bytes(&mut self, val: &[u8]) { + self.extend_from_slice(val) + } +} + +/// A trait for mutable byte slices. +/// +/// It provides convenience methods for `Pod` types. +pub(crate) trait BytesMut { + fn write_at(self, offset: usize, val: &T) -> Result<(), ()>; +} + +impl<'a> BytesMut for &'a mut [u8] { + #[inline] + fn write_at(self, offset: usize, val: &T) -> Result<(), ()> { + let src = bytes_of(val); + let dest = self.get_mut(offset..).ok_or(())?; + let dest = dest.get_mut(..src.len()).ok_or(())?; + dest.copy_from_slice(src); + Ok(()) + } +} pub(crate) fn align(offset: usize, size: usize) -> usize { (offset + (size - 1)) & !(size - 1) @@ -13,3 +101,29 @@ pub(crate) fn write_align(buffer: &mut dyn WritableBuffer, size: usize) { let new_len = align(buffer.len(), size); buffer.resize(new_len, 0); } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn bytes_mut() { + let data = vec![0x01, 0x23, 0x45, 0x67]; + + let mut bytes = data.clone(); + bytes.extend_from_slice(bytes_of(&u16::to_be(0x89ab))); + assert_eq!(bytes, [0x01, 0x23, 0x45, 0x67, 0x89, 0xab]); + + let mut bytes = data.clone(); + assert_eq!(bytes.write_at(0, &u16::to_be(0x89ab)), Ok(())); + assert_eq!(bytes, [0x89, 0xab, 0x45, 0x67]); + + let mut bytes = data.clone(); + assert_eq!(bytes.write_at(2, &u16::to_be(0x89ab)), Ok(())); + assert_eq!(bytes, [0x01, 0x23, 0x89, 0xab]); + + assert_eq!(bytes.write_at(3, &u16::to_be(0x89ab)), Err(())); + assert_eq!(bytes.write_at(4, &u16::to_be(0x89ab)), Err(())); + assert_eq!(vec![].write_at(0, &u32::to_be(0x89ab)), Err(())); + } +}