cyfs_chunk_lib/
mem_chunk.rs

1use std::io::{SeekFrom};
2use std::ops::{Deref, DerefMut};
3use cyfs_base::{BuckyError, BuckyErrorCode, BuckyResult};
4use crate::{Chunk, ChunkMeta, ChunkMut};
5
6pub struct MemChunk {
7    buf: Vec<u8>,
8    pos: usize,
9    data_len: usize,
10}
11
12impl MemChunk {
13    pub fn new(capacity: usize, data_len: usize) -> Self {
14        let mut buf = Vec::new();
15        buf.resize(capacity, 0);
16        Self {
17            buf,
18            pos: 0,
19            data_len
20        }
21    }
22
23    pub fn resize(&mut self, len: usize) {
24        if len < self.data_len {
25            self.data_len = len;
26        }
27        self.buf.resize(len, 0);
28    }
29
30    fn read_inner(&mut self, buf: &mut [u8]) -> BuckyResult<usize> {
31        if self.pos >= self.data_len {
32            Ok(0)
33        } else if buf.len() > self.data_len - self.pos {
34            unsafe {std::ptr::copy::<u8>(self.buf[self.pos..].as_ptr(), buf.as_mut_ptr(), self.data_len - self.pos)};
35            let read_len = self.data_len - self.pos;
36            self.pos = self.data_len;
37            Ok(read_len)
38        } else {
39            unsafe {std::ptr::copy::<u8>(self.buf[self.pos..self.pos + buf.len()].as_ptr(), buf.as_mut_ptr(), buf.len())};
40            let read_len = buf.len();
41            self.pos = self.pos + read_len;
42            Ok(read_len)
43        }
44    }
45
46    fn seek_inner(&mut self, pos: SeekFrom) -> BuckyResult<u64> {
47        match pos {
48            SeekFrom::Start(pos) => {
49                self.pos = pos as usize;
50                Ok(pos)
51            },
52            SeekFrom::End(pos) => {
53                if self.data_len as i64 + pos < 0 {
54                    return Err(BuckyError::new(BuckyErrorCode::Failed, format!("seek failed")));
55                }
56                self.pos = (self.data_len as i64 + pos) as usize;
57                Ok(self.pos as u64)
58            },
59            SeekFrom::Current(pos) => {
60                if self.pos as i64 + pos < 0 {
61                    return Err(BuckyError::new(BuckyErrorCode::Failed, format!("seek failed")));
62                }
63                self.pos = (self.pos as i64 + pos) as usize;
64                Ok(self.pos as u64)
65            }
66        }
67    }
68
69    fn write_inner(&mut self, buf: &[u8]) -> BuckyResult<usize> {
70        unsafe {
71            if self.pos + buf.len() >= self.buf.len() {
72                let write_size = self.buf.len() - self.pos;
73                std::ptr::copy(buf.as_ptr(), self.buf.as_mut_ptr(), write_size);
74                self.pos = self.buf.len();
75                if self.pos > self.data_len {
76                    self.data_len = self.pos;
77                }
78                Ok(write_size)
79            } else {
80                std::ptr::copy(buf.as_ptr(), self.buf.as_mut_ptr(), buf.len());
81                self.pos += buf.len();
82                if self.pos > self.data_len {
83                    self.data_len = self.pos;
84                }
85                Ok(buf.len())
86            }
87        }
88    }
89}
90
91impl From<Vec<u8>> for MemChunk {
92    fn from(buf: Vec<u8>) -> Self {
93        Self {
94            data_len: buf.len(),
95            buf,
96            pos: 0
97        }
98    }
99}
100
101impl Deref for MemChunk {
102    type Target = [u8];
103
104    fn deref(&self) -> &Self::Target {
105        self.buf.as_slice()
106    }
107}
108
109#[async_trait::async_trait]
110impl Chunk for MemChunk {
111    fn get_chunk_meta(&self) -> ChunkMeta {
112        ChunkMeta::MemChunk(self.buf[..self.data_len].to_vec())
113    }
114
115    fn get_len(&self) -> usize {
116        self.data_len
117    }
118
119    fn into_vec(self: Box<Self>) -> Vec<u8> {
120        if self.buf.len() == self.data_len {
121            self.buf
122        } else {
123            self.buf[..self.data_len].to_vec()
124        }
125    }
126
127    async fn read(&mut self, buf: &mut [u8]) -> BuckyResult<usize> {
128        self.read_inner(buf)
129    }
130
131    async fn seek(&mut self, pos: SeekFrom) -> BuckyResult<u64> {
132        self.seek_inner(pos)
133    }
134}
135
136impl DerefMut for MemChunk {
137    fn deref_mut(&mut self) -> &mut Self::Target {
138        self.buf.as_mut_slice()
139    }
140}
141
142#[async_trait::async_trait]
143impl ChunkMut for MemChunk {
144    async fn reset(&mut self) -> BuckyResult<()> {
145        self.pos = 0;
146        self.data_len = 0;
147        Ok(())
148    }
149
150    async fn write(&mut self, buf: &[u8]) -> BuckyResult<usize> {
151        self.write_inner(buf)
152    }
153
154    async fn flush(&mut self) -> BuckyResult<()> {
155        Ok(())
156    }
157}
158
159pub struct MemRefChunk<'a> {
160    buf: &'a [u8],
161    pos: usize,
162}
163
164impl<'a> MemRefChunk<'a> {
165    fn read_inner(&mut self, buf: &mut [u8]) -> BuckyResult<usize> {
166        if self.pos >= self.buf.len() {
167            Ok(0)
168        } else if buf.len() > self.buf.len() - self.pos {
169            unsafe {std::ptr::copy::<u8>(self.buf[self.pos..].as_ptr(), buf.as_mut_ptr(), self.buf.len() - self.pos)};
170            let read_len = self.buf.len() - self.pos;
171            self.pos = self.buf.len();
172            Ok(read_len)
173        } else {
174            unsafe {std::ptr::copy::<u8>(self.buf[self.pos..self.pos + buf.len()].as_ptr(), buf.as_mut_ptr(), buf.len())};
175            let read_len = buf.len();
176            self.pos = self.pos + read_len;
177            Ok(read_len)
178        }
179    }
180
181    fn seek_inner(&mut self, pos: SeekFrom) -> BuckyResult<u64> {
182        match pos {
183            SeekFrom::Start(pos) => {
184                self.pos = pos as usize;
185                Ok(pos)
186            },
187            SeekFrom::End(pos) => {
188                if self.buf.len() as i64 + pos < 0 {
189                    return Err(BuckyError::new(BuckyErrorCode::Failed, format!("seek failed")));
190                }
191                self.pos = (self.buf.len() as i64 + pos) as usize;
192                Ok(self.pos as u64)
193            },
194            SeekFrom::Current(pos) => {
195                if self.pos as i64 + pos < 0 {
196                    return Err(BuckyError::new(BuckyErrorCode::Failed, format!("seek failed")));
197                }
198                self.pos = (self.pos as i64 + pos) as usize;
199                Ok(self.pos as u64)
200            }
201        }
202    }
203}
204impl <'a> From<&'a [u8]> for MemRefChunk<'a> {
205    fn from(buf: &'a [u8]) -> Self {
206        Self {
207            buf,
208            pos: 0
209        }
210    }
211}
212
213impl <'a> Deref for MemRefChunk<'a> {
214    type Target = [u8];
215
216    fn deref(&self) -> &'a Self::Target {
217        self.buf
218    }
219}
220
221#[async_trait::async_trait]
222impl <'a> Chunk for MemRefChunk<'a> {
223    fn get_chunk_meta(&self) -> ChunkMeta {
224        ChunkMeta::MemChunk(self.buf.to_vec())
225    }
226
227    fn get_len(&self) -> usize {
228        self.buf.len()
229    }
230
231    fn into_vec(self: Box<Self>) -> Vec<u8> {
232        self.buf.to_vec()
233    }
234
235    async fn read(&mut self, buf: &mut [u8]) -> BuckyResult<usize> {
236        self.read_inner(buf)
237    }
238
239    async fn seek(&mut self, pos: SeekFrom) -> BuckyResult<u64> {
240        self.seek_inner(pos)
241    }
242}
243
244#[cfg(test)]
245mod test_mem_chunk {
246    use std::sync::Arc;
247    use crate::{Chunk, ChunkMut, MemChunk, MemRefChunk, SharedMemChunk};
248
249    #[test]
250    fn test_mem_ref_chunk() {
251        let buf = {
252            let mut buf = Vec::<u8>::new();
253            buf.resize(20, 0);
254            Arc::new(buf)
255        };
256        let chunk = MemRefChunk::from(buf.as_slice());
257
258        let s = &chunk[..];
259        assert_eq!(s.len(), 20);
260    }
261
262    #[test]
263    fn test_mem_async_test() {
264        async_std::task::block_on(async move {
265            let mut mem_chunk = MemChunk::new(20, 0);
266            mem_chunk.write("test".as_bytes()).await.unwrap();
267        })
268    }
269
270    #[test]
271    fn test_share_mem_test() {
272        async_std::task::block_on(async move {
273            let mut mem_chunk = SharedMemChunk::new(20, 0, "test").unwrap();
274            mem_chunk.write("test".as_bytes()).await.unwrap();
275
276            let mut mem_chunk2 = SharedMemChunk::new(20, mem_chunk.get_len(), "test").unwrap();
277            let mut buf = [0u8;4];
278            mem_chunk2.read(&mut buf).await.unwrap();
279            println!("{} {}", mem_chunk.len(), mem_chunk2.len());
280
281            assert_eq!(20, mem_chunk.len());
282            assert_eq!(20, mem_chunk2.len());
283            assert_eq!("test", String::from_utf8_lossy(&buf).to_string().as_str());
284        })
285    }
286}