1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
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<T: 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<T: Pod>(&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<T: Pod>(&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<T: Pod>(&mut self, val: &[T]) {
self.write_bytes(bytes_of_slice(val))
}
}
impl WritableBuffer for Vec<u8> {
#[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<T: Pod>(self, offset: usize, val: &T) -> Result<(), ()>;
}
impl<'a> BytesMut for &'a mut [u8] {
#[inline]
fn write_at<T: Pod>(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)
}
#[allow(dead_code)]
pub(crate) fn align_u64(offset: u64, size: u64) -> u64 {
(offset + (size - 1)) & !(size - 1)
}
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(()));
}
}
|