async_fuser/ll/reply_async/
read.rs1use std::io::IoSlice;
5use std::sync::Arc;
6
7use crate::ll::{ioslice_concat::IosliceConcat, reply::Response};
8
9#[derive(Debug)]
12enum ReadResponseData {
13 Owned(Vec<u8>),
14 Shared {
15 data: Arc<[u8]>,
16 start: usize,
17 end: usize,
18 },
19}
20
21#[derive(Debug)]
23pub struct ReadResponse {
24 data: ReadResponseData,
25}
26
27impl ReadResponse {
28 pub fn new(data: Vec<u8>) -> ReadResponse {
30 ReadResponse {
31 data: ReadResponseData::Owned(data),
32 }
33 }
34
35 pub fn from_shared_slice(data: Arc<[u8]>, offset: usize, size: usize) -> ReadResponse {
39 let start = offset.min(data.len());
40 let end = start.saturating_add(size).min(data.len());
41 ReadResponse {
42 data: ReadResponseData::Shared { data, start, end },
43 }
44 }
45
46 fn bytes(&self) -> &[u8] {
47 match &self.data {
48 ReadResponseData::Owned(data) => data.as_slice(),
49 ReadResponseData::Shared { data, start, end } => &data[*start..*end],
50 }
51 }
52}
53
54impl Response for ReadResponse {
55 fn payload(&self) -> impl IosliceConcat {
56 [IoSlice::new(self.bytes())]
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::ReadResponse;
63 use std::sync::Arc;
64
65 #[test]
66 fn shared_slice_clamps_to_bounds() {
67 let response = ReadResponse::from_shared_slice(Arc::from(&b"abcdef"[..]), 2, 99);
68 assert_eq!(response.bytes(), b"cdef");
69 }
70
71 #[test]
72 fn shared_slice_handles_offset_past_end() {
73 let response = ReadResponse::from_shared_slice(Arc::from(&b"abcdef"[..]), 99, 4);
74 assert_eq!(response.bytes(), b"");
75 }
76}