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}