lazyext_slice/
lib.rs

1//! Thousands of utility functions for slices and vec
2#![doc(html_root_url = "https://docs.rs/lazyext-slice/0.0.2")]
3#![deny(
4    missing_docs,
5    warnings,
6)]
7#![cfg_attr(docsrs, feature(doc_cfg))]
8#![cfg_attr(docsrs, allow(unused_attributes))]
9
10#[cfg(feature = "alloc")]
11extern crate alloc;
12
13#[macro_use]
14extern crate paste;
15
16macro_rules! cfg_alloc {
17    ($($item:item)*) => {
18        $(
19            #[cfg(feature = "alloc")]
20            #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
21            $item
22        )*
23    }
24}
25
26macro_rules! has_prefix {
27    ($trait:tt::$fn:tt) => {
28        /// Returns whether the slice self begins with prefix.
29        #[inline]
30        fn has_prefix(&self, prefix: impl $trait) -> bool {
31            let src = $trait::$fn(self);
32            let prefix = $trait::$fn(&prefix);
33            let pl = prefix.len();
34            if src.len() < pl {
35                return false;
36            }
37
38            src[0..pl].eq(prefix)
39        }
40    };
41}
42
43macro_rules! has_suffix {
44    ($trait:tt::$fn:tt) => {
45        /// Returns whether the slice self ends with suffix.
46        #[inline]
47        fn has_suffix(&self, suffix: impl $trait) -> bool {
48            let src = $trait::$fn(self);
49            let suffix = $trait::$fn(&suffix);
50            let pl = suffix.len() - 1;
51            if src.len() <= pl {
52                return false;
53            }
54
55            src[pl..].eq(suffix)
56        }
57    };
58}
59
60macro_rules! longest_prefix {
61    ($trait:tt::$fn:tt, $ty: ty) => {
62        /// Finds the longest shared prefix
63        #[inline]
64        fn longest_prefix(&self, other: impl $trait) -> &[$ty] {
65            let k1 = $trait::$fn(self);
66            let k2 = $trait::$fn(&other);
67            let max = k1.len().min(k2.len());
68
69            let mut n = max - 1;
70            for i in 0..max {
71                if k1[i].ne(&k2[i]) {
72                    n = i;
73                    break;
74                }
75            }
76            &k1[..n]
77        }
78    };
79}
80
81macro_rules! longest_suffix {
82    ($trait:tt::$fn:tt, $ty: ty) => {
83        /// Finds the longest shared suffix
84        #[inline]
85        fn longest_suffix(&self, other: impl $trait) -> &[$ty] {
86            let k1 = $trait::$fn(self);
87            let k1_len = k1.len();
88            let k2 = $trait::$fn(&other);
89            let k2_len = k2.len();
90            return if k1_len < k2_len {
91                let max = k1_len;
92                let mut n = max;
93                for i in 0..max {
94                    if k1[k1_len - i - 1].ne(&k2[k2_len - i - 1]) {
95                        n = i;
96                        break;
97                    }
98                }
99                &k1[max - n..]
100            } else {
101                let max = k2_len;
102                let mut n = max;
103                for i in 0..max {
104                    if k1[k1_len - i - 1].ne(&k2[k2_len - i - 1]) {
105                        n = i;
106                        break;
107                    }
108                }
109                &k1[k1_len - k2_len + max - n..]
110            };
111        }
112    }
113}
114
115#[cfg(feature = "alloc")]
116macro_rules! longest_prefix_lossy {
117    ($trait:tt::$fn:tt, $ty: ty, $ty_literal: literal) => {
118        #[doc = concat!("Finds the longest shared prefix, return a Cow<'_, [", $ty_literal, "]>.")]
119        #[inline]
120        fn longest_prefix_lossy(&self, other: impl $trait) -> Cow<'_, [$ty]> {
121            Cow::Borrowed(self.longest_prefix(other))
122        }
123    };
124}
125
126#[cfg(feature = "alloc")]
127macro_rules! longest_suffix_lossy {
128    ($trait:tt::$fn:tt, $ty: ty, $ty_literal: literal) => {
129        #[doc = concat!("Finds the longest shared suffix, return a Cow<'_, [", $ty_literal, "]>.")]
130        #[inline]
131        fn longest_suffix_lossy(&self, other: impl $trait) -> Cow<'_, [$ty]> {
132            Cow::Borrowed(self.longest_suffix(other))
133        }
134    };
135}
136
137macro_rules! impl_psfix_suites {
138    ($trait:tt::$fn:tt, $ty: ty, $ty_literal: literal) => {
139        has_prefix!($trait::$fn);
140
141        has_suffix!($trait::$fn);
142
143        longest_prefix!($trait::$fn, $ty);
144
145        longest_suffix!($trait::$fn, $ty);
146
147        cfg_alloc!{
148            longest_prefix_lossy!($trait::$fn, $ty, $ty_literal);
149            longest_suffix_lossy!($trait::$fn, $ty, $ty_literal);
150        }
151    };
152}
153
154mod bytes_ext;
155mod slice_ext;
156
157pub use bytes_ext::*;
158pub use slice_ext::*;