slice_group_by/
lib.rs

1//! Crate `slice-group-by` is a library for efficiently iterating on a slice by groups defined by
2//! a function that specifies if two elements are in the same group.
3//!
4//! # Example: Linear Searched Immutable Groups
5//!
6//! You will only need to define a function that returns `true` if two elements are in the same group.
7//!
8//! The `LinearGroupBy` iterator will always gives contiguous elements to the predicate function.
9//!
10//! ```rust
11//! use slice_group_by::GroupBy;
12//!
13//! let slice = &[1, 1, 1, 3, 3, 2, 2, 2];
14//!
15//! let mut iter = slice.linear_group_by_key(|x| -x);
16//!
17//! assert_eq!(iter.next(), Some(&[1, 1, 1][..]));
18//! assert_eq!(iter.next(), Some(&[3, 3][..]));
19//! assert_eq!(iter.next(), Some(&[2, 2, 2][..]));
20//! assert_eq!(iter.next(), None);
21//! ```
22//!
23//! # Example: Linear Searched Immutable Str Slices
24//!
25//! You will only need to define a function that returns `true` if two `char` are in the same group.
26//!
27//! The `LinearStrGroupBy` iterator will always gives contiguous `char` to the predicate function.
28//!
29//! ```rust
30//! use slice_group_by::StrGroupBy;
31//!
32//! let string = "aaaabbbbb饰饰cccc";
33//!
34//! let mut iter = string.linear_group_by(|a, b| a == b);
35//!
36//! assert_eq!(iter.next(), Some("aaaa"));
37//! assert_eq!(iter.next(), Some("bbbbb"));
38//! assert_eq!(iter.next(), Some("饰饰"));
39//! assert_eq!(iter.next(), Some("cccc"));
40//! assert_eq!(iter.next(), None);
41//! ```
42//!
43//! # Example: Binary Searched Mutable Groups
44//!
45//! It is also possible to get mutable non overlapping groups of a slice.
46//!
47//! The `BinaryGroupBy/Mut` and `ExponentialGroupBy/Mut` iterators will not necessarily
48//! gives contiguous elements to the predicate function. The predicate function should implement
49//! an order consistent with the sort order of the slice.
50//!
51//! ```rust
52//! use slice_group_by::GroupByMut;
53//!
54//! let slice = &mut [1, 1, 1, 2, 2, 2, 3, 3];
55//!
56//! let mut iter = slice.binary_group_by_mut(|a, b| a == b);
57//!
58//! assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
59//! assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
60//! assert_eq!(iter.next(), Some(&mut [3, 3][..]));
61//! assert_eq!(iter.next(), None);
62//! ```
63//!
64//! # Example: Exponential Searched Mutable Groups starting from the End
65//!
66//! It is also possible to get mutable non overlapping groups of a slice even starting from the end of it.
67//!
68//! ```rust
69//! use slice_group_by::GroupByMut;
70//!
71//! let slice = &mut [1, 1, 1, 2, 2, 2, 3, 3];
72//!
73//! let mut iter = slice.exponential_group_by_mut(|a, b| a == b).rev();
74//!
75//! assert_eq!(iter.next(), Some(&mut [3, 3][..]));
76//! assert_eq!(iter.next(), Some(&mut [2, 2, 2][..]));
77//! assert_eq!(iter.next(), Some(&mut [1, 1, 1][..]));
78//! assert_eq!(iter.next(), None);
79//! ```
80//!
81
82#![cfg_attr(feature = "nightly", feature(ptr_offset_from))]
83#![cfg_attr(feature = "nightly", feature(test))]
84
85#![cfg_attr(all(not(test), not(feature = "std")), no_std)]
86#[cfg(all(not(test), not(feature = "std")))]
87extern crate core as std;
88
89macro_rules! group_by_wrapped {
90    (struct $name:ident, $elem:ty) => {
91        impl<'a, T: 'a> std::iter::Iterator for $name<'a, T>
92        where T: PartialEq,
93        {
94            type Item = $elem;
95
96            fn next(&mut self) -> Option<Self::Item> {
97                self.0.next()
98            }
99
100            fn size_hint(&self) -> (usize, Option<usize>) {
101                self.0.size_hint()
102            }
103
104            fn last(self) -> Option<Self::Item> {
105                self.0.last()
106            }
107        }
108
109        impl<'a, T: 'a> DoubleEndedIterator for $name<'a, T>
110        where T: PartialEq,
111        {
112            fn next_back(&mut self) -> Option<Self::Item> {
113                self.0.next_back()
114            }
115        }
116
117        impl<'a, T: 'a> std::iter::FusedIterator for $name<'a, T>
118        where T: PartialEq,
119        { }
120    }
121}
122
123mod linear_group;
124mod binary_group;
125mod exponential_group;
126mod linear_str_group;
127
128use std::cmp::{self, Ordering};
129
130pub use self::linear_group::{
131    LinearGroupByKey,
132    LinearGroupBy,
133    LinearGroup,
134    LinearGroupByKeyMut,
135    LinearGroupByMut,
136    LinearGroupMut,
137};
138
139pub use self::binary_group::{
140    BinaryGroupByKey,
141    BinaryGroupBy,
142    BinaryGroup,
143    BinaryGroupByKeyMut,
144    BinaryGroupByMut,
145    BinaryGroupMut,
146};
147
148pub use self::exponential_group::{
149    ExponentialGroupByKey,
150    ExponentialGroupBy,
151    ExponentialGroup,
152    ExponentialGroupByKeyMut,
153    ExponentialGroupByMut,
154    ExponentialGroupMut,
155};
156
157pub use self::linear_str_group::{
158    LinearStrGroupByKey,
159    LinearStrGroupBy,
160    LinearStrGroup,
161    LinearStrGroupByKeyMut,
162    LinearStrGroupByMut,
163    LinearStrGroupMut,
164};
165
166#[cfg(feature = "nightly")]
167#[inline]
168unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
169    to.offset_from(from) as usize
170}
171
172#[cfg(not(feature = "nightly"))]
173#[inline]
174unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
175    use std::mem;
176    (to as usize - from as usize) / mem::size_of::<T>()
177}
178
179/// Exponential searches this sorted slice for a given element.
180///
181/// If the value is found then `Ok` is returned, containing the index of the matching element;
182/// if the value is not found then `Err` is returned, containing the index where a matching element
183/// could be inserted while maintaining sorted order.
184///
185/// # Examples
186///
187/// Looks up a series of four elements. The first is found, with a
188/// uniquely determined position; the second and third are not
189/// found; the fourth could match any position in `[1, 4]`.
190///
191/// ```
192/// use slice_group_by::exponential_search;
193///
194/// let s = &[0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
195///
196/// assert_eq!(exponential_search(s, &13),  Ok(9));
197/// assert_eq!(exponential_search(s, &4),   Err(7));
198/// assert_eq!(exponential_search(s, &100), Err(13));
199/// let r = exponential_search(s, &1);
200/// assert!(match r { Ok(1..=4) => true, _ => false, });
201/// ```
202#[inline]
203pub fn exponential_search<T>(slice: &[T], elem: &T) -> Result<usize, usize>
204where T: Ord
205{
206    exponential_search_by(slice, |x| x.cmp(elem))
207}
208
209/// Binary searches this sorted slice with a comparator function.
210///
211/// The comparator function should implement an order consistent with the sort order of
212/// the underlying slice, returning an order code that indicates whether its argument
213/// is `Less`, `Equal` or `Greater` the desired target.
214///
215/// If the value is found then `Ok` is returned, containing the index of the matching element;
216/// if the value is not found then `Err` is returned, containing the index where a matching element
217/// could be inserted while maintaining sorted order.
218///
219/// # Examples
220///
221/// Looks up a series of four elements. The first is found, with a
222/// uniquely determined position; the second and third are not
223/// found; the fourth could match any position in `[1, 4]`.
224///
225/// ```
226/// use slice_group_by::exponential_search_by;
227///
228/// let s = &[0, 1, 1, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55];
229///
230/// let seek = 13;
231/// assert_eq!(exponential_search_by(s, |probe| probe.cmp(&seek)), Ok(9));
232/// let seek = 4;
233/// assert_eq!(exponential_search_by(s, |probe| probe.cmp(&seek)), Err(7));
234/// let seek = 100;
235/// assert_eq!(exponential_search_by(s, |probe| probe.cmp(&seek)), Err(13));
236/// let seek = 1;
237/// let r = exponential_search_by(s, |probe| probe.cmp(&seek));
238/// assert!(match r { Ok(1..=4) => true, _ => false, });
239/// ```
240#[inline]
241pub fn exponential_search_by<T, F>(slice: &[T], mut f: F) -> Result<usize, usize>
242where F: FnMut(&T) -> Ordering,
243{
244    let mut index = 1;
245    while index < slice.len() && f(&slice[index]) == Ordering::Less {
246        index *= 2;
247    }
248
249    let half_bound = index / 2;
250    let bound = cmp::min(index + 1, slice.len());
251
252    match slice[half_bound..bound].binary_search_by(f) {
253        Ok(pos) => Ok(half_bound + pos),
254        Err(pos) => Err(half_bound + pos),
255    }
256}
257
258/// Binary searches this sorted slice with a key extraction function.
259///
260/// Assumes that the slice is sorted by the key.
261///
262/// If the value is found then `Ok` is returned, containing the index of the matching element;
263/// if the value is not found then `Err` is returned, containing the index where a matching element
264/// could be inserted while maintaining sorted order.
265///
266/// # Examples
267///
268/// Looks up a series of four elements. The first is found, with a
269/// uniquely determined position; the second and third are not
270/// found; the fourth could match any position in `[1, 4]`.
271///
272/// ```
273/// use slice_group_by::exponential_search_by_key;
274///
275/// let s = &[(0, 0), (2, 1), (4, 1), (5, 1), (3, 1),
276///           (1, 2), (2, 3), (4, 5), (5, 8), (3, 13),
277///           (1, 21), (2, 34), (4, 55)];
278///
279/// assert_eq!(exponential_search_by_key(s, &13, |&(a,b)| b),  Ok(9));
280/// assert_eq!(exponential_search_by_key(s, &4, |&(a,b)| b),   Err(7));
281/// assert_eq!(exponential_search_by_key(s, &100, |&(a,b)| b), Err(13));
282/// let r = exponential_search_by_key(s, &1, |&(a,b)| b);
283/// assert!(match r { Ok(1..=4) => true, _ => false, });
284/// ```
285#[inline]
286pub fn exponential_search_by_key<T, B, F>(slice: &[T], b: &B, mut f: F) -> Result<usize, usize>
287where F: FnMut(&T) -> B,
288      B: Ord
289{
290    exponential_search_by(slice, |k| f(k).cmp(b))
291}
292
293/// A convenient trait to construct an iterator returning non-overlapping groups
294/// defined by a predicate.
295pub trait GroupBy<T>
296{
297    /// Returns an iterator on slice groups based that will use the given function to generate keys
298    /// and determine groups based on them. It uses *linear search* to iterate over groups.
299    fn linear_group_by_key<F, K>(&self, func: F) -> LinearGroupByKey<T, F>
300    where F: FnMut(&T) -> K,
301          K: PartialEq;
302
303    /// Returns an iterator on slice groups using the *linear search* method.
304    fn linear_group_by<P>(&self, predicate: P) -> LinearGroupBy<T, P>
305    where P: FnMut(&T, &T) -> bool;
306
307    /// Returns an iterator on slice groups based on the [`PartialEq::eq`] method of `T`,
308    /// it uses *linear search* to iterate over groups.
309    ///
310    /// [`PartialEq::eq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#tymethod.eq
311    fn linear_group(&self) -> LinearGroup<T>
312    where T: PartialEq;
313
314    /// Returns an iterator on slice groups based that will use the given function to generate keys
315    /// and determine groups based on them. It uses *binary search* to iterate over groups.
316    ///
317    /// The predicate function should implement an order consistent with
318    /// the sort order of the slice.
319    fn binary_group_by_key<F, K>(&self, func: F) -> BinaryGroupByKey<T, F>
320    where F: FnMut(&T) -> K,
321          K: PartialEq;
322
323    /// Returns an iterator on slice groups using the *binary search* method.
324    ///
325    /// The predicate function should implement an order consistent with
326    /// the sort order of the slice.
327    fn binary_group_by<P>(&self, predicate: P) -> BinaryGroupBy<T, P>
328    where P: FnMut(&T, &T) -> bool;
329
330    /// Returns an iterator on slice groups based on the [`PartialEq::eq`] method of `T`,
331    /// it uses *binary search* to iterate over groups.
332    ///
333    /// The predicate function should implement an order consistent with
334    /// the sort order of the slice.
335    ///
336    /// [`PartialEq::eq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#tymethod.eq
337    fn binary_group(&self) -> BinaryGroup<T>
338    where T: PartialEq;
339
340    /// Returns an iterator on slice groups based that will use the given function to generate keys
341    /// and determine groups based on them. It uses *exponential search* to iterate over groups.
342    ///
343    /// The predicate function should implement an order consistent with
344    /// the sort order of the slice.
345    fn exponential_group_by_key<F, K>(&self, func: F) -> ExponentialGroupByKey<T, F>
346    where F: Fn(&T) -> K,
347          K: PartialEq;
348
349    /// Returns an iterator on slice groups using the *exponential search* method.
350    ///
351    /// The predicate function should implement an order consistent with
352    /// the sort order of the slice.
353    fn exponential_group_by<P>(&self, predicate: P) -> ExponentialGroupBy<T, P>
354    where P: FnMut(&T, &T) -> bool;
355
356    /// Returns an iterator on slice groups based on the [`PartialEq::eq`] method of `T`,
357    /// it uses *exponential search* to iterate over groups.
358    ///
359    /// The predicate function should implement an order consistent with
360    /// the sort order of the slice.
361    ///
362    /// [`PartialEq::eq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#tymethod.eq
363    fn exponential_group(&self) -> ExponentialGroup<T>
364    where T: PartialEq;
365}
366
367/// A convenient trait to construct an iterator returning non-overlapping *mutable*
368/// groups defined by a predicate.
369pub trait GroupByMut<T>
370{
371    /// Returns an iterator on *mutable* slice groups based that will use the given function
372    /// to generate keys and determine groups based on them. It uses *linear search*
373    /// to iterate over groups.
374    fn linear_group_by_key_mut<F, K>(&mut self, func: F) -> LinearGroupByKeyMut<T, F>
375    where F: FnMut(&T) -> K,
376          K: PartialEq;
377
378    /// Returns an iterator on *mutable* slice groups using the *linear search* method.
379    fn linear_group_by_mut<P>(&mut self, predicate: P) -> LinearGroupByMut<T, P>
380    where P: FnMut(&T, &T) -> bool;
381
382    /// Returns an iterator on *mutable* slice groups based on the [`PartialEq::eq`] method of `T`,
383    /// it uses *linear search* to iterate over groups.
384    ///
385    /// [`PartialEq::eq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#tymethod.eq
386    fn linear_group_mut(&mut self) -> LinearGroupMut<T>
387    where T: PartialEq;
388
389    /// Returns an iterator on *mutable* slice groups based that will use the given function
390    /// to generate keys and determine groups based on them. It uses *binary search*
391    /// to iterate over groups.
392    ///
393    /// The predicate function should implement an order consistent with
394    /// the sort order of the slice.
395    fn binary_group_by_key_mut<F, K>(&mut self, func: F) -> BinaryGroupByKeyMut<T, F>
396    where F: FnMut(&T) -> K,
397          K: PartialEq;
398
399    /// Returns an iterator on *mutable* slice groups using the *binary search* method.
400    ///
401    /// The predicate function should implement an order consistent with
402    /// the sort order of the slice.
403    fn binary_group_by_mut<P>(&mut self, predicate: P) -> BinaryGroupByMut<T, P>
404    where P: FnMut(&T, &T) -> bool;
405
406    /// Returns an iterator on *mutable* slice groups based on the [`PartialEq::eq`] method of `T`,
407    /// it uses *binary search* to iterate over groups.
408    ///
409    /// The predicate function should implement an order consistent with
410    /// the sort order of the slice.
411    ///
412    /// [`PartialEq::eq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#tymethod.eq
413    fn binary_group_mut(&mut self) -> BinaryGroupMut<T>
414    where T: PartialEq;
415
416    /// Returns an iterator on *mutable* slice groups based that will use the given function
417    /// to generate keys and determine groups based on them. It uses *exponential search*
418    /// to iterate over groups.
419    ///
420    /// The predicate function should implement an order consistent with
421    /// the sort order of the slice.
422    fn exponential_group_by_key_mut<F, K>(&mut self, func: F) -> ExponentialGroupByKeyMut<T, F>
423    where F: Fn(&T) -> K,
424          K: PartialEq;
425
426    /// Returns an iterator on *mutable* slice groups using the *exponential search* method.
427    ///
428    /// The predicate function should implement an order consistent with
429    /// the sort order of the slice.
430    fn exponential_group_by_mut<P>(&mut self, predicate: P) -> ExponentialGroupByMut<T, P>
431    where P: FnMut(&T, &T) -> bool;
432
433    /// Returns an iterator on *mutable* slice groups based on the [`PartialEq::eq`] method of `T`,
434    /// it uses *exponential search* to iterate over groups.
435    ///
436    /// The predicate function should implement an order consistent with
437    /// the sort order of the slice.
438    ///
439    /// [`PartialEq::eq`]: https://doc.rust-lang.org/std/cmp/trait.PartialEq.html#tymethod.eq
440    fn exponential_group_mut(&mut self) -> ExponentialGroupMut<T>
441    where T: PartialEq;
442}
443
444impl<T> GroupBy<T> for [T]
445{
446    fn linear_group_by_key<F, K>(&self, func: F) -> LinearGroupByKey<T, F>
447    where F: FnMut(&T) -> K,
448          K: PartialEq
449    {
450        LinearGroupByKey::new(self, func)
451    }
452
453    fn linear_group_by<P>(&self, predicate: P) -> LinearGroupBy<T, P>
454    where P: FnMut(&T, &T) -> bool,
455    {
456        LinearGroupBy::new(self, predicate)
457    }
458
459    fn linear_group(&self) -> LinearGroup<T>
460    where T: PartialEq,
461    {
462        LinearGroup::new(self)
463    }
464
465    fn binary_group_by_key<F, K>(&self, func: F) -> BinaryGroupByKey<T, F>
466    where F: FnMut(&T) -> K,
467          K: PartialEq
468    {
469        BinaryGroupByKey::new(self, func)
470    }
471
472    fn binary_group_by<P>(&self, predicate: P) -> BinaryGroupBy<T, P>
473    where P: FnMut(&T, &T) -> bool,
474    {
475        BinaryGroupBy::new(self, predicate)
476    }
477
478    fn binary_group(&self) -> BinaryGroup<T>
479    where T: PartialEq,
480    {
481        BinaryGroup::new(self)
482    }
483
484    fn exponential_group_by_key<F, K>(&self, func: F) -> ExponentialGroupByKey<T, F>
485    where F: Fn(&T) -> K,
486          K: PartialEq
487    {
488        ExponentialGroupByKey::new(self, func)
489    }
490
491    fn exponential_group_by<P>(&self, predicate: P) -> ExponentialGroupBy<T, P>
492    where P: FnMut(&T, &T) -> bool,
493    {
494        ExponentialGroupBy::new(self, predicate)
495    }
496
497    fn exponential_group(&self) -> ExponentialGroup<T>
498    where T: PartialEq,
499    {
500        ExponentialGroup::new(self)
501    }
502}
503
504impl<T> GroupByMut<T> for [T]
505{
506    fn linear_group_by_key_mut<F, K>(&mut self, func: F) -> LinearGroupByKeyMut<T, F>
507    where F: FnMut(&T) -> K,
508          K: PartialEq
509    {
510        LinearGroupByKeyMut::new(self, func)
511    }
512
513    fn linear_group_by_mut<P>(&mut self, predicate: P) -> LinearGroupByMut<T, P>
514    where P: FnMut(&T, &T) -> bool,
515    {
516        LinearGroupByMut::new(self, predicate)
517    }
518
519    fn linear_group_mut(&mut self) -> LinearGroupMut<T>
520    where T: PartialEq,
521    {
522        LinearGroupMut::new(self)
523    }
524
525    fn binary_group_by_key_mut<F, K>(&mut self, func: F) -> BinaryGroupByKeyMut<T, F>
526    where F: FnMut(&T) -> K,
527          K: PartialEq
528    {
529        BinaryGroupByKeyMut::new(self, func)
530    }
531
532    fn binary_group_by_mut<P>(&mut self, predicate: P) -> BinaryGroupByMut<T, P>
533    where P: FnMut(&T, &T) -> bool,
534    {
535        BinaryGroupByMut::new(self, predicate)
536    }
537
538    fn binary_group_mut(&mut self) -> BinaryGroupMut<T>
539    where T: PartialEq,
540    {
541        BinaryGroupMut::new(self)
542    }
543
544    fn exponential_group_by_key_mut<F, K>(&mut self, func: F) -> ExponentialGroupByKeyMut<T, F>
545    where F: Fn(&T) -> K,
546          K: PartialEq
547    {
548        ExponentialGroupByKeyMut::new(self, func)
549    }
550
551    fn exponential_group_by_mut<P>(&mut self, predicate: P) -> ExponentialGroupByMut<T, P>
552    where P: FnMut(&T, &T) -> bool,
553    {
554        ExponentialGroupByMut::new(self, predicate)
555    }
556
557    fn exponential_group_mut(&mut self) -> ExponentialGroupMut<T>
558    where T: PartialEq,
559    {
560        ExponentialGroupMut::new(self)
561    }
562}
563
564/// A convenient trait to construct an iterator returning non-overlapping `str` slices
565/// defined by a predicate.
566pub trait StrGroupBy
567{
568    /// Returns an iterator on `str` groups based that will use the given function
569    /// to generate keys and determine groups based on them. It uses *linear search*
570    /// to iterate over groups.
571    fn linear_group_by_key<F, K>(&self, func: F) -> LinearStrGroupByKey<F>
572    where F: FnMut(char) -> K,
573          K: PartialEq;
574
575    /// Returns an iterator on `str` groups using the *linear search* method.
576    fn linear_group_by<P>(&self, predicate: P) -> LinearStrGroupBy<P>
577    where P: FnMut(char, char) -> bool;
578
579    /// Returns an iterator on `str` groups based on the [`PartialEq::eq`] method of `char`,
580    /// it uses *linear search* to iterate over groups.
581    ///
582    /// [`PartialEq::eq`]: https://doc.rust-lang.org/std/primitive.char.html#impl-PartialEq%3Cchar%3E
583    fn linear_group(&self) -> LinearStrGroup;
584}
585
586/// A convenient trait to construct an iterator returning non-overlapping *mutable* `str` slices
587/// defined by a predicate.
588pub trait StrGroupByMut
589{
590    /// Returns an iterator on *mutable* `str` groups based that will use the given function
591    /// to generate keys and determine groups based on them. It uses *linear search*
592    /// to iterate over groups.
593    fn linear_group_by_key_mut<F, K>(&mut self, func: F) -> LinearStrGroupByKeyMut<F>
594    where F: FnMut(char) -> K,
595          K: PartialEq;
596
597    /// Returns an iterator on *mutable* `str` groups using the *linear search* method.
598    fn linear_group_by_mut<P>(&mut self, predicate: P) -> LinearStrGroupByMut<P>
599    where P: FnMut(char, char) -> bool;
600
601    /// Returns an iterator on *mutable* `str` groups based on the [`PartialEq::eq`] method of `char`,
602    /// it uses *linear search* to iterate over groups.
603    ///
604    /// [`PartialEq::eq`]: https://doc.rust-lang.org/std/primitive.char.html#impl-PartialEq%3Cchar%3E
605    fn linear_group_mut(&mut self) -> LinearStrGroupMut;
606}
607
608impl StrGroupBy for str
609{
610    fn linear_group_by_key<F, K>(&self, func: F) -> LinearStrGroupByKey<F>
611    where F: FnMut(char) -> K,
612          K: PartialEq
613    {
614        LinearStrGroupByKey::new(self, func)
615    }
616
617    fn linear_group_by<P>(&self, predicate: P) -> LinearStrGroupBy<P>
618    where P: FnMut(char, char) -> bool,
619    {
620        LinearStrGroupBy::new(self, predicate)
621    }
622
623    fn linear_group(&self) -> LinearStrGroup {
624        LinearStrGroup::new(self)
625    }
626}
627
628impl StrGroupByMut for str
629{
630    fn linear_group_by_key_mut<F, K>(&mut self, func: F) -> LinearStrGroupByKeyMut<F>
631    where F: FnMut(char) -> K,
632          K: PartialEq
633    {
634        LinearStrGroupByKeyMut::new(self, func)
635    }
636
637    fn linear_group_by_mut<P>(&mut self, predicate: P) -> LinearStrGroupByMut<P>
638    where P: FnMut(char, char) -> bool,
639    {
640        LinearStrGroupByMut::new(self, predicate)
641    }
642
643    fn linear_group_mut(&mut self) -> LinearStrGroupMut {
644        LinearStrGroupMut::new(self)
645    }
646}