interprocess_docfix/os/windows/named_pipe/enums.rs
1use super::super::imports::*;
2use std::{convert::TryFrom, mem};
3
4/// The direction of a named pipe connection, designating who can read data and who can write it. This describes the direction of the data flow unambiguously, so that the meaning of the values is the same for the client and server – [`ClientToServer`] always means client → server, for example.
5///
6/// [`ClientToServer`]: enum.PipeDirection.html#variant.ClientToServer " "
7// I had to type out both the link to the page and the name of the variant since the link can be clicked from module-level documentation so please don't touch it.
8#[repr(u32)]
9// We depend on the fact that DWORD always maps to u32, which, thankfully, will always stay true
10// since the public WinAPI is supposed to be ABI-compatible. Just keep in mind that the
11// #[repr(u32)] means that we can transmute this enumeration to the Windows DWORD type.
12#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
13pub enum PipeDirection {
14 /// Represents a server ← client data flow: clients write data, the server reads it.
15 ClientToServer = PIPE_ACCESS_INBOUND,
16 /// Represents a server → client data flow: the server writes data, clients read it.
17 ServerToClient = PIPE_ACCESS_OUTBOUND,
18 /// Represents a server ⇄ client data flow: the server can write data which then is read by the client, while the client writes data which is read by the server.
19 Duplex = PIPE_ACCESS_DUPLEX,
20}
21impl PipeDirection {
22 /// Returns the role which the pipe client will have in this direction setting.
23 ///
24 /// # Usage
25 /// ```
26 /// # #[cfg(windows)] {
27 /// # use interprocess::os::windows::named_pipe::{PipeDirection, PipeStreamRole};
28 /// assert_eq!(
29 /// PipeDirection::ClientToServer.client_role(),
30 /// PipeStreamRole::Writer,
31 /// );
32 /// assert_eq!(
33 /// PipeDirection::ServerToClient.client_role(),
34 /// PipeStreamRole::Reader,
35 /// );
36 /// assert_eq!(
37 /// PipeDirection::Duplex.client_role(),
38 /// PipeStreamRole::ReaderAndWriter,
39 /// );
40 /// # }
41 /// ```
42 pub const fn client_role(self) -> PipeStreamRole {
43 match self {
44 Self::ClientToServer => PipeStreamRole::Writer,
45 Self::ServerToClient => PipeStreamRole::Reader,
46 Self::Duplex => PipeStreamRole::ReaderAndWriter,
47 }
48 }
49 /// Returns the role which the pipe server will have in this direction setting.
50 ///
51 /// # Usage
52 /// ```
53 /// # #[cfg(windows)] {
54 /// # use interprocess::os::windows::named_pipe::{PipeDirection, PipeStreamRole};
55 /// assert_eq!(
56 /// PipeDirection::ClientToServer.server_role(),
57 /// PipeStreamRole::Reader,
58 /// );
59 /// assert_eq!(
60 /// PipeDirection::ServerToClient.server_role(),
61 /// PipeStreamRole::Writer,
62 /// );
63 /// assert_eq!(
64 /// PipeDirection::Duplex.server_role(),
65 /// PipeStreamRole::ReaderAndWriter,
66 /// );
67 /// # }
68 /// ```
69 pub const fn server_role(self) -> PipeStreamRole {
70 match self {
71 Self::ClientToServer => PipeStreamRole::Reader,
72 Self::ServerToClient => PipeStreamRole::Writer,
73 Self::Duplex => PipeStreamRole::ReaderAndWriter,
74 }
75 }
76}
77impl TryFrom<DWORD> for PipeDirection {
78 type Error = ();
79 /// Converts a Windows constant to a `PipeDirection` if it's in range.
80 ///
81 /// # Errors
82 /// Returns `Err` if the value is not a valid pipe direction constant.
83 fn try_from(op: DWORD) -> Result<Self, ()> {
84 assert!((1..=3).contains(&op));
85 // See the comment block above for why this is safe.
86 unsafe { mem::transmute(op) }
87 }
88}
89impl From<PipeDirection> for DWORD {
90 fn from(op: PipeDirection) -> Self {
91 unsafe { mem::transmute(op) }
92 }
93}
94/// Describes the role of a named pipe stream. In constrast to [`PipeDirection`], the meaning of values here is relative – for example, [`Reader`] means [`ServerToClient`] if you're creating a server and [`ClientToServer`] if you're creating a client.
95///
96/// This enumeration is also not layout-compatible with the `PIPE_ACCESS_*` constants, in contrast to [`PipeDirection`].
97///
98/// [`PipeDirection`]: enum.PipeDirection.html " "
99/// [`Reader`]: #variant.Reader " "
100/// [`ServerToClient`]: enum.PipeDirection.html#variant.ServerToClient " "
101/// [`ClientToServer`]: enum.PipeDirection.html#variant.ClientToServer " "
102#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
103#[repr(u32)]
104pub enum PipeStreamRole {
105 /// The stream only reads data.
106 Reader,
107 /// The stream only writes data.
108 Writer,
109 /// The stream both reads and writes data.
110 ReaderAndWriter,
111}
112impl PipeStreamRole {
113 /// Returns the data flow direction of the data stream, assuming that the value describes the role of the server.
114 ///
115 /// # Usage
116 /// ```
117 /// # #[cfg(windows)] {
118 /// # use interprocess::os::windows::named_pipe::{PipeDirection, PipeStreamRole};
119 /// assert_eq!(
120 /// PipeStreamRole::Reader.direction_as_server(),
121 /// PipeDirection::ClientToServer,
122 /// );
123 /// assert_eq!(
124 /// PipeStreamRole::Writer.direction_as_server(),
125 /// PipeDirection::ServerToClient,
126 /// );
127 /// assert_eq!(
128 /// PipeStreamRole::ReaderAndWriter.direction_as_server(),
129 /// PipeDirection::Duplex,
130 /// );
131 /// # }
132 /// ```
133 pub const fn direction_as_server(self) -> PipeDirection {
134 match self {
135 Self::Reader => PipeDirection::ClientToServer,
136 Self::Writer => PipeDirection::ServerToClient,
137 Self::ReaderAndWriter => PipeDirection::Duplex,
138 }
139 }
140 /// Returns the data flow direction of the data stream, assuming that the value describes the role of the client.
141 ///
142 /// # Usage
143 /// ```
144 /// # #[cfg(windows)] {
145 /// # use interprocess::os::windows::named_pipe::{PipeDirection, PipeStreamRole};
146 /// assert_eq!(
147 /// PipeStreamRole::Reader.direction_as_client(),
148 /// PipeDirection::ServerToClient,
149 /// );
150 /// assert_eq!(
151 /// PipeStreamRole::Writer.direction_as_client(),
152 /// PipeDirection::ClientToServer,
153 /// );
154 /// assert_eq!(
155 /// PipeStreamRole::ReaderAndWriter.direction_as_client(),
156 /// PipeDirection::Duplex,
157 /// );
158 /// # }
159 /// ```
160 pub const fn direction_as_client(self) -> PipeDirection {
161 match self {
162 Self::Reader => PipeDirection::ServerToClient,
163 Self::Writer => PipeDirection::ClientToServer,
164 Self::ReaderAndWriter => PipeDirection::Duplex,
165 }
166 }
167}
168
169/// Specifies the mode for a pipe stream.
170#[repr(u32)]
171#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
172pub enum PipeMode {
173 /// Designates that the pipe stream works in byte stream mode, erasing the boundaries of separate messages.
174 Bytes = PIPE_TYPE_BYTE,
175 /// Designates that the pipe stream works in message stream mode, preserving the boundaries of separate messages yet still allowing to read them in byte stream mode.
176 Messages = PIPE_TYPE_MESSAGE,
177}
178impl PipeMode {
179 /// Converts the value into a raw `DWORD`-typed constant, either `PIPE_TYPE_BYTE` or `PIPE_TYPE_MESSAGE` depending on the value.
180 pub const fn to_pipe_type(self) -> DWORD {
181 self as _
182 }
183 /// Converts the value into a raw `DWORD`-typed constant, either `PIPE_READMODE_BYTE` or `PIPE_READMODE_MESSAGE` depending on the value.
184 pub const fn to_readmode(self) -> DWORD {
185 match self {
186 Self::Bytes => PIPE_READMODE_BYTE,
187 Self::Messages => PIPE_READMODE_MESSAGE,
188 }
189 }
190}
191impl TryFrom<DWORD> for PipeMode {
192 type Error = ();
193 /// Converts a Windows constant to a `PipeMode` if it's in range. Both `PIPE_TYPE_*` and `PIPE_READMODE_*` are supported.
194 ///
195 /// # Errors
196 /// Returns `Err` if the value is not a valid pipe stream mode constant.
197 fn try_from(op: DWORD) -> Result<Self, ()> {
198 // It's nicer to only match than to check and transmute
199 #[allow(unreachable_patterns)] // PIPE_READMODE_BYTE and PIPE_TYPE_BYTE are equal
200 match op {
201 PIPE_TYPE_BYTE | PIPE_READMODE_BYTE => Ok(Self::Bytes),
202 PIPE_READMODE_MESSAGE | PIPE_TYPE_MESSAGE => Ok(Self::Messages),
203 _ => Err(()),
204 }
205 }
206}