From ce74c21bca2482c42193fc8503099acd409452f6 Mon Sep 17 00:00:00 2001 From: Fintan Halpenny Date: Thu, 14 Nov 2024 15:17:47 +0100 Subject: [PATCH] Improve return type of NonEmpty::split Fixes #60[^issue-60]. As pointed out in #60, splitting a `NonEmpty` that contains a single element can be ambiguous to a `NonEmpty` equivalent to `(x, [x])`. A better representation for this return type is `(&T, &[T], Option<&T>)`. [^issue-60]: https://github.com/cloudhead/nonempty/issues/60 Signed-off-by: Fintan Halpenny X-Clacks-Overhead: GNU Terry Pratchett --- src/lib.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f8b8b89..761de76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -523,7 +523,7 @@ impl NonEmpty { /// Deconstruct a `NonEmpty` into its first, last, and /// middle elements, in that order. /// - /// If there is only one element then first == last. + /// If there is only one element then last is `None`. /// /// # Example Use /// @@ -532,19 +532,20 @@ impl NonEmpty { /// /// let mut non_empty = NonEmpty::from((1, vec![2, 3, 4, 5])); /// - /// // Guaranteed to have the last element and the elements - /// // preceding it. - /// assert_eq!(non_empty.split(), (&1, &[2, 3, 4][..], &5)); + /// // When there are two or more elements, the last element is represented + /// // as a `Some`. Elements preceding it, except for the first, are returned + /// // in the middle. + /// assert_eq!(non_empty.split(), (&1, &[2, 3, 4][..], Some(&5))); /// /// let non_empty = NonEmpty::new(1); /// - /// // Guaranteed to have the last element. - /// assert_eq!(non_empty.split(), (&1, &[][..], &1)); + /// // The last element is `None` when there's only one element. + /// assert_eq!(non_empty.split(), (&1, &[][..], None)); /// ``` - pub fn split(&self) -> (&T, &[T], &T) { + pub fn split(&self) -> (&T, &[T], Option<&T>) { match self.tail.split_last() { - None => (&self.head, &[], &self.head), - Some((last, middle)) => (&self.head, middle, last), + None => (&self.head, &[], None), + Some((last, middle)) => (&self.head, middle, Some(last)), } } @@ -1286,5 +1287,16 @@ mod tests { ); Ok(()) } + + #[test] + fn test_arbitrary_with_split() -> arbitrary::Result<()> { + let mut u = Unstructured::new(&[1, 2, 3, 4, 5, 6, 7, 8]); + let ne = NonEmpty::::arbitrary(&mut u)?; + let (head, middle, last) = ne.split(); + let mut tail = middle.to_vec(); + tail.extend(last); + assert_eq!(ne, NonEmpty { head: *head, tail }); + Ok(()) + } } }