1use super::{
2 traits::{
3 ReplyGather, ReplyOk, RequestData, RequestFlags, RequestHandle, RequestOffset, RequestSize,
4 },
5 FromRequest,
6};
7
8use crate::{io::FsyncFlags, proto, sealed::Sealed, Done, Operation, Reply, Request};
9
10pub enum Readlink {}
11pub enum Read {}
12pub enum Write {}
13pub enum Fsync {}
14pub enum Flush {}
15pub enum Fsyncdir {}
16
17pub struct WriteState {
18 size: u32,
19}
20
21pub trait ReplyAll<'o>: Operation<'o> {
22 fn all(reply: Reply<'o, Self>) -> Done<'o>;
23}
24
25impl Sealed for Readlink {}
26impl Sealed for Read {}
27impl Sealed for Write {}
28impl Sealed for Fsync {}
29impl Sealed for Flush {}
30impl Sealed for Fsyncdir {}
31
32impl<'o> Operation<'o> for Readlink {
33 type RequestBody = ();
34 type ReplyState = ();
35}
36
37impl<'o> Operation<'o> for Read {
38 type RequestBody = &'o proto::ReadIn;
39 type ReplyState = ();
40}
41
42impl<'o> Operation<'o> for Write {
43 type RequestBody = (&'o proto::WriteIn, &'o [u8]);
44 type ReplyState = WriteState;
45}
46
47impl<'o> Operation<'o> for Fsync {
48 type RequestBody = &'o proto::FsyncIn;
49 type ReplyState = ();
50}
51
52impl<'o> Operation<'o> for Flush {
53 type RequestBody = &'o proto::FlushIn;
54 type ReplyState = ();
55}
56
57impl<'o> Operation<'o> for Fsyncdir {
58 type RequestBody = &'o proto::FsyncdirIn;
59 type ReplyState = ();
60}
61
62impl<'o> ReplyGather<'o> for Readlink {}
63
64impl<'o> RequestHandle<'o> for Read {
65 fn handle(request: &Request<'o, Self>) -> u64 {
66 request.body.fh
67 }
68}
69
70impl<'o> RequestOffset<'o> for Read {
71 fn offset(request: &Request<'o, Self>) -> u64 {
72 request.body.offset
73 }
74}
75
76impl<'o> RequestSize<'o> for Read {
77 fn size(request: &Request<'o, Self>) -> u32 {
78 request.body.size
79 }
80}
81
82impl<'o> ReplyGather<'o> for Read {}
83
84impl<'o> RequestHandle<'o> for Write {
85 fn handle(request: &Request<'o, Self>) -> u64 {
86 request.body.0.fh
87 }
88}
89
90impl<'o> RequestOffset<'o> for Write {
91 fn offset(request: &Request<'o, Self>) -> u64 {
92 request.body.0.offset
93 }
94}
95
96impl<'o> RequestData<'o> for Write {
97 fn data<'a>(request: &'a Request<'o, Self>) -> &'a [u8] {
98 request.body.1
99 }
100}
101
102impl<'o> ReplyAll<'o> for Write {
103 fn all(reply: Reply<'o, Self>) -> Done<'o> {
104 let size = reply.state.size;
105 reply.single(&proto::WriteOut {
106 size,
107 padding: Default::default(),
108 })
109 }
110}
111
112impl<'o> RequestHandle<'o> for Fsync {
113 fn handle(request: &Request<'o, Self>) -> u64 {
114 request.body.fh
115 }
116}
117
118impl<'o> RequestFlags<'o> for Fsync {
119 type Flags = FsyncFlags;
120
121 fn flags(request: &Request<'o, Self>) -> Self::Flags {
122 FsyncFlags::from_bits_truncate(request.body.fsync_flags)
123 }
124}
125
126impl<'o> ReplyOk<'o> for Fsync {}
127
128impl<'o> RequestHandle<'o> for Flush {
129 fn handle(request: &Request<'o, Self>) -> u64 {
130 request.body.fh
131 }
132}
133
134impl<'o> ReplyOk<'o> for Flush {}
135
136impl<'o> RequestHandle<'o> for Fsyncdir {
137 fn handle(request: &Request<'o, Self>) -> u64 {
138 request.body.fsync_in.fh
139 }
140}
141
142impl<'o> RequestFlags<'o> for Fsyncdir {
143 type Flags = FsyncFlags;
144
145 fn flags(request: &Request<'o, Self>) -> Self::Flags {
146 FsyncFlags::from_bits_truncate(request.body.fsync_in.fsync_flags)
147 }
148}
149
150impl<'o> ReplyOk<'o> for Fsyncdir {}
151
152impl<'o> FromRequest<'o, Write> for WriteState {
153 fn from_request(request: &Request<'o, Write>) -> Self {
154 let (body, data) = request.body;
155
156 if body.size as usize != data.len() {
157 log::warn!(
158 "Write size={} differs from data.len={}",
159 body.size,
160 data.len()
161 );
162 }
163
164 WriteState { size: body.size }
165 }
166}