file_system/fundamentals/
control.rs1use shared::{AnyByLayout, flags};
2
3use crate::{Error, Result};
4
5flags! {
6 pub enum ControlDirectionFlags: u8 {
8 Read,
10 Write,
12 }
13}
14
15struct ControlCommandInputOutput<I, O> {
16 pub _input: I,
17 pub _output: O,
18}
19
20pub trait ControlCommand: Clone + Copy {
21 type Input;
22 type Output;
23
24 const IDENTIFIER: ControlCommandIdentifier;
25
26 fn cast_input(input: &AnyByLayout) -> Result<&Self::Input> {
27 input.cast().ok_or(Error::InvalidParameter)
28 }
29
30 fn cast_output(output: &mut AnyByLayout) -> Result<&mut Self::Output> {
31 output.cast_mutable().ok_or(Error::InvalidParameter)
32 }
33
34 fn cast<'i, 'o>(
35 input: &'i AnyByLayout,
36 output: &'o mut AnyByLayout,
37 ) -> Result<(&'i Self::Input, &'o mut Self::Output)> {
38 Ok((Self::cast_input(input)?, Self::cast_output(output)?))
39 }
40}
41
42#[macro_export]
43macro_rules! define_command {
44 ($name:ident, Read, $kind:expr, $number:expr, $I:ty, $O:ty) => {
45 $crate::define_command!(
46 $name,
47 $crate::ControlDirectionFlags::Read,
48 $kind,
49 $number,
50 $I,
51 $O
52 );
53 };
54 ($name:ident, Write, $kind:expr, $number:expr, $I:ty, $O:ty) => {
55 $crate::define_command!(
56 $name,
57 $crate::ControlDirectionFlags::Write,
58 $kind,
59 $number,
60 $I,
61 $O
62 );
63 };
64 ($name:ident, $direction:expr, $kind:expr, $number:expr, $I:ty, $O:ty) => {
65 #[derive(Clone, Copy, Debug)]
66 #[allow(non_camel_case_types)]
67 pub struct $name;
68
69 impl ControlCommand for $name {
70 type Input = $I;
71 type Output = $O;
72
73 const IDENTIFIER: $crate::ControlCommandIdentifier =
74 $crate::ControlCommandIdentifier::new::<$I, $O>($direction, $kind, $number);
75 }
76 };
77}
78
79#[repr(transparent)]
80#[derive(Clone, Copy, Debug, PartialEq, Eq)]
81pub struct ControlCommandIdentifier(usize);
82
83impl ControlCommandIdentifier {
84 const NUMBER_SIZE: usize = 8;
85 const KIND_SIZE: usize = 8;
86 const SIZE_SIZE: usize = 14;
87 const DIRECTION_SIZE: usize = 2;
88
89 const NUMBER_SHIFT: usize = 0;
90 const KIND_SHIFT: usize = Self::NUMBER_SHIFT + Self::NUMBER_SIZE; const SIZE_SHIFT: usize = Self::KIND_SHIFT + Self::KIND_SIZE; const DIRECTION_SHIFT: usize = Self::SIZE_SHIFT + Self::SIZE_SIZE; pub const fn new<I, O>(direction: ControlDirectionFlags, kind: u8, number: u8) -> Self {
95 let size = core::mem::size_of::<ControlCommandInputOutput<I, O>>();
96
97 Self::new_with_size(direction, size, kind, number)
98 }
99
100 pub const fn new_read<I, O>(kind: u8, number: u8) -> Self {
101 Self::new_with_size(
102 ControlDirectionFlags::Read,
103 size_of::<ControlCommandInputOutput<I, O>>(),
104 kind,
105 number,
106 )
107 }
108
109 pub const fn new_write<I, O>(kind: u8, number: u8) -> Self {
110 Self::new_with_size(
111 ControlDirectionFlags::Write,
112 size_of::<ControlCommandInputOutput<I, O>>(),
113 kind,
114 number,
115 )
116 }
117
118 pub const fn new_with_size(
119 direction: ControlDirectionFlags,
120 size: usize,
121 kind: u8,
122 number: u8,
123 ) -> Self {
124 let direction = direction.bits() as usize;
125 let kind = kind as usize;
126 let number = number as usize;
127
128 Self(
129 (direction << Self::DIRECTION_SHIFT)
130 | (size << Self::SIZE_SHIFT)
131 | (kind << Self::KIND_SHIFT)
132 | (number << Self::NUMBER_SHIFT),
133 )
134 }
135
136 pub const fn get_direction(&self) -> ControlDirectionFlags {
137 let direction = (self.0 >> Self::DIRECTION_SHIFT) & ((1 << Self::DIRECTION_SIZE) - 1);
138 ControlDirectionFlags(direction as u8)
139 }
140
141 pub const fn get_size(&self) -> usize {
142 (self.0 >> Self::SIZE_SHIFT) & ((1 << Self::SIZE_SIZE) - 1)
143 }
144
145 pub const fn get_kind(&self) -> u8 {
146 ((self.0 >> Self::KIND_SHIFT) & ((1 << Self::KIND_SIZE) - 1)) as u8
147 }
148
149 pub const fn get_number(&self) -> u8 {
150 ((self.0 >> Self::NUMBER_SHIFT) & ((1 << Self::NUMBER_SIZE) - 1)) as u8
151 }
152}