From a60d1444bc74e9b38242db81495d6746859d24f2 Mon Sep 17 00:00:00 2001 From: Mark Date: Fri, 1 Jun 2018 23:25:34 +0200 Subject: [PATCH] Add string slicing by character #52 --- src/mango/util/mod.rs | 2 + src/mango/util/strslice/mod.rs | 4 ++ src/mango/util/strslice/slice.rs | 64 ++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 src/mango/util/strslice/mod.rs create mode 100644 src/mango/util/strslice/slice.rs diff --git a/src/mango/util/mod.rs b/src/mango/util/mod.rs index e6c649ab..8d0156e9 100644 --- a/src/mango/util/mod.rs +++ b/src/mango/util/mod.rs @@ -2,6 +2,8 @@ pub mod collection; pub mod strtype; +pub mod strslice; + pub mod numtype; pub mod signaltype; diff --git a/src/mango/util/strslice/mod.rs b/src/mango/util/strslice/mod.rs new file mode 100644 index 00000000..5846d94a --- /dev/null +++ b/src/mango/util/strslice/mod.rs @@ -0,0 +1,4 @@ +pub mod slice; +pub use self::slice::charslice; +pub use self::slice::charslicefrom; +pub use self::slice::charsliceto; diff --git a/src/mango/util/strslice/slice.rs b/src/mango/util/strslice/slice.rs new file mode 100644 index 00000000..97bb04e7 --- /dev/null +++ b/src/mango/util/strslice/slice.rs @@ -0,0 +1,64 @@ +/// Take a character-based slice of a string (as opposed to the default byte-slice). +/// Allows negative indices to slice from the end (but start must be before end). +/// This may not be very fast. +pub fn charslice>(text: S, start: isize, end: isize) -> String { + let stext = text.into(); + let from: usize; + let length: usize; + if start < 0 { + // LATER: may remove this check and just default to 0 in the future. + assert!( + -start as usize <= stext.len(), + "charslice: if 'start' is negative, the magnitude may not exceed the length" + ); + // TODO: off by one? + from = (stext.len() as isize + start) as usize; + } else { + from = start as usize; + } + if end < 0 { + // LATER: may remove this check and just default to 0 in the future. + assert!( + -end as usize <= stext.len(), + "charslice: if 'end' is negative, the magnitude may not exceed the length" + ); + // TODO: off by one? + let new_end = (stext.len() as isize + end) as usize; + assert!( + new_end >= from, + "charslice: 'start' may not be before 'end' (end was positive)" + ); + length = new_end - from; + } else { + assert!( + end >= from as isize, + "charslice: 'start' may not be before 'end' (end was positive)" + ); + length = end as usize - from; + } + stext.chars().skip(from).take(length).collect() +} + +pub fn charslicefrom>(text: S, start: isize) -> String { + let stext = text.into(); + let len = stext.len() as isize; + charslice(stext, start, len) +} + +pub fn charsliceto>(text: S, end: isize) -> String { + charslice(text, 0, end) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_slice() { + assert_eq!(42isize as usize, 42usize); + assert_eq!("你好", charslice("你好!", 0, 2)); + assert_eq!("!", charslicefrom("你好!", 2)); + assert_eq!("你好", charsliceto("你好!", 2)); + // TODO: test negative values + } +}