Skip to main content

circular_buffer/
cmp.rs

1// Copyright © 2023-2026 Andrea Corbellini and contributors
2// SPDX-License-Identifier: BSD-3-Clause
3
4//! Implementations of [`PartialEq`], [`Eq`], [`PartialOrd`], [`Ord`].
5
6use crate::CircularBuffer;
7use crate::FixedCircularBuffer;
8use core::cmp::Ordering;
9use core::convert::identity;
10use core::ops::Deref;
11
12#[cfg(feature = "alloc")]
13use crate::HeapCircularBuffer;
14
15#[cfg(all(not(feature = "std"), feature = "alloc"))]
16use alloc::boxed::Box;
17
18impl<T> Eq for CircularBuffer<T> where T: Eq {}
19
20impl<T, const N: usize> Eq for FixedCircularBuffer<T, N> where T: Eq {}
21
22#[cfg(feature = "alloc")]
23impl<T> Eq for HeapCircularBuffer<T> where T: Eq {}
24
25impl<T, U> PartialEq<CircularBuffer<U>> for CircularBuffer<T>
26where
27    T: PartialEq<U>,
28{
29    fn eq(&self, other: &CircularBuffer<U>) -> bool {
30        if self.len() != other.len() {
31            return false;
32        }
33
34        let (a_left, a_right) = self.as_slices();
35        let (b_left, b_right) = other.as_slices();
36
37        match a_left.len().cmp(&b_left.len()) {
38            Ordering::Less => {
39                let x = a_left.len();
40                let y = b_left.len() - x;
41                a_left[..] == b_left[..x]
42                    && a_right[..y] == b_left[x..]
43                    && a_right[y..] == b_right[..]
44            }
45            Ordering::Greater => {
46                let x = b_left.len();
47                let y = a_left.len() - x;
48                a_left[..x] == b_left[..]
49                    && a_left[x..] == b_right[..y]
50                    && a_right[..] == b_right[y..]
51            }
52            Ordering::Equal => {
53                debug_assert_eq!(a_left.len(), b_left.len());
54                debug_assert_eq!(a_right.len(), b_right.len());
55                a_left == b_left && a_right == b_right
56            }
57        }
58    }
59}
60
61impl<T, U> PartialEq<[U]> for CircularBuffer<T>
62where
63    T: PartialEq<U>,
64{
65    fn eq(&self, other: &[U]) -> bool {
66        if self.len() != other.len() {
67            return false;
68        }
69
70        let (a_left, a_right) = self.as_slices();
71        let (b_left, b_right) = other.split_at(a_left.len());
72
73        debug_assert_eq!(a_left.len(), b_left.len());
74        debug_assert_eq!(a_right.len(), b_right.len());
75        a_left == b_left && a_right == b_right
76    }
77}
78
79impl<T, U> PartialEq<CircularBuffer<U>> for [T]
80where
81    T: PartialEq<U>,
82{
83    #[inline]
84    fn eq(&self, other: &CircularBuffer<U>) -> bool {
85        if self.len() != other.len() {
86            return false;
87        }
88
89        let (a_left, a_right) = other.as_slices();
90        let (b_left, b_right) = self.split_at(a_left.len());
91
92        debug_assert_eq!(a_left.len(), b_left.len());
93        debug_assert_eq!(a_right.len(), b_right.len());
94        b_left == a_left && b_right == a_right
95    }
96}
97
98macro_rules! impl_partial_eq {
99    ( [ $( $generics:tt )* ] $lhs:ty [ $l_transform:path ] , $rhs:ty [ $r_transform:path ] ) => {
100        impl<T, U, $($generics)*> PartialEq<$rhs> for $lhs
101        where
102            T: PartialEq<U>,
103        {
104            #[inline]
105            fn eq(&self, other: &$rhs) -> bool {
106                $l_transform(self) == $r_transform(other)
107            }
108        }
109    };
110}
111
112macro_rules! impl_partial_eq_with_refs {
113    ( [ $( $generics:tt )* ] $lhs:ty [ $l_transform:path ] , $rhs:ty [ $r_transform:path ] ) => {
114        impl_partial_eq!([$($generics)*] $lhs [$l_transform], $rhs [$r_transform]);
115        impl_partial_eq!([$($generics)*] $lhs [$l_transform], &'_ $rhs [$r_transform]);
116        impl_partial_eq!([$($generics)*] $lhs [$l_transform], &'_ mut $rhs [$r_transform]);
117        impl_partial_eq!([$($generics)*] &'_ $lhs [$l_transform], $rhs [$r_transform]);
118        impl_partial_eq!([$($generics)*] &'_ mut $lhs [$l_transform], $rhs [$r_transform]);
119    };
120}
121
122// CircularBuffer <=> CircularBuffer
123impl_partial_eq!([] CircularBuffer<T> [identity], &'_ CircularBuffer<U> [Deref::deref]);
124impl_partial_eq!([] CircularBuffer<T> [identity], &'_ mut CircularBuffer<U> [Deref::deref]);
125impl_partial_eq!([] &'_ CircularBuffer<T> [Deref::deref], CircularBuffer<U> [identity]);
126impl_partial_eq!([] &'_ mut CircularBuffer<T> [Deref::deref], CircularBuffer<U> [identity]);
127
128// CircularBuffer <=> slice
129impl_partial_eq!([] CircularBuffer<T> [identity], &'_ [U] [Deref::deref]);
130impl_partial_eq!([] CircularBuffer<T> [identity], &'_ mut [U] [Deref::deref]);
131impl_partial_eq!([] &'_ CircularBuffer<T> [Deref::deref], [U] [identity]);
132impl_partial_eq!([] &'_ mut CircularBuffer<T> [Deref::deref], [U] [identity]);
133
134// CircularBuffer <=> array
135impl_partial_eq_with_refs!([const M: usize] CircularBuffer<T> [identity], [U; M] [AsRef::as_ref]);
136
137// CircularBuffer <=> FixedCircularBuffer
138impl_partial_eq_with_refs!([const M: usize] CircularBuffer<T> [identity], FixedCircularBuffer<U, M> [Deref::deref]);
139impl_partial_eq_with_refs!([const N: usize] FixedCircularBuffer<T, N> [Deref::deref], CircularBuffer<U> [identity]);
140
141// CircularBuffer <=> HeapCircularBuffer
142#[cfg(feature = "alloc")]
143impl_partial_eq_with_refs!([] CircularBuffer<T> [identity], HeapCircularBuffer<U> [Deref::deref]);
144#[cfg(feature = "alloc")]
145impl_partial_eq_with_refs!([] HeapCircularBuffer<T> [Deref::deref], CircularBuffer<U> [identity]);
146
147// FixedCircularBuffer <=> FixedCircularBuffer, slice, array
148impl_partial_eq_with_refs!([const N: usize, const M: usize] FixedCircularBuffer<T, N> [Deref::deref], FixedCircularBuffer<U, M> [Deref::deref]);
149impl_partial_eq_with_refs!([const N: usize] FixedCircularBuffer<T, N> [Deref::deref], [U] [identity]);
150impl_partial_eq_with_refs!([const N: usize, const M: usize] FixedCircularBuffer<T, N> [Deref::deref], [U; M] [AsRef::as_ref]);
151
152// HeapCircularBuffer <=> HeapCircularBuffer, slice, array
153#[cfg(feature = "alloc")]
154impl_partial_eq_with_refs!([] HeapCircularBuffer<T> [Deref::deref], HeapCircularBuffer<U> [Deref::deref]);
155#[cfg(feature = "alloc")]
156impl_partial_eq_with_refs!([] HeapCircularBuffer<T> [Deref::deref], [U] [identity]);
157#[cfg(feature = "alloc")]
158impl_partial_eq_with_refs!([const M: usize] HeapCircularBuffer<T> [Deref::deref], [U; M] [AsRef::as_ref]);
159
160// Box<CircularBuffer> <=> slice, array
161#[cfg(feature = "alloc")]
162impl_partial_eq_with_refs!([] Box<CircularBuffer<T>> [Deref::deref], [U] [identity]);
163#[cfg(feature = "alloc")]
164impl_partial_eq_with_refs!([const M: usize] Box<CircularBuffer<T>> [Deref::deref], [U; M] [AsRef::as_ref]);
165
166impl<T, U> PartialOrd<CircularBuffer<U>> for CircularBuffer<T>
167where
168    T: PartialOrd<U>,
169{
170    fn partial_cmp(&self, other: &CircularBuffer<U>) -> Option<Ordering> {
171        self.iter().partial_cmp(other.iter())
172    }
173}
174
175impl<T> Ord for CircularBuffer<T>
176where
177    T: Ord,
178{
179    fn cmp(&self, other: &Self) -> Ordering {
180        self.iter().cmp(other.iter())
181    }
182}
183
184impl<T, const N: usize, U, const M: usize> PartialOrd<FixedCircularBuffer<U, M>>
185    for FixedCircularBuffer<T, N>
186where
187    T: PartialOrd<U>,
188{
189    #[inline]
190    fn partial_cmp(&self, other: &FixedCircularBuffer<U, M>) -> Option<Ordering> {
191        self.deref().partial_cmp(other.deref())
192    }
193}
194
195impl<T, const N: usize> Ord for FixedCircularBuffer<T, N>
196where
197    T: Ord,
198{
199    #[inline]
200    fn cmp(&self, other: &Self) -> Ordering {
201        self.deref().cmp(other.deref())
202    }
203}
204
205#[cfg(feature = "alloc")]
206impl<T, U> PartialOrd<HeapCircularBuffer<U>> for HeapCircularBuffer<T>
207where
208    T: PartialOrd<U>,
209{
210    #[inline]
211    fn partial_cmp(&self, other: &HeapCircularBuffer<U>) -> Option<Ordering> {
212        self.deref().partial_cmp(other.deref())
213    }
214}
215
216#[cfg(feature = "alloc")]
217impl<T> Ord for HeapCircularBuffer<T>
218where
219    T: Ord,
220{
221    #[inline]
222    fn cmp(&self, other: &Self) -> Ordering {
223        self.deref().cmp(other.deref())
224    }
225}