sized_dst/
trait_impls.rs

1use core::{
2    borrow::{Borrow, BorrowMut},
3    cmp::Ordering,
4    error::Error,
5    fmt::{Binary, Debug, Display, LowerExp, LowerHex, Octal, Pointer, UpperExp, UpperHex},
6    future::Future,
7    hash::{Hash, Hasher},
8    iter::FusedIterator,
9    ops::{
10        AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, Deref, DerefMut, DivAssign, Index,
11        IndexMut, MulAssign, RemAssign, ShlAssign, ShrAssign, SubAssign,
12    },
13    pin::Pin,
14};
15#[cfg(feature = "std")]
16use std::{
17    io::{BufRead, Read, Seek, Write},
18    os::fd::{AsFd, AsRawFd},
19};
20
21use aligned::Alignment;
22
23use crate::DstBase;
24
25macro_rules! impl_fmt_trait {
26    ($trait:ident) => {
27        impl<D: ?Sized + $trait, A: Alignment, const N: usize> $trait for DstBase<D, A, N> {
28            fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
29                self.deref().fmt(f)
30            }
31        }
32    };
33}
34
35impl_fmt_trait!(Debug);
36impl_fmt_trait!(Display);
37impl_fmt_trait!(Binary);
38impl_fmt_trait!(Octal);
39impl_fmt_trait!(LowerHex);
40impl_fmt_trait!(UpperHex);
41impl_fmt_trait!(LowerExp);
42impl_fmt_trait!(UpperExp);
43impl_fmt_trait!(Pointer);
44
45impl<D: ?Sized + core::fmt::Write, A: Alignment, const N: usize> core::fmt::Write
46    for DstBase<D, A, N>
47{
48    fn write_str(&mut self, s: &str) -> core::fmt::Result {
49        self.deref_mut().write_str(s)
50    }
51    fn write_char(&mut self, c: char) -> core::fmt::Result {
52        self.deref_mut().write_char(c)
53    }
54    fn write_fmt(&mut self, args: core::fmt::Arguments<'_>) -> core::fmt::Result {
55        self.deref_mut().write_fmt(args)
56    }
57}
58
59impl<T: ?Sized, D: ?Sized + AsRef<T>, A: Alignment, const N: usize> AsRef<T> for DstBase<D, A, N> {
60    fn as_ref(&self) -> &T {
61        self.deref().as_ref()
62    }
63}
64
65impl<T: ?Sized, D: ?Sized + AsMut<T>, A: Alignment, const N: usize> AsMut<T> for DstBase<D, A, N> {
66    fn as_mut(&mut self) -> &mut T {
67        self.deref_mut().as_mut()
68    }
69}
70
71impl<D: ?Sized, A: Alignment, const N: usize> Borrow<D> for DstBase<D, A, N> {
72    fn borrow(&self) -> &D {
73        self.deref()
74    }
75}
76
77impl<D: ?Sized, A: Alignment, const N: usize> BorrowMut<D> for DstBase<D, A, N> {
78    fn borrow_mut(&mut self) -> &mut D {
79        self.deref_mut()
80    }
81}
82
83impl<Idx, D: ?Sized + Index<Idx>, A: Alignment, const N: usize> Index<Idx> for DstBase<D, A, N> {
84    type Output = D::Output;
85    fn index(&self, index: Idx) -> &<Self as Index<Idx>>::Output {
86        self.deref().index(index)
87    }
88}
89
90impl<Idx, D: ?Sized + IndexMut<Idx>, A: Alignment, const N: usize> IndexMut<Idx>
91    for DstBase<D, A, N>
92{
93    fn index_mut(&mut self, index: Idx) -> &mut Self::Output {
94        self.deref_mut().index_mut(index)
95    }
96}
97
98macro_rules! impl_assign_trait {
99    ($trait:ident, $method:ident) => {
100        impl<Rhs, D: ?Sized + $trait<Rhs>, A: Alignment, const N: usize> $trait<Rhs>
101            for DstBase<D, A, N>
102        {
103            fn $method(&mut self, rhs: Rhs) {
104                self.deref_mut().$method(rhs)
105            }
106        }
107    };
108}
109
110impl_assign_trait!(AddAssign, add_assign);
111impl_assign_trait!(SubAssign, sub_assign);
112impl_assign_trait!(BitOrAssign, bitor_assign);
113impl_assign_trait!(BitAndAssign, bitand_assign);
114impl_assign_trait!(BitXorAssign, bitxor_assign);
115impl_assign_trait!(MulAssign, mul_assign);
116impl_assign_trait!(DivAssign, div_assign);
117impl_assign_trait!(RemAssign, rem_assign);
118impl_assign_trait!(ShrAssign, shr_assign);
119impl_assign_trait!(ShlAssign, shl_assign);
120
121impl<D: ?Sized + Iterator, A: Alignment, const N: usize> Iterator for DstBase<D, A, N> {
122    type Item = D::Item;
123    fn next(&mut self) -> Option<Self::Item> {
124        self.deref_mut().next()
125    }
126    fn size_hint(&self) -> (usize, Option<usize>) {
127        self.deref().size_hint()
128    }
129    fn nth(&mut self, n: usize) -> Option<Self::Item> {
130        self.deref_mut().nth(n)
131    }
132}
133
134impl<D: ?Sized + DoubleEndedIterator, A: Alignment, const N: usize> DoubleEndedIterator
135    for DstBase<D, A, N>
136{
137    fn next_back(&mut self) -> Option<Self::Item> {
138        self.deref_mut().next_back()
139    }
140    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
141        self.deref_mut().nth_back(n)
142    }
143}
144
145impl<D: ?Sized + ExactSizeIterator, A: Alignment, const N: usize> ExactSizeIterator
146    for DstBase<D, A, N>
147{
148    fn len(&self) -> usize {
149        self.deref().len()
150    }
151}
152
153impl<D: ?Sized + FusedIterator, A: Alignment, const N: usize> FusedIterator for DstBase<D, A, N> {}
154
155macro_rules! cmp_method {
156    ($method:ident -> $ret:ty) => {
157        fn $method(&self, other: &Self) -> $ret {
158            self.deref().$method(other)
159        }
160    };
161}
162
163impl<D: ?Sized + PartialEq, A: Alignment, const N: usize> PartialEq for DstBase<D, A, N> {
164    cmp_method!(eq -> bool);
165}
166
167impl<D: ?Sized + PartialOrd, A: Alignment, const N: usize> PartialOrd for DstBase<D, A, N> {
168    cmp_method!(partial_cmp -> Option<Ordering>);
169    cmp_method!(lt -> bool);
170    cmp_method!(le -> bool);
171    cmp_method!(gt -> bool);
172    cmp_method!(ge -> bool);
173}
174
175impl<D: ?Sized + Eq, A: Alignment, const N: usize> Eq for DstBase<D, A, N> {}
176
177impl<D: ?Sized + Ord, A: Alignment, const N: usize> Ord for DstBase<D, A, N> {
178    cmp_method!(cmp -> Ordering);
179}
180
181impl<D: ?Sized + Hasher, A: Alignment, const N: usize> Hasher for DstBase<D, A, N> {
182    fn finish(&self) -> u64 {
183        self.deref().finish()
184    }
185    fn write(&mut self, bytes: &[u8]) {
186        self.deref_mut().write(bytes)
187    }
188    fn write_u8(&mut self, i: u8) {
189        self.deref_mut().write_u8(i)
190    }
191    fn write_u16(&mut self, i: u16) {
192        self.deref_mut().write_u16(i)
193    }
194    fn write_u32(&mut self, i: u32) {
195        self.deref_mut().write_u32(i)
196    }
197    fn write_u64(&mut self, i: u64) {
198        self.deref_mut().write_u64(i)
199    }
200    fn write_u128(&mut self, i: u128) {
201        self.deref_mut().write_u128(i)
202    }
203    fn write_usize(&mut self, i: usize) {
204        self.deref_mut().write_usize(i)
205    }
206    fn write_i8(&mut self, i: i8) {
207        self.deref_mut().write_i8(i)
208    }
209    fn write_i16(&mut self, i: i16) {
210        self.deref_mut().write_i16(i)
211    }
212    fn write_i32(&mut self, i: i32) {
213        self.deref_mut().write_i32(i)
214    }
215    fn write_i64(&mut self, i: i64) {
216        self.deref_mut().write_i64(i)
217    }
218    fn write_i128(&mut self, i: i128) {
219        self.deref_mut().write_i128(i)
220    }
221    fn write_isize(&mut self, i: isize) {
222        self.deref_mut().write_isize(i)
223    }
224}
225
226impl<D: ?Sized + Hash, A: Alignment, const N: usize> Hash for DstBase<D, A, N> {
227    fn hash<H: Hasher>(&self, state: &mut H) {
228        self.deref().hash(state)
229    }
230}
231
232impl<D: ?Sized + Future, A: Alignment, const N: usize> Future for DstBase<D, A, N> {
233    type Output = D::Output;
234    fn poll(
235        self: Pin<&mut Self>,
236        cx: &mut core::task::Context<'_>,
237    ) -> core::task::Poll<Self::Output> {
238        // SAFETY:
239        // This is basically a pin projection into Pin<&mut D>, so the pin projection rules apply
240        // - DstBase is Unpin only if D is Unpin, because it has a PhantomData<D> field.
241        // - The destructor of DstBase only calls drop_in_place on the D pointer. D's
242        //   destructor can only move D if it implements Unpin, which also means DstBase is
243        //   Unpin. Thus, DstBase's destructor can only move its D field if DstBase is Unpin.
244        // - The only way to get a mutable reference to D is via deref_mut, which can't be called
245        //   while DstBase is pinned, so it's impossible to re-use the memory used for the D
246        //   with safe code after DstBase has been pinned.
247        // - Likewise, since there's no way to obtain a mutable D reference while DstBase is
248        //   pinned, data can't be moved out of the D after it's pinned.
249        unsafe { self.map_unchecked_mut(|p| &mut **p).poll(cx) }
250    }
251}
252
253impl<D: ?Sized + Error, A: Alignment, const N: usize> Error for DstBase<D, A, N> {
254    fn source(&self) -> Option<&(dyn Error + 'static)> {
255        self.deref().source()
256    }
257}
258
259#[cfg(feature = "std")]
260impl<D: ?Sized + Read, A: Alignment, const N: usize> Read for DstBase<D, A, N> {
261    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
262        self.deref_mut().read(buf)
263    }
264    fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> std::io::Result<usize> {
265        self.deref_mut().read_vectored(bufs)
266    }
267    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
268        self.deref_mut().read_to_end(buf)
269    }
270    fn read_to_string(&mut self, buf: &mut String) -> std::io::Result<usize> {
271        self.deref_mut().read_to_string(buf)
272    }
273    fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
274        self.deref_mut().read_exact(buf)
275    }
276}
277
278#[cfg(feature = "std")]
279impl<D: ?Sized + Write, A: Alignment, const N: usize> Write for DstBase<D, A, N> {
280    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
281        self.deref_mut().write(buf)
282    }
283    fn flush(&mut self) -> std::io::Result<()> {
284        self.deref_mut().flush()
285    }
286    fn write_vectored(&mut self, bufs: &[std::io::IoSlice<'_>]) -> std::io::Result<usize> {
287        self.deref_mut().write_vectored(bufs)
288    }
289    fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
290        self.deref_mut().write_all(buf)
291    }
292    fn write_fmt(&mut self, fmt: std::fmt::Arguments<'_>) -> std::io::Result<()> {
293        self.deref_mut().write_fmt(fmt)
294    }
295}
296
297#[cfg(feature = "std")]
298impl<D: ?Sized + BufRead, A: Alignment, const N: usize> BufRead for DstBase<D, A, N> {
299    fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
300        self.deref_mut().fill_buf()
301    }
302    fn consume(&mut self, amt: usize) {
303        self.deref_mut().consume(amt)
304    }
305    fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> std::io::Result<usize> {
306        self.deref_mut().read_until(byte, buf)
307    }
308    fn read_line(&mut self, buf: &mut String) -> std::io::Result<usize> {
309        self.deref_mut().read_line(buf)
310    }
311}
312
313#[cfg(feature = "std")]
314impl<D: ?Sized + Seek, A: Alignment, const N: usize> Seek for DstBase<D, A, N> {
315    fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
316        self.deref_mut().seek(pos)
317    }
318    fn rewind(&mut self) -> std::io::Result<()> {
319        self.deref_mut().rewind()
320    }
321    fn stream_position(&mut self) -> std::io::Result<u64> {
322        self.deref_mut().stream_position()
323    }
324    fn seek_relative(&mut self, offset: i64) -> std::io::Result<()> {
325        self.deref_mut().seek_relative(offset)
326    }
327}
328
329#[cfg(feature = "std")]
330impl<D: ?Sized + AsFd, A: Alignment, const N: usize> AsFd for DstBase<D, A, N> {
331    fn as_fd(&self) -> std::os::unix::prelude::BorrowedFd<'_> {
332        self.deref().as_fd()
333    }
334}
335
336#[cfg(feature = "std")]
337impl<D: ?Sized + AsRawFd, A: Alignment, const N: usize> AsRawFd for DstBase<D, A, N> {
338    fn as_raw_fd(&self) -> std::os::unix::prelude::RawFd {
339        self.deref().as_raw_fd()
340    }
341}
342
343#[cfg(test)]
344mod tests {
345    use static_assertions::{assert_impl_all, assert_not_impl_any};
346
347    use super::*;
348    use crate::*;
349
350    // Ensure Send and Sync propagate properly
351    assert_not_impl_any!(DstA8::<dyn ToString, 8>: Send, Sync);
352    assert_impl_all!(DstA8::<dyn ToString + Send, 8>: Send);
353    assert_not_impl_any!(DstA8::<dyn ToString + Send, 8>: Sync);
354    assert_impl_all!(DstA8::<dyn ToString + Send + Sync, 8>: Send, Sync);
355
356    // Ensure Unpin is only implemented if D is Unpin
357    assert_not_impl_any!(Dst<dyn Future<Output = i32>, 12>: Unpin);
358    assert_impl_all!(Dst<dyn Future<Output = i32>, 12>: Future<Output = i32>);
359    assert_impl_all!(Dst<dyn Future<Output = i32> + Unpin, 12>: Unpin, Future<Output = i32>);
360
361    #[test]
362    fn future() {
363        let fut = async { 5 };
364        let dst = Dst::<dyn Future<Output = i32>, 12>::new(fut);
365
366        let n = futures_executor::block_on(dst);
367        assert_eq!(n, 5);
368    }
369
370    assert_impl_all!(Dst<dyn AsRef<[u8]>, 12>: AsRef<[u8]>, BorrowMut<dyn AsRef<[u8]>>);
371    assert_impl_all!(Dst<dyn AsMut<[u8]>, 12>: AsMut<[u8]>, BorrowMut<dyn AsMut<[u8]>>);
372
373    #[test]
374    fn as_ref() {
375        let dst = Dst::<dyn AsRef<[u8]>, 32>::new(String::from("xyz"));
376        assert_eq!(dst.as_ref(), b"xyz");
377    }
378
379    #[test]
380    fn as_mut() {
381        let mut dst = Dst::<dyn AsMut<[u32]>, 32>::new(vec![0, 1, 2]);
382        assert_eq!(dst.as_mut(), &[0, 1, 2]);
383        dst.as_mut()[0] = 3;
384        assert_eq!(dst.as_mut(), &[3, 1, 2]);
385    }
386
387    assert_impl_all!(Dst<dyn IndexMut<usize, Output = u8>, 32>: IndexMut<usize>, Index<usize>);
388
389    #[test]
390    fn index() {
391        let mut dst = Dst::<dyn IndexMut<usize, Output = u8>, 32>::new(vec![0, 3]);
392        assert_eq!(dst[0], 0);
393        assert_eq!(dst[1], 3);
394        dst[0] = 4;
395        assert_eq!(dst[0], 4);
396    }
397
398    assert_impl_all!(Dst<dyn DoubleEndedIterator<Item = u8>, 32>: DoubleEndedIterator, Iterator);
399    assert_impl_all!(Dst<dyn FusedIterator<Item = u8>, 32>: FusedIterator, Iterator);
400    assert_impl_all!(Dst<dyn ExactSizeIterator<Item = u8>, 32>: ExactSizeIterator, Iterator);
401
402    #[test]
403    fn iterator() {
404        let mut dst =
405            Dst::<dyn DoubleEndedIterator<Item = u8>, 32>::new([2, 3, 4, 5, 6].into_iter());
406        assert_eq!(dst.next(), Some(2));
407        assert_eq!(dst.nth(1), Some(4));
408        assert_eq!(dst.next_back(), Some(6));
409        assert_eq!(dst.nth_back(0), Some(5));
410        assert_eq!(dst.next(), None);
411    }
412}