channels_io/transaction/
write_kind.rs

1use core::pin::Pin;
2use core::task::{Context, Poll};
3
4use alloc::vec::Vec;
5
6use pin_project::pin_project;
7
8use crate::transaction::{
9	AsyncWriteTransaction, Buffered, Unbuffered, WriteTransaction,
10};
11use crate::{AsyncWrite, Write};
12
13/// Kind of the transaction.
14#[derive(Debug)]
15pub enum WriteTransactionKind<'a> {
16	/// A [`Buffered`] transaction.
17	Buffered(&'a mut Vec<u8>),
18	/// An [`Unbuffered`] transaction.
19	Unbuffered,
20}
21
22/// A unified interface for calling code to choose which transaction kind it wants
23/// at runtime.
24#[derive(Debug)]
25#[pin_project(project = WriteTransactionVariantProj)]
26pub enum WriteTransactionVariant<'a, W> {
27	/// A [`Buffered`] transaction.
28	Buffered(#[pin] Buffered<'a, W>),
29	/// An [`Unbuffered`] transaction.
30	Unbuffered(#[pin] Unbuffered<W>),
31}
32
33impl<'a, W> WriteTransactionVariant<'a, W> {
34	/// Create a [`Buffered`] transaction.
35	pub fn buffered(writer: W, buf: &'a mut Vec<u8>) -> Self {
36		Self::Buffered(Buffered::new(writer, buf))
37	}
38
39	/// Create an [`Unbuffered`] transaction.
40	pub fn unbuffered(writer: W) -> Self {
41		Self::Unbuffered(Unbuffered::new(writer))
42	}
43
44	/// Create a new transaction based on `kind`.
45	pub fn new(writer: W, kind: WriteTransactionKind<'a>) -> Self {
46		match kind {
47			WriteTransactionKind::Buffered(buf) => {
48				Self::buffered(writer, buf)
49			},
50			WriteTransactionKind::Unbuffered => {
51				Self::unbuffered(writer)
52			},
53		}
54	}
55
56	/// Get a reference to the underlying writer.
57	#[must_use]
58	pub fn writer(&self) -> &W {
59		match self {
60			Self::Buffered(x) => x.writer(),
61			Self::Unbuffered(x) => x.writer(),
62		}
63	}
64
65	/// Get a mutable reference to the underlying writer.
66	#[must_use]
67	pub fn writer_mut(&mut self) -> &mut W {
68		match self {
69			Self::Buffered(x) => x.writer_mut(),
70			Self::Unbuffered(x) => x.writer_mut(),
71		}
72	}
73
74	/// Get a pinned mutable reference to the underlying writer.
75	#[must_use]
76	pub fn writer_pin_mut(self: Pin<&mut Self>) -> Pin<&mut W> {
77		match self.project() {
78			WriteTransactionVariantProj::Buffered(x) => {
79				x.writer_pin_mut()
80			},
81			WriteTransactionVariantProj::Unbuffered(x) => {
82				x.writer_pin_mut()
83			},
84		}
85	}
86}
87
88impl<'a, W> Write for WriteTransactionVariant<'a, W>
89where
90	W: Write,
91{
92	type Error = W::Error;
93
94	fn write_slice(
95		&mut self,
96		buf: &[u8],
97	) -> Result<usize, Self::Error> {
98		match self {
99			Self::Buffered(x) => x.write_slice(buf),
100			Self::Unbuffered(x) => x.write_slice(buf),
101		}
102	}
103
104	fn flush_once(&mut self) -> Result<(), Self::Error> {
105		match self {
106			Self::Buffered(x) => x.flush_once(),
107			Self::Unbuffered(x) => x.flush_once(),
108		}
109	}
110}
111
112impl<'a, W> WriteTransaction for WriteTransactionVariant<'a, W>
113where
114	W: Write,
115{
116	fn finish(self) -> Result<(), Self::Error> {
117		match self {
118			Self::Buffered(x) => x.finish(),
119			Self::Unbuffered(x) => x.finish(),
120		}
121	}
122}
123
124impl<'a, W> AsyncWrite for WriteTransactionVariant<'a, W>
125where
126	W: AsyncWrite,
127{
128	type Error = W::Error;
129
130	fn poll_write_slice(
131		self: Pin<&mut Self>,
132		cx: &mut Context,
133		buf: &[u8],
134	) -> Poll<Result<usize, Self::Error>> {
135		match self.project() {
136			WriteTransactionVariantProj::Buffered(x) => {
137				x.poll_write_slice(cx, buf)
138			},
139			WriteTransactionVariantProj::Unbuffered(x) => {
140				x.poll_write_slice(cx, buf)
141			},
142		}
143	}
144
145	fn poll_flush_once(
146		self: Pin<&mut Self>,
147		cx: &mut Context,
148	) -> Poll<Result<(), Self::Error>> {
149		match self.project() {
150			WriteTransactionVariantProj::Buffered(x) => {
151				x.poll_flush_once(cx)
152			},
153			WriteTransactionVariantProj::Unbuffered(x) => {
154				x.poll_flush_once(cx)
155			},
156		}
157	}
158}
159
160impl<'a, W> AsyncWriteTransaction for WriteTransactionVariant<'a, W>
161where
162	W: AsyncWrite,
163{
164	fn poll_finish(
165		self: Pin<&mut Self>,
166		cx: &mut Context,
167	) -> Poll<Result<(), Self::Error>> {
168		match self.project() {
169			WriteTransactionVariantProj::Buffered(x) => {
170				x.poll_finish(cx)
171			},
172			WriteTransactionVariantProj::Unbuffered(x) => {
173				x.poll_finish(cx)
174			},
175		}
176	}
177}