1#[must_use = "a chain takes ownership of itself, performs the action, then returns itself again"]
2pub struct Chain<T> {
3 inner: T
4}
5
6impl<T> Chain<T> {
7 #[inline]
8 pub const fn from_inner(inner: T) -> Self {
9 Self { inner }
10 }
11
12 #[inline]
13 pub fn into_inner(self) -> T {
14 self.inner
15 }
16
17 #[inline]
18 pub const fn as_inner(&self) -> &T {
19 &self.inner
20 }
21
22 #[inline]
23 pub const fn as_inner_mut(&mut self) -> &mut T {
24 &mut self.inner
25 }
26
27 #[inline]
28 pub const fn as_inner_chain(&self) -> Chain<&T> {
29 Chain::from_inner(self.as_inner())
30 }
31
32 #[inline]
33 pub const fn as_inner_mut_chain(&mut self) -> Chain<&mut T> {
34 Chain::from_inner(self.as_inner_mut())
35 }
36
37 #[inline]
38 pub fn with_inner<F>(self, f: F) -> Self
39 where
40 F: FnOnce(&T)
41 {
42 f(self.as_inner());
43 self
44 }
45
46 #[inline]
47 pub fn with_inner_mut<F>(mut self, f: F) -> Self
48 where
49 F: FnOnce(&mut T)
50 {
51 f(self.as_inner_mut());
52 self
53 }
54}
55
56pub trait ChainInner: Sized {
57 #[inline]
58 fn from_chain(chain: Chain<Self>) -> Self {
59 chain.into_inner()
60 }
61
62 #[inline]
63 fn into_chain(self) -> Chain<Self> {
64 Chain::from_inner(self)
65 }
66}
67
68impl<T> ChainInner for T {}
69
70pub(crate) trait ChainInnerType {
71 type Inner;
72}
73
74impl<T> ChainInnerType for Chain<T> {
75 type Inner = T;
76}
77
78pub unsafe trait Output<T>: Sized + private::Sealed<T> {
88 fn write(self, item: T);
90}
91
92unsafe impl<T> Output<T> for &mut T {
94 #[expect(
95 clippy::inline_always,
96 reason = "same as MaybeUninit::write"
97 )]
98 #[inline(always)]
99 fn write(self, item: T) {
100 *self = item;
101 }
102}
103impl<T> private::Sealed<T> for &mut T {}
104
105unsafe impl<T> Output<T> for &mut Option<T> {
107 #[expect(
108 clippy::inline_always,
109 reason = "same as MaybeUninit::write"
110 )]
111 #[inline(always)]
112 fn write(self, item: T) {
113 *self = Some(item);
114 }
115}
116impl<T> private::Sealed<T> for &mut Option<T> {}
117
118unsafe impl<T> Output<T> for &mut core::mem::MaybeUninit<T> {
120 #[expect(
121 clippy::inline_always,
122 reason = "same as MaybeUninit::write"
123 )]
124 #[inline(always)]
125 fn write(self, item: T) {
126 self.write(item);
127 }
128}
129impl<T> private::Sealed<T> for &mut core::mem::MaybeUninit<T> {}
130
131#[expect(
136 clippy::inline_always,
137 reason = "should be no-op"
138)]
139#[inline(always)]
140pub fn out_dbg<T>(out: impl Output<T>) -> impl Output<T> {
141 #[cfg(debug_assertions)]
142 let out = OutputDebug {
143 inner: out,
144 __marker: std::marker::PhantomData
145 };
146
147 out
148}
149
150#[cfg(debug_assertions)]
151#[repr(transparent)]
152struct OutputDebug<T, O>
153where
154 O: Output<T>
155{
156 inner: O,
157 __marker: core::marker::PhantomData<fn(T)>
158}
159
160#[cfg(debug_assertions)]
162unsafe impl<T, O> Output<T> for OutputDebug<T, O>
163where
164 O: Output<T>
165{
166 #[inline]
167 fn write(self, item: T) {
168 let this = core::mem::ManuallyDrop::new(self);
169
170 let inner = unsafe { core::ptr::read(&raw const this.inner) };
172
173 inner.write(item);
174 }
175}
176
177#[cfg(debug_assertions)]
178impl<T, O> private::Sealed<T> for OutputDebug<T, O>
179where
180 O: Output<T>
181{}
182
183#[cfg(debug_assertions)]
184impl<T, O> Drop for OutputDebug<T, O>
185where
186 O: Output<T>
187{
188 #[inline]
189 fn drop(&mut self) {
190 panic!("`write` not called on created instance of `Output` (this is a bug)")
192 }
193}
194
195mod private {
196 pub trait Sealed<T> {}
197}