simple_bytes/
offset.rs

1
2use crate::{
3	BytesRead, ReadError, BytesWrite, WriteError, BytesSeek, SeekError, Bytes
4};
5
6/// A struct which holds a specific offset for any BytesRead,
7/// BytesWrite or BytesSeek implementation.
8///
9/// ## Example
10/// ```
11/// # use simple_bytes::{Offset, BytesOwned, BytesRead, BytesWrite, BytesSeek};
12/// let mut offset = Offset::new(BytesOwned::from(vec![1, 2, 3, 4]), 2);
13/// assert_eq!(offset.as_slice(), &[3, 4]);
14/// assert_eq!(offset.remaining(), &[3, 4]);
15/// offset.write_u8(5);
16/// assert_eq!(offset.as_slice(), &[5, 4]);
17/// assert_eq!(offset.remaining(), &[4]);
18/// offset.seek(2);
19/// offset.write_u8(5);
20/// assert_eq!(offset.as_slice(), &[5, 4, 5]);
21/// ```
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23pub struct Offset<T> {
24	// the offset gets applied to the inner
25	// position
26	offset: usize,
27	inner: T
28}
29
30impl<T> Offset<T> {
31
32	/// Creates a new Cursor.
33	///
34	/// May panic if the offset is bigger than the inner len.
35	/// Depending on inner.
36	pub fn new(mut inner: T, offset: usize) -> Self
37	where T: BytesRead + BytesSeek {
38		inner.seek(inner.position() + offset);
39		Self { inner, offset }
40	}
41
42	/// Updates the offset.
43	///
44	/// Maybe panic if there aren't enough bytes left.
45	pub fn set_offset(&mut self, offset: usize)
46	where T: BytesSeek {
47		let prev_pos = self.inner.position() - self.offset;
48		self.inner.seek(prev_pos + offset);
49		self.offset = offset;
50	}
51
52	/// Returns the current offset.
53	pub fn offset(&self) -> usize {
54		self.offset
55	}
56
57	/// Returns the inner value as a reference.
58	pub fn inner(&self) -> &T {
59		&self.inner
60	}
61
62	/// Returns the inner value as a mutable reference.
63	/// Shrinking the inner len or updating the position may lead
64	/// to panics when reading or writing.
65	pub fn inner_mut(&mut self) -> &mut T {
66		&mut self.inner
67	}
68
69	/// Returns the inner value, discarding the offset.
70	pub fn into_inner(self) -> T {
71		self.inner
72	}
73
74}
75
76impl<T> BytesRead for Offset<T>
77where T: BytesRead {
78	#[inline]
79	fn as_slice(&self) -> &[u8] {
80		&self.inner.as_slice()[self.offset..]
81	}
82
83	#[inline]
84	fn remaining(&self) -> &[u8] {
85		self.inner.remaining()
86	}
87
88	fn try_read(&mut self, len: usize) -> Result<&[u8], ReadError> {
89		self.inner.try_read(len)
90	}
91
92	fn peek(&self, len: usize) -> Option<&[u8]> {
93		self.inner.peek(len)
94	}
95}
96
97impl<T> BytesSeek for Offset<T>
98where T: BytesSeek {
99	/// Returns the internal position.
100	fn position(&self) -> usize {
101		self.inner.position() - self.offset
102	}
103
104	/// Sets the internal position.
105	/// 
106	/// ## Panics
107	/// Depending on the implementation.
108	fn try_seek(&mut self, pos: usize) -> Result<(), SeekError> {
109		self.inner.try_seek(self.offset + pos)
110	}
111}
112
113impl<T> BytesWrite for Offset<T>
114where T: BytesWrite {
115	fn as_mut(&mut self) -> &mut [u8] {
116		&mut self.inner.as_mut()[self.offset..]
117	}
118
119	fn as_bytes(&self) -> Bytes<'_> {
120		self.inner.as_bytes().inner()[self.offset..].into()
121	}
122
123	fn remaining_mut(&mut self) -> &mut [u8] {
124		self.inner.remaining_mut()
125	}
126
127	fn try_write(&mut self, slice: impl AsRef<[u8]>) -> Result<(), WriteError> {
128		self.inner.try_write(slice)
129	}
130}
131
132
133
134#[cfg(test)]
135mod tests {
136
137	use super::*;
138	use crate::Cursor;
139
140	#[test]
141	fn write() {
142
143		let cursor = Cursor::new(vec![1, 2, 3, 4]);
144		let mut offset_cursor = Offset::new(cursor, 2);
145		assert_eq!(offset_cursor.remaining_mut().len(), 2);
146		offset_cursor.write(&[1]);
147		assert_eq!(offset_cursor.remaining_mut().len(), 1);
148		offset_cursor.write(&[2]);
149		assert_eq!(offset_cursor.remaining_mut().len(), 0);
150		offset_cursor.write(&[1, 2]);
151
152		assert_eq!(offset_cursor.as_mut(), &[1, 2, 1, 2]);
153
154	}
155
156	#[test]
157	fn read() {
158
159		let cursor = Cursor::new(vec![1, 2, 3, 4]);
160		let mut offset_cursor = Offset::new(cursor, 2);
161		assert_eq!(offset_cursor.position(), 0);
162		offset_cursor.seek(1);
163		assert_eq!(offset_cursor.position(), 1);
164		assert_eq!(offset_cursor.as_slice(), &[3, 4]);
165		assert_eq!(offset_cursor.remaining(), &[4]);
166
167		offset_cursor.set_offset(1);
168		assert_eq!(offset_cursor.position(), 1);
169		assert_eq!(offset_cursor.as_slice(), &[2, 3, 4]);
170		assert_eq!(offset_cursor.remaining(), &[3, 4]);
171
172	}
173
174}