embytes_buffer/
write.rs

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