konst/slice/
slice_const_methods.rs

1macro_rules! slice_from_impl {
2    ($slice:ident, $start:ident, $as_ptr:ident, $from_raw_parts:ident, $on_overflow:expr) => {{
3        #[allow(unused_variables)]
4        let (rem, overflowed) = $slice.len().overflowing_sub($start);
5
6        if overflowed {
7            return $on_overflow;
8        }
9
10        #[cfg(feature = "rust_1_64")]
11        {
12            unsafe { crate::utils::$from_raw_parts($slice.$as_ptr().offset($start as _), rem) }
13        }
14        #[cfg(not(feature = "rust_1_64"))]
15        {
16            let mut ret = $slice;
17            let mut to_remove = $start;
18
19            slice_up_to_linear_time_impl! {
20                ret, to_remove, next,
21                () (next @ ..),
22            }
23            ret
24        }
25    }};
26}
27
28macro_rules! slice_up_to_impl {
29    ($slice:ident, $len:ident, $as_ptr:ident, $from_raw_parts:ident, $on_overflow:expr) => {{
30        #[allow(unused_variables)]
31        let (rem, overflowed) = $slice.len().overflowing_sub($len);
32
33        if overflowed {
34            return $on_overflow;
35        }
36
37        #[cfg(feature = "rust_1_64")]
38        {
39            // Doing this to get a slice up to length at compile-time
40            unsafe { crate::utils::$from_raw_parts($slice.$as_ptr(), $len) }
41        }
42        #[cfg(not(feature = "rust_1_64"))]
43        {
44            let mut ret = $slice;
45            let mut to_remove = rem;
46
47            slice_up_to_linear_time_impl! {
48                ret, to_remove, next,
49                (next @ ..,) (),
50            }
51            ret
52        }
53    }};
54}
55
56#[cfg(not(feature = "rust_1_64"))]
57macro_rules! slice_up_to_linear_time_impl{
58    (
59        $($args:tt)*
60    )=>({
61        slice_up_to_impl_inner!{
62            $($args)*
63            (64, [
64                _, _, _, _, _, _,_, _, _, _, _, _,_, _, _, _,
65                _, _, _, _, _, _, _, _,_, _, _, _, _, _,_, _,
66                _, _, _, _, _, _,_, _, _, _, _, _,_, _, _, _,
67                _, _, _, _, _, _, _, _,_, _, _, _, _, _,_, _,
68            ])
69        }
70        slice_up_to_impl_inner!{
71            $($args)*
72            (8, [_, _, _, _, _, _, _, _,])
73        }
74        slice_up_to_impl_inner!{
75            $($args)*
76            (1, [_,])
77        }
78    });
79}
80#[cfg(not(feature = "rust_1_64"))]
81macro_rules! slice_up_to_impl_inner{
82    (
83        $ret:ident, $to_remove:ident, $next:ident,
84        ($($before_ignored:tt)*) ($($after_ignored:tt)*),
85        ($ignored_len:expr, [$($ignored:tt)*])
86    )=>{
87        while $to_remove >= $ignored_len {
88            if let [
89                $($before_ignored)*
90                $($ignored)*
91                $($after_ignored)*
92            ] = $ret {
93                $ret = $next;
94            }
95            $to_remove -= $ignored_len;
96        }
97    }
98}
99
100/// A const equivalent of `slice.get(index)`
101///
102/// # Example
103///
104/// ```rust
105/// use konst::slice;
106///
107/// const FIBB: &[u16] = &[3, 5, 8];
108///
109/// const ELEM0: Option<&u16> = slice::get(FIBB, 0);
110/// const ELEM1: Option<&u16> = slice::get(FIBB, 1);
111/// const ELEM2: Option<&u16> = slice::get(FIBB, 2);
112/// const ELEM3: Option<&u16> = slice::get(FIBB, 3);
113///
114/// assert_eq!(ELEM0, Some(&3));
115/// assert_eq!(ELEM1, Some(&5));
116/// assert_eq!(ELEM2, Some(&8));
117/// assert_eq!(ELEM3, None);
118///
119/// ```
120#[inline]
121pub const fn get<T>(slice: &[T], index: usize) -> Option<&T> {
122    if slice.len() > index {
123        Some(&slice[index])
124    } else {
125        None
126    }
127}
128
129/// A const equivalent of `slice.get_mut(index)`
130///
131/// # Example
132///
133/// ```rust
134/// use konst::slice;
135///
136/// let mut fibb = [3, 5, 8];
137///
138/// assert_eq!(slice::get_mut(&mut fibb, 0), Some(&mut 3));
139/// assert_eq!(slice::get_mut(&mut fibb, 1), Some(&mut 5));
140/// assert_eq!(slice::get_mut(&mut fibb, 2), Some(&mut 8));
141/// assert_eq!(slice::get_mut(&mut fibb, 3), None);
142///
143/// ```
144#[inline]
145#[cfg(feature = "mut_refs")]
146#[cfg_attr(
147    feature = "docsrs",
148    doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
149)]
150pub const fn get_mut<T>(slice: &mut [T], index: usize) -> Option<&mut T> {
151    if slice.len() > index {
152        Some(&mut slice[index])
153    } else {
154        None
155    }
156}
157
158/// A const equivalent of `&slice[start..]`.
159///
160/// If `slice.len() < start`, this simply returns an empty slice.
161///
162/// # Performance
163///
164/// If the "rust_1_64" feature is disabled,
165/// thich takes linear time to remove the leading elements,
166/// proportional to `start`.
167///
168/// If the "rust_1_64" feature is enabled, it takes constant time to run.
169///
170/// # Example
171///
172/// ```rust
173/// use konst::slice::slice_from;
174///
175/// const FIBB: &[u16] = &[3, 5, 8, 13, 21, 34, 55, 89];
176///
177/// const TWO: &[u16] = slice_from(FIBB, 2);
178/// const FOUR: &[u16] = slice_from(FIBB, 4);
179/// const ALL: &[u16] = slice_from(FIBB, 0);
180/// const NONE: &[u16] = slice_from(FIBB, 1000);
181///
182/// assert_eq!(TWO, &[8, 13, 21, 34, 55, 89]);
183/// assert_eq!(FOUR, &[21, 34, 55, 89]);
184/// assert_eq!(ALL, FIBB);
185/// assert_eq!(NONE, &[]);
186///
187/// ```
188#[inline]
189pub const fn slice_from<T>(slice: &[T], start: usize) -> &[T] {
190    slice_from_impl!(slice, start, as_ptr, slice_from_raw_parts, &[])
191}
192
193/// A const equivalent of `slice.get(start..)`.
194///
195/// # Performance
196///
197/// If the "rust_1_64" feature is disabled,
198/// thich takes linear time to remove the leading elements,
199/// proportional to `start`.
200///
201/// If the "rust_1_64" feature is enabled, it takes constant time to run.
202///
203/// # Example
204///
205/// ```rust
206/// use konst::slice;
207///
208/// const FIBB: &[u16] = &[3, 5, 8, 13, 21, 34, 55, 89];
209///
210/// const TWO: Option<&[u16]> = slice::get_from(FIBB, 2);
211/// const FOUR: Option<&[u16]> = slice::get_from(FIBB, 4);
212/// const ALL: Option<&[u16]> = slice::get_from(FIBB, 0);
213/// const NONE: Option<&[u16]> = slice::get_from(FIBB, 1000);
214///
215/// assert_eq!(TWO, Some(&[8, 13, 21, 34, 55, 89][..]));
216/// assert_eq!(FOUR, Some(&[21, 34, 55, 89][..]));
217/// assert_eq!(ALL, Some(FIBB));
218/// assert_eq!(NONE, None);
219///
220/// ```
221#[inline]
222pub const fn get_from<T>(slice: &[T], start: usize) -> Option<&[T]> {
223    Some(slice_from_impl!(
224        slice,
225        start,
226        as_ptr,
227        slice_from_raw_parts,
228        None
229    ))
230}
231
232/// A const equivalent of `&mut slice[start..]`.
233///
234/// If `slice.len() < start`, this simply returns an empty slice.
235///
236/// # Performance
237///
238/// If the "rust_1_64" feature is disabled,
239/// thich takes linear time to remove the leading elements,
240/// proportional to `start`.
241///
242/// If the "rust_1_64" feature is enabled, it takes constant time to run.
243///
244/// # Example
245///
246/// ```rust
247/// use konst::slice::slice_from_mut;
248///
249/// let mut fibs = [3, 5, 8, 13, 21, 34, 55, 89];
250///
251/// assert_eq!(slice_from_mut(&mut fibs, 0), &mut [3, 5, 8, 13, 21, 34, 55, 89]);
252/// assert_eq!(slice_from_mut(&mut fibs, 1), &mut [5, 8, 13, 21, 34, 55, 89]);
253/// assert_eq!(slice_from_mut(&mut fibs, 2), &mut [8, 13, 21, 34, 55, 89]);
254/// assert_eq!(slice_from_mut(&mut fibs, 6), &mut [55, 89]);
255/// assert_eq!(slice_from_mut(&mut fibs, 7), &mut [89]);
256/// assert_eq!(slice_from_mut(&mut fibs, 8), &mut []);
257/// assert_eq!(slice_from_mut(&mut fibs, 1000), &mut []);
258///
259///
260/// ```
261#[inline]
262#[cfg(feature = "mut_refs")]
263#[cfg_attr(
264    feature = "docsrs",
265    doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
266)]
267pub const fn slice_from_mut<T>(slice: &mut [T], start: usize) -> &mut [T] {
268    slice_from_impl!(slice, start, as_mut_ptr, slice_from_raw_parts_mut, &mut [])
269}
270
271/// A const equivalent of `slice.get_mut(start..)`.
272///
273/// # Performance
274///
275/// If the "rust_1_64" feature is disabled,
276/// thich takes linear time to remove the leading elements,
277/// proportional to `start`.
278///
279/// If the "rust_1_64" feature is enabled, it takes constant time to run.
280///
281/// # Example
282///
283/// ```rust
284/// use konst::slice;
285///
286/// let mut fibs = [3, 5, 8, 13, 21, 34, 55];
287///
288/// assert_eq!(slice::get_from_mut(&mut fibs, 0), Some(&mut [3, 5, 8, 13, 21, 34, 55][..]));
289/// assert_eq!(slice::get_from_mut(&mut fibs, 1), Some(&mut [5, 8, 13, 21, 34, 55][..]));
290/// assert_eq!(slice::get_from_mut(&mut fibs, 2), Some(&mut [8, 13, 21, 34, 55][..]));
291/// assert_eq!(slice::get_from_mut(&mut fibs, 6), Some(&mut [55][..]));
292/// assert_eq!(slice::get_from_mut(&mut fibs, 7), Some(&mut [][..]));
293/// assert_eq!(slice::get_from_mut(&mut fibs, 8), None);
294/// assert_eq!(slice::get_from_mut(&mut fibs, 100), None);
295///
296///
297/// ```
298#[inline]
299#[cfg(feature = "mut_refs")]
300#[cfg_attr(
301    feature = "docsrs",
302    doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
303)]
304pub const fn get_from_mut<T>(slice: &mut [T], start: usize) -> Option<&mut [T]> {
305    Some(slice_from_impl!(
306        slice,
307        start,
308        as_mut_ptr,
309        slice_from_raw_parts_mut,
310        None
311    ))
312}
313
314/// A const equivalent of `&slice[..len]`.
315///
316/// If `slice.len() < len`, this simply returns `slice` back.
317///
318/// # Performance
319///
320/// If the "rust_1_64" feature is disabled,
321/// thich takes linear time to remove the trailing elements,
322/// proportional to `slice.len() - len`.
323///
324/// If the "rust_1_64" feature is enabled, it takes constant time to run.
325///
326/// # Example
327///
328/// ```rust
329/// use konst::slice::slice_up_to;
330///
331/// const FIBB: &[u16] = &[3, 5, 8, 13, 21, 34, 55, 89];
332///
333/// const TWO: &[u16] = slice_up_to(FIBB, 2);
334/// const FOUR: &[u16] = slice_up_to(FIBB, 4);
335/// const NONE: &[u16] = slice_up_to(FIBB, 0);
336/// const ALL: &[u16] = slice_up_to(FIBB, 1000);
337///
338/// assert_eq!(TWO, &[3, 5]);
339/// assert_eq!(FOUR, &[3, 5, 8, 13]);
340/// assert_eq!(NONE, &[]);
341/// assert_eq!(ALL, FIBB);
342///
343/// ```
344#[inline]
345pub const fn slice_up_to<T>(slice: &[T], len: usize) -> &[T] {
346    slice_up_to_impl!(slice, len, as_ptr, slice_from_raw_parts, slice)
347}
348
349/// A const equivalent of `slice.get(..len)`.
350///
351/// # Performance
352///
353/// If the "rust_1_64" feature is disabled,
354/// thich takes linear time to remove the trailing elements,
355/// proportional to `slice.len() - len`.
356///
357/// If the "rust_1_64" feature is enabled, it takes constant time to run.
358///
359/// # Example
360///
361/// ```rust
362/// use konst::slice;
363///
364/// const FIBB: &[u16] = &[3, 5, 8, 13, 21, 34, 55, 89];
365///
366/// const TWO: Option<&[u16]> = slice::get_up_to(FIBB, 2);
367/// const FOUR: Option<&[u16]> = slice::get_up_to(FIBB, 4);
368/// const NONE: Option<&[u16]> = slice::get_up_to(FIBB, 0);
369/// const ALL: Option<&[u16]> = slice::get_up_to(FIBB, 1000);
370///
371/// assert_eq!(TWO, Some(&[3, 5][..]));
372/// assert_eq!(FOUR, Some(&[3, 5, 8, 13][..]));
373/// assert_eq!(NONE, Some(&[][..]));
374/// assert_eq!(ALL, None);
375///
376/// ```
377#[inline]
378pub const fn get_up_to<T>(slice: &[T], len: usize) -> Option<&[T]> {
379    Some(slice_up_to_impl!(
380        slice,
381        len,
382        as_ptr,
383        slice_from_raw_parts,
384        None
385    ))
386}
387
388/// A const equivalent of `&mut slice[..len]`.
389///
390/// If `slice.len() < len`, this simply returns `slice` back.
391///
392/// # Performance
393///
394/// This takes constant time to run.
395///
396/// # Example
397///
398/// ```rust
399/// use konst::slice::slice_up_to_mut;
400///
401/// let mut fibs = [3, 5, 8, 13, 21, 34, 55, 89];
402///
403/// assert_eq!(slice_up_to_mut(&mut fibs, 100), &mut [3, 5, 8, 13, 21, 34, 55, 89]);
404/// assert_eq!(slice_up_to_mut(&mut fibs, 8), &mut [3, 5, 8, 13, 21, 34, 55, 89]);
405/// assert_eq!(slice_up_to_mut(&mut fibs, 7), &mut [3, 5, 8, 13, 21, 34, 55]);
406/// assert_eq!(slice_up_to_mut(&mut fibs, 6), &mut [3, 5, 8, 13, 21, 34]);
407/// assert_eq!(slice_up_to_mut(&mut fibs, 3), &mut [3, 5, 8]);
408/// assert_eq!(slice_up_to_mut(&mut fibs, 2), &mut [3, 5]);
409/// assert_eq!(slice_up_to_mut(&mut fibs, 1), &mut [3]);
410/// assert_eq!(slice_up_to_mut(&mut fibs, 0), &mut []);
411///
412///
413/// ```
414#[inline]
415#[cfg(feature = "mut_refs")]
416#[cfg_attr(
417    feature = "docsrs",
418    doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
419)]
420pub const fn slice_up_to_mut<T>(slice: &mut [T], len: usize) -> &mut [T] {
421    slice_up_to_impl!(slice, len, as_mut_ptr, slice_from_raw_parts_mut, slice)
422}
423
424/// A const equivalent of `slice.get_mut(..len)`.
425///
426/// # Performance
427///
428/// This takes constant time to run.
429///
430/// # Example
431///
432/// ```rust
433/// use konst::slice;
434///
435/// let mut fibs = [3, 5, 8, 13, 21, 34, 55, 89];
436///
437/// assert_eq!(slice::get_up_to_mut(&mut fibs, 100), None);
438/// assert_eq!(slice::get_up_to_mut(&mut fibs, 9), None);
439/// assert_eq!(slice::get_up_to_mut(&mut fibs, 8), Some(&mut [3, 5, 8, 13, 21, 34, 55, 89][..]));
440/// assert_eq!(slice::get_up_to_mut(&mut fibs, 7), Some(&mut [3, 5, 8, 13, 21, 34, 55][..]));
441/// assert_eq!(slice::get_up_to_mut(&mut fibs, 6), Some(&mut [3, 5, 8, 13, 21, 34][..]));
442/// assert_eq!(slice::get_up_to_mut(&mut fibs, 3), Some(&mut [3, 5, 8][..]));
443/// assert_eq!(slice::get_up_to_mut(&mut fibs, 2), Some(&mut [3, 5][..]));
444/// assert_eq!(slice::get_up_to_mut(&mut fibs, 1), Some(&mut [3][..]));
445/// assert_eq!(slice::get_up_to_mut(&mut fibs, 0), Some(&mut [][..]));
446///
447/// ```
448#[inline]
449#[cfg(feature = "mut_refs")]
450#[cfg_attr(
451    feature = "docsrs",
452    doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
453)]
454#[inline]
455pub const fn get_up_to_mut<T>(slice: &mut [T], len: usize) -> Option<&mut [T]> {
456    Some(slice_up_to_impl!(
457        slice,
458        len,
459        as_mut_ptr,
460        slice_from_raw_parts_mut,
461        None
462    ))
463}
464
465/// A const equivalent of `&slice[start..end]`.
466///
467/// If `start >= end ` or `slice.len() < start `, this returns an empty slice.
468///
469/// If `slice.len() < end`, this returns the slice from `start`.
470///
471/// # Alternatives
472///
473/// For a const equivalent of `&slice[start..]` there's [`slice_from`].
474///
475/// For a const equivalent of `&slice[..end]` there's [`slice_up_to`].
476///
477/// [`slice_from`]: ./fn.slice_from.html
478/// [`slice_up_to`]: ./fn.slice_up_to.html
479///
480/// # Performance
481///
482/// If the "rust_1_64" feature is disabled,
483/// thich takes linear time to remove the leading and trailing elements,
484/// proportional to `start + (slice.len() - end)`.
485///
486/// If the "rust_1_64" feature is enabled, it takes constant time to run.
487///
488/// # Example
489///
490/// ```rust
491/// use konst::slice::slice_range;
492///
493/// const FIBB: &[u16] = &[3, 5, 8, 13, 21, 34, 55, 89];
494///
495/// const TWO: &[u16] = slice_range(FIBB, 2, 4);
496/// const FOUR: &[u16] = slice_range(FIBB, 4, 7);
497/// const NONE: &[u16] = slice_range(FIBB, 0, 0);
498/// const ALL: &[u16] = slice_range(FIBB, 0, 1000);
499///
500/// assert_eq!(TWO, &[8, 13]);
501/// assert_eq!(FOUR, &[21, 34, 55]);
502/// assert_eq!(NONE, &[]);
503/// assert_eq!(ALL, FIBB);
504///
505/// ```
506pub const fn slice_range<T>(slice: &[T], start: usize, end: usize) -> &[T] {
507    slice_from(slice_up_to(slice, end), start)
508}
509
510/// A const equivalent of `slice.get(start..end)`.
511///
512/// # Alternatives
513///
514/// For a const equivalent of `slice.get(start..)` there's [`get_from`].
515///
516/// For a const equivalent of `slice.get(..end)` there's [`get_up_to`].
517///
518/// [`get_from`]: ./fn.get_from.html
519/// [`get_up_to`]: ./fn.get_up_to.html
520///
521/// # Performance
522///
523/// If the "rust_1_64" feature is disabled,
524/// thich takes linear time to remove the leading and trailing elements,
525/// proportional to `start + (slice.len() - end)`.
526///
527/// If the "rust_1_64" feature is enabled, it takes constant time to run.
528///
529/// # Example
530///
531/// ```rust
532/// use konst::slice;
533///
534/// const FIBB: &[u16] = &[3, 5, 8, 13, 21, 34, 55, 89];
535///
536/// const TWO: Option<&[u16]> = slice::get_range(FIBB, 2, 4);
537/// const FOUR: Option<&[u16]> = slice::get_range(FIBB, 4, 7);
538/// const ALL: Option<&[u16]> = slice::get_range(FIBB, 0, 8);
539/// const EMPTY: Option<&[u16]> = slice::get_range(FIBB, 0, 0);
540/// const NONE: Option<&[u16]> = slice::get_range(FIBB, 0, 1000);
541///
542/// assert_eq!(TWO, Some(&[8, 13][..]));
543/// assert_eq!(FOUR, Some(&[21, 34, 55][..]));
544/// assert_eq!(ALL, Some(FIBB));
545/// assert_eq!(EMPTY, Some(&[][..]));
546/// assert_eq!(NONE, None);
547///
548/// ```
549pub const fn get_range<T>(slice: &[T], start: usize, end: usize) -> Option<&[T]> {
550    let x = crate::try_opt!(get_up_to(slice, end));
551    get_from(x, start)
552}
553
554/// A const equivalent of `&mut slice[start..end]`.
555///
556/// If `start >= end ` or `slice.len() < start `, this returns an empty slice.
557///
558/// If `slice.len() < end`, this returns the slice from `start`.
559///
560///
561/// # Alternatives
562///
563/// For a const equivalent of `&mut slice[start..]` there's [`slice_from_mut`].
564///
565/// For a const equivalent of `&mut slice[..end]` there's [`slice_up_to_mut`].
566///
567/// [`slice_from_mut`]: ./fn.slice_from_mut.html
568/// [`slice_up_to_mut`]: ./fn.slice_up_to_mut.html
569///
570/// # Performance
571///
572/// If the "rust_1_64" feature is disabled,
573/// thich takes linear time to remove the leading and trailing elements,
574/// proportional to `start + (slice.len() - end)`.
575///
576/// If the "rust_1_64" feature is enabled, it takes constant time to run.
577///
578/// # Example
579///
580/// ```rust
581/// use konst::slice::slice_range_mut;
582///
583/// let mut fibb = [3, 5, 8, 13, 21, 34, 55, 89];
584///
585/// assert_eq!(slice_range_mut(&mut fibb, 2, 4), &mut [8, 13]);
586/// assert_eq!(slice_range_mut(&mut fibb, 4, 7), &mut [21, 34, 55]);
587/// assert_eq!(slice_range_mut(&mut fibb, 0, 0), &mut []);
588/// assert_eq!(slice_range_mut(&mut fibb, 0, 1000), &mut [3, 5, 8, 13, 21, 34, 55, 89]);
589///
590/// ```
591#[inline]
592#[cfg(feature = "mut_refs")]
593#[cfg_attr(
594    feature = "docsrs",
595    doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
596)]
597pub const fn slice_range_mut<T>(slice: &mut [T], start: usize, end: usize) -> &mut [T] {
598    slice_from_mut(slice_up_to_mut(slice, end), start)
599}
600
601/// A const equivalent of `slice.get_mut(start..end)`.
602///
603///
604/// # Alternatives
605///
606/// For a const equivalent of `slice.get_mut(start..)` there's [`get_from_mut`].
607///
608/// For a const equivalent of `slice.get_mut(..end)` there's [`get_up_to_mut`].
609///
610/// [`get_from_mut`]: ./fn.get_from_mut.html
611/// [`get_up_to_mut`]: ./fn.get_up_to_mut.html
612///
613/// # Performance
614///
615/// If the "rust_1_64" feature is disabled,
616/// thich takes linear time to remove the leading and trailing elements,
617/// proportional to `start + (slice.len() - end)`.
618///
619/// If the "rust_1_64" feature is enabled, it takes constant time to run.
620///
621/// # Example
622///
623/// ```rust
624/// use konst::slice;
625///
626/// let mut fibb = [3, 5, 8, 13, 21, 34, 55];
627///
628/// assert_eq!(slice::get_range_mut(&mut fibb, 0, 0), Some(&mut [][..]));
629/// assert_eq!(slice::get_range_mut(&mut fibb, 2, 4), Some(&mut [8, 13][..]));
630/// assert_eq!(slice::get_range_mut(&mut fibb, 4, 7), Some(&mut [21, 34, 55][..]));
631/// assert_eq!(slice::get_range_mut(&mut fibb, 0, 7), Some(&mut [3, 5, 8, 13, 21, 34, 55][..]));
632/// assert_eq!(slice::get_range_mut(&mut fibb, 0, 1000), None);
633///
634/// ```
635#[inline]
636#[cfg(feature = "mut_refs")]
637#[cfg_attr(
638    feature = "docsrs",
639    doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
640)]
641pub const fn get_range_mut<T>(slice: &mut [T], start: usize, end: usize) -> Option<&mut [T]> {
642    let x = crate::try_opt!(get_up_to_mut(slice, end));
643    get_from_mut(x, start)
644}
645
646/// A const equivalent of
647/// [`<[T]>::split_at`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_at)
648///
649/// If `at > slice.len()`, this returns a `slice`, empty slice pair.
650///
651/// # Performance
652///
653/// If the "rust_1_64" feature is disabled,
654/// thich takes linear time to split the string, proportional to its length.
655///
656/// If the "rust_1_64" feature is enabled, it takes constant time to run.
657///
658/// # Example
659///
660/// ```rust
661/// use konst::slice::split_at;
662///
663/// let arr = [3, 5, 8, 13, 21, 34];
664///
665/// assert_eq!(split_at(&arr, 0), (&[][..], &[3, 5, 8, 13, 21, 34][..]));
666///
667/// assert_eq!(split_at(&arr, 1), (&[3][..], &[5, 8, 13, 21, 34][..]));
668///
669/// assert_eq!(split_at(&arr, 2), (&[3, 5][..], &[8, 13, 21, 34][..]));
670///
671/// assert_eq!(split_at(&arr, 5), (&[3, 5, 8, 13, 21][..], &[34][..]));
672///
673/// assert_eq!(split_at(&arr, 6), (&[3, 5, 8, 13, 21, 34][..], &[][..]));
674///
675/// assert_eq!(split_at(&arr, 7), (&[3, 5, 8, 13, 21, 34][..], &[][..]));
676///
677/// ```
678///
679pub const fn split_at<T>(slice: &[T], at: usize) -> (&[T], &[T]) {
680    (slice_up_to(slice, at), slice_from(slice, at))
681}
682
683/// A const equivalent of
684/// [`<[T]>::split_at_mut`
685/// ](https://doc.rust-lang.org/std/primitive.slice.html#method.split_at_mut)
686///
687/// If `at > slice.len()`, this returns a `slice`, empty slice pair.
688///
689/// # Performance
690///
691/// This takes constant time to run.
692///
693/// # Example
694///
695/// ```rust
696/// use konst::slice::split_at_mut;
697///
698/// let mut arr = [3, 5, 8, 13, 21, 34];
699///
700/// assert_eq!(split_at_mut(&mut arr, 0), (&mut [][..], &mut [3, 5, 8, 13, 21, 34][..]));
701///
702/// assert_eq!(split_at_mut(&mut arr, 1), (&mut [3][..], &mut [5, 8, 13, 21, 34][..]));
703///
704/// assert_eq!(split_at_mut(&mut arr, 2), (&mut [3, 5][..], &mut [8, 13, 21, 34][..]));
705///
706/// assert_eq!(split_at_mut(&mut arr, 5), (&mut [3, 5, 8, 13, 21][..], &mut [34][..]));
707///
708/// assert_eq!(split_at_mut(&mut arr, 6), (&mut [3, 5, 8, 13, 21, 34][..], &mut [][..]));
709///
710/// assert_eq!(split_at_mut(&mut arr, 7), (&mut [3, 5, 8, 13, 21, 34][..], &mut [][..]));
711///
712/// ```
713///
714#[inline]
715#[cfg(feature = "mut_refs")]
716#[cfg_attr(feature = "docsrs", doc(cfg(feature = "mut_refs")))]
717pub const fn split_at_mut<T>(slice: &mut [T], at: usize) -> (&mut [T], &mut [T]) {
718    use crate::utils::slice_from_raw_parts_mut;
719
720    if at > slice.len() {
721        return (slice, &mut []);
722    }
723
724    let suffix_len = slice.len() - at;
725
726    unsafe {
727        let ptr = slice.as_mut_ptr();
728
729        let prefix = slice_from_raw_parts_mut(ptr.offset(0), at);
730        let suffix = slice_from_raw_parts_mut(ptr.offset(at as isize), suffix_len);
731
732        (prefix, suffix)
733    }
734}
735
736/// A const equivalent of
737/// [`<[u8]>::starts_with`](https://doc.rust-lang.org/std/primitive.slice.html#method.starts_with)
738///
739/// # Example
740///
741/// ```rust
742/// use konst::slice::bytes_start_with;
743///
744/// assert!( bytes_start_with(b"foo,bar,baz", b"foo,"));
745///
746/// assert!(!bytes_start_with(b"foo,bar,baz", b"bar"));
747/// assert!(!bytes_start_with(b"foo,bar,baz", b"baz"));
748///
749/// ```
750///
751#[inline]
752pub const fn bytes_start_with(left: &[u8], right: &[u8]) -> bool {
753    matches!(bytes_strip_prefix(left, right), Some(_))
754}
755
756/// A const equivalent of
757/// [`<[u8]>::strip_prefix`](https://doc.rust-lang.org/std/primitive.slice.html#method.strip_prefix)
758///
759/// # Example
760///
761/// ```rust
762/// use konst::slice::bytes_strip_prefix;
763///
764/// assert_eq!(bytes_strip_prefix(b"foo,bar,baz", b"foo,"), Some("bar,baz".as_bytes()));
765///
766/// assert_eq!(bytes_strip_prefix(b"foo,bar,baz", b"bar"), None);
767/// assert_eq!(bytes_strip_prefix(b"foo,bar,baz", b"baz"), None);
768///
769/// ```
770///
771/// [`strip_prefix`]:
772/// https://doc.rust-lang.org/std/primitive.slice.html#method.strip_prefix
773///
774#[inline]
775pub const fn bytes_strip_prefix<'a>(mut left: &'a [u8], mut prefix: &[u8]) -> Option<&'a [u8]> {
776    impl_bytes_function! {
777        strip_prefix;
778        left = left;
779        right = prefix;
780        on_error = return None,
781    }
782    Some(left)
783}
784
785/// A const equivalent of
786/// [`<[u8]>::ends_with`](https://doc.rust-lang.org/std/primitive.slice.html#method.ends_with)
787///
788/// # Example
789///
790/// ```rust
791/// use konst::slice::bytes_end_with;
792///
793/// assert!( bytes_end_with(b"foo,bar,baz", b",baz"));
794///
795/// assert!(!bytes_end_with(b"foo,bar,baz", b"bar"));
796/// assert!(!bytes_end_with(b"foo,bar,baz", b"foo"));
797///
798/// ```
799///
800#[inline]
801pub const fn bytes_end_with(left: &[u8], right: &[u8]) -> bool {
802    matches!(bytes_strip_suffix(left, right), Some(_))
803}
804
805/// A const equivalent of
806/// [`<[u8]>::strip_suffix`](https://doc.rust-lang.org/std/primitive.slice.html#method.strip_suffix)
807///
808/// # Example
809///
810/// ```rust
811/// use konst::slice::bytes_strip_suffix;
812///
813/// assert_eq!(bytes_strip_suffix(b"foo,bar,baz", b",baz"), Some("foo,bar".as_bytes()));
814///
815/// assert_eq!(bytes_strip_suffix(b"foo,bar,baz", b"bar"), None);
816/// assert_eq!(bytes_strip_suffix(b"foo,bar,baz", b"foo"), None);
817///
818/// ```
819///
820/// [`strip_suffix`]:
821/// https://doc.rust-lang.org/std/primitive.slice.html#method.strip_suffix
822///
823#[inline]
824pub const fn bytes_strip_suffix<'a>(mut left: &'a [u8], mut suffix: &[u8]) -> Option<&'a [u8]> {
825    impl_bytes_function! {
826        strip_suffix;
827        left = left;
828        right = suffix;
829        on_error = return None,
830    }
831    Some(left)
832}
833
834/// Finds the byte offset of `right` in `left`, starting from the `from` index.
835///
836/// Returns `None` if `right` isn't inside `&left[from..]`
837///
838/// # Example
839///
840/// ```rust
841/// use konst::slice::bytes_find;
842///
843/// assert_eq!(bytes_find(b"foo-bar-baz-foo", b"foo", 0), Some(0));
844/// assert_eq!(bytes_find(b"foo-bar-baz-foo", b"foo", 4), Some(12));
845///
846/// assert_eq!(bytes_find(b"foo-bar-baz-foo-bar", b"bar", 0), Some(4));
847/// assert_eq!(bytes_find(b"foo-bar-baz-foo-bar", b"bar", 4), Some(4));
848/// assert_eq!(bytes_find(b"foo-bar-baz-foo-bar", b"bar", 5), Some(16));
849/// assert_eq!(bytes_find(b"foo-bar-baz-foo-bar", b"bar", 16), Some(16));
850/// assert_eq!(bytes_find(b"foo-bar-baz-foo-bar", b"bar", 17), None);
851///
852/// ```
853///
854#[inline]
855pub const fn bytes_find(left: &[u8], right: &[u8], from: usize) -> Option<usize> {
856    let mut matching = right;
857
858    for_range! {i in from..left.len() =>
859        match matching {
860            [mb, m_rem @ ..] => {
861                let b = left[i];
862
863                matching = if b == *mb {
864                    m_rem
865                } else {
866                    match right {
867                        // For when the string is "lawlawn" and we are trying to find "lawn"
868                        [mb2, m_rem2 @ ..] if b == *mb2 => m_rem2,
869                        _ => right,
870                    }
871                };
872            }
873            [] => {
874                return Some(i - right.len())
875            }
876        }
877    }
878
879    if matching.is_empty() {
880        Some(left.len() - right.len())
881    } else {
882        None
883    }
884}
885
886/// Whether `right` is inside `&left[from..]`.
887///
888/// # Example
889///
890/// ```rust
891/// use konst::slice::bytes_contain;
892///
893/// assert!(bytes_contain(b"foo-bar-baz-foo", b"foo", 0));
894/// assert!(bytes_contain(b"foo-bar-baz-foo", b"foo", 4));
895///
896/// assert!( bytes_contain(b"foo-bar-baz-foo-bar", b"bar", 0));
897/// assert!( bytes_contain(b"foo-bar-baz-foo-bar", b"bar", 4));
898/// assert!( bytes_contain(b"foo-bar-baz-foo-bar", b"bar", 5));
899/// assert!( bytes_contain(b"foo-bar-baz-foo-bar", b"bar", 16));
900/// assert!(!bytes_contain(b"foo-bar-baz-foo-bar", b"bar", 17));
901///
902/// ```
903///
904#[inline(always)]
905pub const fn bytes_contain(left: &[u8], right: &[u8], from: usize) -> bool {
906    matches!(bytes_find(left, right, from), Some(_))
907}
908
909/// Finds the byte offset of `right` inside `&left[..=from]`, searching in reverse.
910///
911/// Returns `None` if `right` isn't inside `&left[..=from]`.
912///
913/// # Example
914///
915/// ```rust
916/// use konst::slice::bytes_rfind;
917///
918/// assert_eq!(bytes_rfind(b"foo-bar-baz-foo", b"foo", 0), None);
919/// assert_eq!(bytes_rfind(b"foo-bar-baz-foo", b"foo", 1), None);
920///
921/// assert_eq!(bytes_rfind(b"foo-bar-baz-foo", b"foo", 2), Some(0));
922/// assert_eq!(bytes_rfind(b"foo-bar-baz-foo", b"foo", 3), Some(0));
923/// assert_eq!(bytes_rfind(b"foo-bar-baz-foo", b"foo", 4), Some(0));
924///
925/// assert_eq!(bytes_rfind(b"foo-bar-baz-foo", b"foo", 15), Some(12));
926/// assert_eq!(bytes_rfind(b"foo-bar-baz-foo", b"foo", 20000), Some(12));
927///
928/// ```
929///
930#[inline]
931pub const fn bytes_rfind(left: &[u8], right: &[u8], from: usize) -> Option<usize> {
932    let mut matching = right;
933
934    let llen = left.len();
935
936    let mut i = if from >= llen { llen } else { from + 1 };
937
938    while i != 0 {
939        i -= 1;
940
941        match matching {
942            [m_rem @ .., mb] => {
943                let b = left[i];
944
945                matching = if b == *mb {
946                    m_rem
947                } else {
948                    match right {
949                        // For when the string is "lawlawn" and we are trying to find "lawn"
950                        [m_rem2 @ .., mb2] if b == *mb2 => m_rem2,
951                        _ => right,
952                    }
953                };
954            }
955            [] => return Some(i + (!right.is_empty()) as usize),
956        }
957    }
958
959    if matching.is_empty() {
960        Some(i)
961    } else {
962        None
963    }
964}
965
966/// Returns whether `right` is contained inside `&left[..=from]` searching in reverse.
967///
968/// # Example
969///
970/// ```rust
971/// use konst::slice::bytes_rcontain;
972///
973/// assert!(!bytes_rcontain(b"foo-bar-baz-foo", b"foo", 0));
974/// assert!(!bytes_rcontain(b"foo-bar-baz-foo", b"foo", 1));
975///
976/// assert!(bytes_rcontain(b"foo-bar-baz-foo", b"foo", 2));
977/// assert!(bytes_rcontain(b"foo-bar-baz-foo", b"foo", 3));
978/// assert!(bytes_rcontain(b"foo-bar-baz-foo", b"foo", 4));
979///
980/// assert!(bytes_rcontain(b"foo-bar-baz-foo", b"foo", 15));
981/// assert!(bytes_rcontain(b"foo-bar-baz-foo", b"foo", 20000));
982///
983/// ```
984///
985#[inline(always)]
986pub const fn bytes_rcontain(left: &[u8], right: &[u8], from: usize) -> bool {
987    matches!(bytes_rfind(left, right, from), Some(_))
988}
989
990macro_rules! matches_space {
991    ($b:ident) => {
992        matches!($b, b'\t' | b'\n' | b'\r' | b' ')
993    };
994}
995
996/// Removes ascii whitespace from the start and end of `this`.
997///
998/// # Example
999///
1000/// ```rust
1001/// use konst::slice;
1002///
1003/// const TRIMMED: &[u8] = slice::bytes_trim(b"\nhello world  ");
1004///
1005/// assert_eq!(TRIMMED, b"hello world");
1006///
1007/// ```
1008pub const fn bytes_trim(this: &[u8]) -> &[u8] {
1009    bytes_trim_start(bytes_trim_end(this))
1010}
1011
1012/// Removes ascii whitespace from the start of `this`.
1013///
1014/// # Example
1015///
1016/// ```rust
1017/// use konst::slice;
1018///
1019/// const TRIMMED: &[u8] = slice::bytes_trim_start(b"\tfoo bar  ");
1020///
1021/// assert_eq!(TRIMMED, b"foo bar  ");
1022///
1023/// ```
1024pub const fn bytes_trim_start(mut this: &[u8]) -> &[u8] {
1025    loop {
1026        match this {
1027            [b, rem @ ..] if matches_space!(b) => this = rem,
1028            _ => return this,
1029        }
1030    }
1031}
1032
1033/// Removes ascii whitespace from the end of `this`.
1034///
1035/// # Example
1036///
1037/// ```rust
1038/// use konst::slice;
1039///
1040/// const TRIMMED: &[u8] = slice::bytes_trim_end(b"\rfoo bar  ");
1041///
1042/// assert_eq!(TRIMMED, b"\rfoo bar");
1043///
1044/// ```
1045pub const fn bytes_trim_end(mut this: &[u8]) -> &[u8] {
1046    loop {
1047        match this {
1048            [rem @ .., b] if matches_space!(b) => this = rem,
1049            _ => return this,
1050        }
1051    }
1052}
1053
1054/// Removes all instances of `needle` from the start and end of `this`.
1055///
1056/// # Example
1057///
1058/// ```rust
1059/// use konst::slice;
1060///
1061/// const TRIMMED: &[u8] = slice::bytes_trim_matches(b"<>baz qux<><><>", b"<>");
1062///
1063/// assert_eq!(TRIMMED, b"baz qux");
1064///
1065/// ```
1066pub const fn bytes_trim_matches<'a>(this: &'a [u8], needle: &[u8]) -> &'a [u8] {
1067    let ltrim = bytes_trim_start_matches(this, needle);
1068    bytes_trim_end_matches(ltrim, needle)
1069}
1070
1071/// Removes all instances of `needle` from the start of `this`.
1072///
1073/// # Example
1074///
1075/// ```rust
1076/// use konst::slice;
1077///
1078/// const TRIMMED: &[u8] = slice::bytes_trim_start_matches(b"#####huh###", b"##");
1079///
1080/// assert_eq!(TRIMMED, b"#huh###");
1081///
1082/// ```
1083pub const fn bytes_trim_start_matches<'a>(mut this: &'a [u8], needle: &[u8]) -> &'a [u8] {
1084    if needle.is_empty() {
1085        return this;
1086    }
1087
1088    let mut matched = needle;
1089
1090    loop {
1091        let at_start = this;
1092
1093        match (this, matched) {
1094            ([b, rem @ ..], [bm, remm @ ..]) if *b == *bm => {
1095                this = rem;
1096                matched = remm;
1097            }
1098            _ => return this,
1099        }
1100
1101        'inner: loop {
1102            match (this, matched) {
1103                ([], [_, ..]) => return at_start,
1104                ([b, rem @ ..], [bm, remm @ ..]) => {
1105                    if *b == *bm {
1106                        this = rem;
1107                        matched = remm;
1108                    } else {
1109                        return at_start;
1110                    }
1111                }
1112                _ => break 'inner,
1113            }
1114        }
1115
1116        matched = needle;
1117    }
1118}
1119
1120/// Removes all instances of `needle` from the end of `this`.
1121///
1122/// # Example
1123///
1124/// ```rust
1125/// use konst::slice;
1126///
1127/// const TRIMMED: &[u8] = slice::bytes_trim_end_matches(b"oowowooooo", b"oo");
1128///
1129/// assert_eq!(TRIMMED, b"oowowo");
1130///
1131/// ```
1132pub const fn bytes_trim_end_matches<'a>(mut this: &'a [u8], needle: &[u8]) -> &'a [u8] {
1133    if needle.is_empty() {
1134        return this;
1135    }
1136
1137    let mut matched = needle;
1138
1139    loop {
1140        let at_start = this;
1141
1142        match (this, matched) {
1143            ([rem @ .., b], [remm @ .., bm]) if *b == *bm => {
1144                this = rem;
1145                matched = remm;
1146            }
1147            _ => return this,
1148        }
1149
1150        'inner: loop {
1151            match (this, matched) {
1152                ([], [.., _]) => return at_start,
1153                ([rem @ .., b], [remm @ .., bm]) => {
1154                    if *b == *bm {
1155                        this = rem;
1156                        matched = remm;
1157                    } else {
1158                        return at_start;
1159                    }
1160                }
1161                _ => break 'inner,
1162            }
1163        }
1164
1165        matched = needle;
1166    }
1167}
1168
1169macro_rules! elem_then_rem {
1170    ($elem:ident, $($rem:tt)*) => { [$elem, $($rem)*] };
1171}
1172
1173macro_rules! rem_then_elem {
1174    ($elem:ident, $($rem:tt)*) => { [$($rem)*, $elem] };
1175}
1176
1177macro_rules! byte_find_then {
1178    ($slice_order:ident, $this:ident, $needle:ident, |$next:ident| $then:block) => ({
1179        if $needle.is_empty() {
1180            return Some($this);
1181        }
1182
1183        let mut matching = $needle;
1184
1185        let mut $next = $this;
1186
1187        while let $slice_order!(mb, ref m_rem @ ..) = *matching {
1188            matching = m_rem;
1189
1190            if let $slice_order!(b, ref rem @ ..) = *$next {
1191                if b != mb {
1192                    matching = match *$needle {
1193                        // For when the string is "lawlawn" and we are skipping "lawn"
1194                        $slice_order!(mb2, ref m_rem2 @ ..) if b == mb2 => {
1195                            // This is considered used in half of the macro invocations
1196                            #[allow(unused_assignments)]
1197                            {$this = $next;}
1198                            m_rem2
1199                        },
1200                        _ => {
1201                            // This is considered used in half of the macro invocations
1202                            #[allow(unused_assignments)]
1203                            {$this = rem;}
1204                            $needle
1205                        },
1206                    };
1207                }
1208                $next = rem;
1209            } else {
1210                return None;
1211            }
1212        }
1213
1214        $then
1215
1216        Some($this)
1217    });
1218}
1219
1220/// Advances `this` past the first instance of `needle`.
1221///
1222/// Return `None` if no instance of `needle` is found.
1223///
1224/// Return `Some(this)` if `needle` is empty.
1225///
1226/// # Motivation
1227///
1228/// This function exists because calling [`bytes_find`] + [`slice_from`]
1229/// when the `"rust_1_64"` feature is disabled
1230/// is slower than it could be, since the slice has to be traversed twice.
1231///
1232/// [`bytes_find`]: ./fn.bytes_find.html
1233/// [`slice_from`]: ./fn.slice_from.html
1234///
1235/// # Example
1236///
1237/// ```rust
1238/// use konst::slice::bytes_find_skip;
1239///
1240/// {
1241///     const FOUND: Option<&[u8]> = bytes_find_skip(b"foo bar baz", b"bar");
1242///     assert_eq!(FOUND, Some(&b" baz"[..]));
1243/// }
1244/// {
1245///     const NOT_FOUND: Option<&[u8]> = bytes_find_skip(b"foo bar baz", b"qux");
1246///     assert_eq!(NOT_FOUND, None);
1247/// }
1248/// {
1249///     const EMPTY_NEEDLE: Option<&[u8]> = bytes_find_skip(b"foo bar baz", b"");
1250///     assert_eq!(EMPTY_NEEDLE, Some(&b"foo bar baz"[..]));
1251/// }
1252/// ```
1253pub const fn bytes_find_skip<'a>(mut this: &'a [u8], needle: &[u8]) -> Option<&'a [u8]> {
1254    byte_find_then! {elem_then_rem, this, needle, |next| {this = next}}
1255}
1256
1257/// Advances `this` up to the first instance of `needle`.
1258///
1259/// Return `None` if no instance of `needle` is found.
1260///
1261/// Return `Some(this)` if `needle` is empty.
1262///
1263/// # Motivation
1264///
1265/// This function exists because calling [`bytes_find`] + [`slice_from`]
1266/// when the `"rust_1_64"` feature is disabled
1267/// is slower than it could be, since the slice has to be traversed twice.
1268///
1269/// [`bytes_find`]: ./fn.bytes_find.html
1270/// [`slice_from`]: ./fn.slice_from.html
1271///
1272/// # Example
1273///
1274/// ```rust
1275/// use konst::slice::bytes_find_keep;
1276///
1277/// {
1278///     const FOUND: Option<&[u8]> = bytes_find_keep(b"foo bar baz", b"bar");
1279///     assert_eq!(FOUND, Some(&b"bar baz"[..]));
1280/// }
1281/// {
1282///     const NOT_FOUND: Option<&[u8]> = bytes_find_keep(b"foo bar baz", b"qux");
1283///     assert_eq!(NOT_FOUND, None);
1284/// }
1285/// {
1286///     const EMPTY_NEEDLE: Option<&[u8]> = bytes_find_keep(b"foo bar baz", b"");
1287///     assert_eq!(EMPTY_NEEDLE, Some(&b"foo bar baz"[..]));
1288/// }
1289/// ```
1290pub const fn bytes_find_keep<'a>(mut this: &'a [u8], needle: &[u8]) -> Option<&'a [u8]> {
1291    byte_find_then! {elem_then_rem, this, needle, |next| {}}
1292}
1293
1294/// Truncates `this` to before the last instance of `needle`.
1295///
1296/// Return `None` if no instance of `needle` is found.
1297///
1298/// Return `Some(this)` if `needle` is empty.
1299///
1300/// # Motivation
1301///
1302/// This function exists because calling [`bytes_rfind`] + [`slice_up_to`]
1303/// when the `"rust_1_64"` feature is disabled
1304/// is slower than it could be, since the slice has to be traversed twice.
1305///
1306/// [`bytes_rfind`]: ./fn.bytes_rfind.html
1307/// [`slice_up_to`]: ./fn.slice_up_to.html
1308///
1309/// # Example
1310///
1311/// ```rust
1312/// use konst::slice::bytes_rfind_skip;
1313///
1314/// {
1315///     const FOUND: Option<&[u8]> = bytes_rfind_skip(b"foo bar _ bar baz", b"bar");
1316///     assert_eq!(FOUND, Some(&b"foo bar _ "[..]));
1317/// }
1318/// {
1319///     const NOT_FOUND: Option<&[u8]> = bytes_rfind_skip(b"foo bar baz", b"qux");
1320///     assert_eq!(NOT_FOUND, None);
1321/// }
1322/// {
1323///     const EMPTY_NEEDLE: Option<&[u8]> = bytes_rfind_skip(b"foo bar baz", b"");
1324///     assert_eq!(EMPTY_NEEDLE, Some(&b"foo bar baz"[..]));
1325/// }
1326/// ```
1327pub const fn bytes_rfind_skip<'a>(mut this: &'a [u8], needle: &[u8]) -> Option<&'a [u8]> {
1328    byte_find_then! {rem_then_elem, this, needle, |next| {this = next}}
1329}
1330
1331/// Truncates `this` to the last instance of `needle`.
1332///
1333/// Return `None` if no instance of `needle` is found.
1334///
1335/// Return `Some(this)` if `needle` is empty.
1336///
1337/// # Motivation
1338///
1339/// This function exists because calling [`bytes_rfind`] + [`slice_up_to`]
1340/// when the `"rust_1_64"` feature is disabled
1341/// is slower than it could be, since the slice has to be traversed twice.
1342///
1343/// [`bytes_rfind`]: ./fn.bytes_rfind.html
1344/// [`slice_up_to`]: ./fn.slice_up_to.html
1345///
1346/// # Example
1347///
1348/// ```rust
1349/// use konst::slice::bytes_rfind_keep;
1350///
1351/// {
1352///     const FOUND: Option<&[u8]> = bytes_rfind_keep(b"foo bar _ bar baz", b"bar");
1353///     assert_eq!(FOUND, Some(&b"foo bar _ bar"[..]));
1354/// }
1355/// {
1356///     const NOT_FOUND: Option<&[u8]> = bytes_rfind_keep(b"foo bar baz", b"qux");
1357///     assert_eq!(NOT_FOUND, None);
1358/// }
1359/// {
1360///     const EMPTY_NEEDLE: Option<&[u8]> = bytes_rfind_keep(b"foo bar baz", b"");
1361///     assert_eq!(EMPTY_NEEDLE, Some(&b"foo bar baz"[..]));
1362/// }
1363/// ```
1364pub const fn bytes_rfind_keep<'a>(mut this: &'a [u8], needle: &[u8]) -> Option<&'a [u8]> {
1365    byte_find_then! {rem_then_elem, this, needle, |next| {}}
1366}
1367
1368/// A const equivalent of
1369/// [`<[T]>::first`](https://doc.rust-lang.org/std/primitive.slice.html#method.first)
1370///
1371/// # Example
1372///
1373/// ```rust
1374/// use konst::slice;
1375///
1376/// assert_eq!(slice::first(&[8, 5, 3]), Some(&8));
1377///
1378/// assert_eq!(slice::first(&[5, 3]), Some(&5));
1379///
1380/// assert_eq!(slice::first(&[3]), Some(&3));
1381///
1382/// assert_eq!(slice::first::<u8>(&[]), None);
1383///
1384/// ```
1385///
1386pub const fn first<T>(slice: &[T]) -> Option<&T> {
1387    if let [first, ..] = slice {
1388        Some(first)
1389    } else {
1390        None
1391    }
1392}
1393
1394/// A const equivalent of
1395/// [`<[T]>::first_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.first_mut)
1396///
1397/// # Example
1398///
1399/// ```rust
1400/// use konst::slice;
1401///
1402/// assert_eq!(slice::first_mut(&mut [8, 5, 3]), Some(&mut 8));
1403///
1404/// assert_eq!(slice::first_mut(&mut [5, 3]), Some(&mut 5));
1405///
1406/// assert_eq!(slice::first_mut(&mut [3]), Some(&mut 3));
1407///
1408/// assert_eq!(slice::first_mut::<u8>(&mut []), None);
1409///
1410/// ```
1411///
1412#[cfg(feature = "mut_refs")]
1413#[cfg_attr(
1414    feature = "docsrs",
1415    doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
1416)]
1417pub const fn first_mut<T>(slice: &mut [T]) -> Option<&mut T> {
1418    if let [first, ..] = slice {
1419        Some(first)
1420    } else {
1421        None
1422    }
1423}
1424
1425/// A const equivalent of
1426/// [`<[T]>::last`](https://doc.rust-lang.org/std/primitive.slice.html#method.last)
1427///
1428/// # Example
1429///
1430/// ```rust
1431/// use konst::slice;
1432///
1433/// assert_eq!(slice::last(&[3, 5, 8]), Some(&8));
1434///
1435/// assert_eq!(slice::last(&[3, 5]), Some(&5));
1436///
1437/// assert_eq!(slice::last(&[3]), Some(&3));
1438///
1439/// assert_eq!(slice::last::<u8>(&[]), None);
1440///
1441/// ```
1442///
1443pub const fn last<T>(slice: &[T]) -> Option<&T> {
1444    if let [.., last] = slice {
1445        Some(last)
1446    } else {
1447        None
1448    }
1449}
1450
1451/// A const equivalent of
1452/// [`<[T]>::last_mut`](https://doc.rust-lang.org/std/primitive.slice.html#method.last_mut)
1453///
1454/// # Example
1455///
1456/// ```rust
1457/// use konst::slice;
1458///
1459/// assert_eq!(slice::last_mut(&mut [3, 5, 8]), Some(&mut 8));
1460///
1461/// assert_eq!(slice::last_mut(&mut [3, 5]), Some(&mut 5));
1462///
1463/// assert_eq!(slice::last_mut(&mut [3]), Some(&mut 3));
1464///
1465/// assert_eq!(slice::last_mut::<u8>(&mut []), None);
1466///
1467/// ```
1468#[cfg(feature = "mut_refs")]
1469#[cfg_attr(
1470    feature = "docsrs",
1471    doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
1472)]
1473pub const fn last_mut<T>(slice: &mut [T]) -> Option<&mut T> {
1474    if let [.., last] = slice {
1475        Some(last)
1476    } else {
1477        None
1478    }
1479}
1480
1481/// A const equivalent of
1482/// [`<[T]>::split_first`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_first)
1483///
1484/// # Example
1485///
1486/// ```rust
1487/// use konst::slice;
1488///
1489/// const fn add_up(mut slice: &[u32]) -> u64 {
1490///     let mut ret = 0u64;
1491///     while let Some((first, rem)) = slice::split_first(slice) {
1492///         ret += *first as u64;
1493///
1494///         // advances the slice
1495///         slice = rem;
1496///     }
1497///     ret
1498/// }
1499///
1500/// assert_eq!(add_up(&[1]), 1);
1501/// assert_eq!(add_up(&[1, 2]), 3);
1502/// assert_eq!(add_up(&[1, 2, 3]), 6);
1503/// assert_eq!(add_up(&[1, 2, 3, 4]), 10);
1504///
1505/// ```
1506///
1507pub const fn split_first<T>(slice: &[T]) -> Option<(&T, &[T])> {
1508    if let [first, rem @ ..] = slice {
1509        Some((first, rem))
1510    } else {
1511        None
1512    }
1513}
1514
1515/// A const equivalent of
1516/// [`<[T]>::split_first_mut`
1517/// ](https://doc.rust-lang.org/std/primitive.slice.html#method.split_first_mut)
1518///
1519/// # Example
1520///
1521/// ```rust
1522/// use konst::slice;
1523///
1524/// assert_eq!(slice::split_first_mut(&mut [5, 8, 13, 21]), Some((&mut 5, &mut [8, 13, 21][..])));
1525/// assert_eq!(slice::split_first_mut(&mut [8, 13, 21]), Some((&mut 8, &mut [13, 21][..])));
1526/// assert_eq!(slice::split_first_mut(&mut [13, 21]), Some((&mut 13, &mut [21][..])));
1527/// assert_eq!(slice::split_first_mut(&mut [21]), Some((&mut 21, &mut [][..])));
1528/// assert_eq!(slice::split_first_mut::<()>(&mut []), None);
1529///
1530/// ```
1531///
1532#[cfg(feature = "mut_refs")]
1533#[cfg_attr(
1534    feature = "docsrs",
1535    doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
1536)]
1537pub const fn split_first_mut<T>(slice: &mut [T]) -> Option<(&mut T, &mut [T])> {
1538    if let [first, rem @ ..] = slice {
1539        Some((first, rem))
1540    } else {
1541        None
1542    }
1543}
1544
1545/// A const equivalent of
1546/// [`<[T]>::split_last`](https://doc.rust-lang.org/std/primitive.slice.html#method.split_last)
1547///
1548/// # Example
1549///
1550/// ```rust
1551/// use konst::slice;
1552///
1553/// const fn find_last_even(mut slice: &[u32]) -> Option<usize> {
1554///     let mut ret = 0u32;
1555///     while let Some((last, rem)) = slice::split_last(slice) {
1556///         if *last % 2 == 0 {
1557///             return Some(rem.len());
1558///         }
1559///
1560///         // advances the slice
1561///         slice = rem;
1562///     }
1563///     None
1564/// }
1565///
1566/// assert_eq!(find_last_even(&[3, 5]), None);
1567///
1568/// assert_eq!(find_last_even(&[3, 5, 8, 13, 21]), Some(2));
1569///
1570/// assert_eq!(find_last_even(&[3, 5, 8, 13, 21, 34, 55]), Some(5));
1571///
1572/// assert_eq!(find_last_even(&[3, 5, 8, 13, 21, 34, 55, 89, 144]), Some(8));
1573///
1574/// ```
1575///
1576pub const fn split_last<T>(slice: &[T]) -> Option<(&T, &[T])> {
1577    if let [rem @ .., last] = slice {
1578        Some((last, rem))
1579    } else {
1580        None
1581    }
1582}
1583
1584/// A const equivalent of
1585/// [`<[T]>::split_last_mut`
1586/// ](https://doc.rust-lang.org/std/primitive.slice.html#method.split_last_mut)
1587///
1588/// # Example
1589///
1590/// ```rust
1591/// use konst::slice;
1592///
1593/// assert_eq!(slice::split_last_mut(&mut [8, 13, 21, 5]), Some((&mut 5, &mut [8, 13, 21][..])));
1594/// assert_eq!(slice::split_last_mut(&mut [13, 21, 8]), Some((&mut 8, &mut [13, 21][..])));
1595/// assert_eq!(slice::split_last_mut(&mut [21, 13]), Some((&mut 13, &mut [21][..])));
1596/// assert_eq!(slice::split_last_mut(&mut [21]), Some((&mut 21, &mut [][..])));
1597/// assert_eq!(slice::split_last_mut::<()>(&mut []), None);
1598///
1599/// ```
1600///
1601#[cfg(feature = "mut_refs")]
1602#[cfg_attr(
1603    feature = "docsrs",
1604    doc(cfg(any(feature = "mut_refs", feature = "nightly_mut_refs")))
1605)]
1606pub const fn split_last_mut<T>(slice: &mut [T]) -> Option<(&mut T, &mut [T])> {
1607    if let [rem @ .., last] = slice {
1608        Some((last, rem))
1609    } else {
1610        None
1611    }
1612}