rustix/ioctl/
patterns.rs
1use super::{Ioctl, IoctlOutput, Opcode, RawOpcode};
4
5use crate::backend::c;
6use crate::io::Result;
7
8use core::marker::PhantomData;
9use core::ptr::addr_of_mut;
10use core::{fmt, mem};
11
12pub struct NoArg<Opcode> {
14 _opcode: PhantomData<Opcode>,
16}
17
18impl<Opcode: CompileTimeOpcode> fmt::Debug for NoArg<Opcode> {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 f.debug_tuple("NoArg").field(&Opcode::OPCODE).finish()
21 }
22}
23
24impl<Opcode: CompileTimeOpcode> NoArg<Opcode> {
25 #[inline]
31 pub unsafe fn new() -> Self {
32 Self {
33 _opcode: PhantomData,
34 }
35 }
36}
37
38unsafe impl<Opcode: CompileTimeOpcode> Ioctl for NoArg<Opcode> {
39 type Output = ();
40
41 const IS_MUTATING: bool = false;
42 const OPCODE: self::Opcode = Opcode::OPCODE;
43
44 fn as_ptr(&mut self) -> *mut c::c_void {
45 core::ptr::null_mut()
46 }
47
48 unsafe fn output_from_ptr(_: IoctlOutput, _: *mut c::c_void) -> Result<Self::Output> {
49 Ok(())
50 }
51}
52
53pub struct Getter<Opcode, Output> {
58 output: mem::MaybeUninit<Output>,
60
61 _opcode: PhantomData<Opcode>,
63}
64
65impl<Opcode: CompileTimeOpcode, Output> fmt::Debug for Getter<Opcode, Output> {
66 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
67 f.debug_tuple("Getter").field(&Opcode::OPCODE).finish()
68 }
69}
70
71impl<Opcode: CompileTimeOpcode, Output> Getter<Opcode, Output> {
72 #[inline]
80 pub unsafe fn new() -> Self {
81 Self {
82 output: mem::MaybeUninit::uninit(),
83 _opcode: PhantomData,
84 }
85 }
86}
87
88unsafe impl<Opcode: CompileTimeOpcode, Output> Ioctl for Getter<Opcode, Output> {
89 type Output = Output;
90
91 const IS_MUTATING: bool = true;
92 const OPCODE: self::Opcode = Opcode::OPCODE;
93
94 fn as_ptr(&mut self) -> *mut c::c_void {
95 self.output.as_mut_ptr().cast()
96 }
97
98 unsafe fn output_from_ptr(_: IoctlOutput, ptr: *mut c::c_void) -> Result<Self::Output> {
99 Ok(ptr.cast::<Output>().read())
100 }
101}
102
103pub struct Setter<Opcode, Input> {
108 input: Input,
110
111 _opcode: PhantomData<Opcode>,
113}
114
115impl<Opcode: CompileTimeOpcode, Input: fmt::Debug> fmt::Debug for Setter<Opcode, Input> {
116 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117 f.debug_tuple("Setter")
118 .field(&Opcode::OPCODE)
119 .field(&self.input)
120 .finish()
121 }
122}
123
124impl<Opcode: CompileTimeOpcode, Input> Setter<Opcode, Input> {
125 #[inline]
133 pub unsafe fn new(input: Input) -> Self {
134 Self {
135 input,
136 _opcode: PhantomData,
137 }
138 }
139}
140
141unsafe impl<Opcode: CompileTimeOpcode, Input> Ioctl for Setter<Opcode, Input> {
142 type Output = ();
143
144 const IS_MUTATING: bool = false;
145 const OPCODE: self::Opcode = Opcode::OPCODE;
146
147 fn as_ptr(&mut self) -> *mut c::c_void {
148 addr_of_mut!(self.input).cast::<c::c_void>()
149 }
150
151 unsafe fn output_from_ptr(_: IoctlOutput, _: *mut c::c_void) -> Result<Self::Output> {
152 Ok(())
153 }
154}
155
156pub trait CompileTimeOpcode {
158 const OPCODE: Opcode;
160}
161
162pub struct BadOpcode<const OPCODE: RawOpcode>;
164
165impl<const OPCODE: RawOpcode> CompileTimeOpcode for BadOpcode<OPCODE> {
166 const OPCODE: Opcode = Opcode::old(OPCODE);
167}
168
169#[cfg(any(linux_kernel, bsd))]
173pub struct ReadOpcode<const GROUP: u8, const NUM: u8, Data>(Data);
174
175#[cfg(any(linux_kernel, bsd))]
176impl<const GROUP: u8, const NUM: u8, Data> CompileTimeOpcode for ReadOpcode<GROUP, NUM, Data> {
177 const OPCODE: Opcode = Opcode::read::<Data>(GROUP, NUM);
178}
179
180#[cfg(any(linux_kernel, bsd))]
184pub struct WriteOpcode<const GROUP: u8, const NUM: u8, Data>(Data);
185
186#[cfg(any(linux_kernel, bsd))]
187impl<const GROUP: u8, const NUM: u8, Data> CompileTimeOpcode for WriteOpcode<GROUP, NUM, Data> {
188 const OPCODE: Opcode = Opcode::write::<Data>(GROUP, NUM);
189}
190
191#[cfg(any(linux_kernel, bsd))]
195pub struct ReadWriteOpcode<const GROUP: u8, const NUM: u8, Data>(Data);
196
197#[cfg(any(linux_kernel, bsd))]
198impl<const GROUP: u8, const NUM: u8, Data> CompileTimeOpcode for ReadWriteOpcode<GROUP, NUM, Data> {
199 const OPCODE: Opcode = Opcode::read_write::<Data>(GROUP, NUM);
200}
201
202#[cfg(any(linux_kernel, bsd))]
207pub struct NoneOpcode<const GROUP: u8, const NUM: u8, Data>(Data);
208
209#[cfg(any(linux_kernel, bsd))]
210impl<const GROUP: u8, const NUM: u8, Data> CompileTimeOpcode for NoneOpcode<GROUP, NUM, Data> {
211 const OPCODE: Opcode = Opcode::none::<Data>(GROUP, NUM);
212}