1use core::{cell::Cell, ops::{Deref, DerefMut}};
2
3use crate::{Buffer, BufferError};
4
5pub trait BufferWriter: DerefMut<Target = [u8]> {
7
8 fn commit(&self, n: usize) -> Result<(), BufferError>;
11
12 fn remaining_capacity(&self) -> usize;
14
15 fn has_remaining_capacity(&self) -> bool {
17 self.remaining_capacity() > 0
18 }
19}
20
21pub struct Write<'a, T: AsMut<[u8]> + AsRef<[u8]>> {
23 buffer: &'a mut Buffer<T>,
24 bytes_written: Cell<usize>
25}
26
27impl <'a, T: AsMut<[u8]> + AsRef<[u8]>> Write<'a, T> {
28 pub(crate) fn new(buffer: &'a mut Buffer<T>) -> Self {
29 Self {
30 buffer,
31 bytes_written: Cell::new(0)
32 }
33 }
34}
35
36impl <'a, T: AsMut<[u8]> + AsRef<[u8]>> BufferWriter for Write<'a, T> {
37
38 fn commit(&self, n: usize) -> Result<(), BufferError> {
39 if self.remaining_capacity() < n {
40 Err(BufferError::NoCapacity)
41 } else {
42 self.bytes_written.set(
43 self.bytes_written.get() + n
44 );
45 Ok(())
46 }
47 }
48
49 fn remaining_capacity(&self) -> usize {
50 self.buffer.capacity() - self.buffer.write_position - self.bytes_written.get()
51 }
52}
53
54impl <'a, T: AsMut<[u8]> + AsRef<[u8]>> Drop for Write<'a, T> {
55 fn drop(&mut self) {
56
57 self.buffer.write_position += self.bytes_written.get();
58 if self.buffer.write_position > self.buffer.source.as_ref().len() {
59 panic!("illegal state: Write<'a, T> committed more bytes than available!")
60 }
61
62 }
63}
64
65impl <'a, T: AsMut<[u8]> + AsRef<[u8]>> Deref for Write<'a, T>{
66 type Target = [u8];
67
68 fn deref(&self) -> &Self::Target {
69 let tgt = self.buffer.source.as_ref();
70 let offset = self.buffer.write_position + self.bytes_written.get();
71 &tgt[offset..]
72 }
73}
74
75impl <'a, T: AsMut<[u8]> + AsRef<[u8]>> DerefMut for Write<'a, T>{
76 fn deref_mut(&mut self) -> &mut Self::Target {
77 let tgt = self.buffer.source.as_mut();
78 let offset = self.buffer.write_position + self.bytes_written.get();
79 &mut tgt[offset..]
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use crate::{Buffer, BufferWriter, ReadWrite};
86
87
88 #[test]
89 fn test_write() {
90 let mut b = [0u8; 8];
91 let mut buf = Buffer::new(&mut b);
92
93 buf.write_base(&[1, 2]).unwrap();
94
95
96 let mut write = buf.create_writer();
97 write[0] = 3;
98 write[1] = 4;
99
100 write.commit(2).unwrap();
101 drop(write);
102
103 assert_eq!(buf.data(), &[1, 2, 3, 4]);
104 }
105
106 #[test]
107 fn test_multi_write() {
108 let mut b = [0u8; 8];
109 let mut buf = Buffer::new(&mut b);
110
111 let mut write = buf.create_writer();
112 write[0] = 1;
113 write[1] = 2;
114 write.commit(2).unwrap();
115 drop(write);
116
117 let mut write = buf.create_writer();
118 write[0] = 3;
119 write[1] = 4;
120 write.commit(2).unwrap();
121 drop(write);
122
123 assert_eq!(buf.data(), &[1, 2, 3, 4]);
124 assert_eq!(buf.write_position, 4);
125 }
126
127}