pub fn explode<D, S>(delimiter: D, string: S, limit: isize) -> Option<Vec<String>>
where
D: AsRef<str>,
S: AsRef<str> {
let delimiter = delimiter.as_ref();
let string = string.as_ref();
if delimiter.is_empty() {
return None;
}
if limit == 0 || limit == 1 {
return Some(vec![string.to_string()]);
}
let vec: Vec<String> = string.split(delimiter).map(String::from).collect();
let vec_length = vec.len() as isize;
if limit > vec_length {
return Some(vec);
}
if limit > 0 {
let (left, right) = vec.split_at(limit as usize - 1);
let mut vec = left.to_vec();
vec.push(right.join(delimiter));
return Some(vec);
}
if limit < 0 {
if limit <= (0 - vec_length) {
return Some(vec![]);
}
let (left, _right) = vec.split_at((vec_length + limit) as usize);
let vec = left.to_vec();
return Some(vec);
}
Some(vec)
}
pub fn implode<G>(glue: G, pieces: &Vec<String>) -> String
where
G: AsRef<str> {
pieces.join(glue.as_ref())
}
pub fn strlen<S>(string: S) -> usize
where
S: AsRef<str>
{
string.as_ref().len()
}
pub fn strpos<H, N>(haystack: H, needle: N, offset: isize) -> Option<usize>
where
H: AsRef<str>,
N: AsRef<str> {
let mut haystack = haystack.as_ref().to_string();
let needle = needle.as_ref();
let mut offset = offset;
let haystack_length = haystack.len() as isize;
if offset > 0 && offset > haystack_length {
return None;
}
if offset < 0 {
if offset < (0 - haystack_length) {
return None;
}
offset = haystack_length + offset;
}
if offset == 0 {
return haystack.find(needle);
}
haystack = haystack.chars().skip(offset as usize).collect();
match haystack.find(needle) {
None => None,
Some(position) => Some(position + offset as usize),
}
}
pub fn stripos<H, N>(haystack: H, needle: N, offset: isize) -> Option<usize>
where
H: AsRef<str>,
N: AsRef<str> {
strpos(haystack.as_ref().to_lowercase(), needle.as_ref().to_lowercase(), offset)
}
pub fn substr<S>(string: S, start: isize, length: isize) -> Option<String>
where
S: AsRef<str> {
let string = string.as_ref();
let mut start = start;
let mut length = length;
let string_length = string.len() as isize;
if start > 0 && start >= string_length {
return None;
}
if length == 0 {
return None;
}
if start < 0 {
start = string_length + start;
if start < 0 {
start = 0;
}
}
if length < 0 {
if start > string_length + length {
return None;
}
length = string_length + length - start;
}
if start == 0 && length == string_length {
return Some(string.to_string());
}
Some(string.chars().skip(start as usize).take(length as usize).collect::<String>())
}
#[cfg(test)]
mod tests {
use crate::string::*;
#[test]
fn explode_test() {
assert_eq!(explode("|", "one|two|three", 3), Some(vec!["one".to_string(), "two".to_string(), "three".to_string()]));
assert_eq!(explode("|", "one|two|three", 1), Some(vec!["one|two|three".to_string()]));
assert_eq!(explode("|", "one|two|three", 2), Some(vec!["one".to_string(), "two|three".to_string()]));
assert_eq!(explode("|", "one|two|three", -1), Some(vec!["one".to_string(), "two".to_string()]));
assert_eq!(explode("|", "one|two|three", -3), Some(vec![]));
assert_eq!(explode(",", "one|two|three", 1), Some(vec!["one|two|three".to_string()]));
assert_eq!(explode("", "one|two|three", 3), None);
}
#[test]
fn implode_test() {
assert_eq!(implode("|", &vec!["one".to_string(), "two".to_string(), "three".to_string()]), "one|two|three".to_string());
assert_eq!(implode("", &vec!["one".to_string(), "two".to_string(), "three".to_string()]), "onetwothree".to_string());
assert_eq!(implode("", &vec![]), "".to_string());
}
#[test]
fn strlen_test() {
assert_eq!(strlen("Hello World"), 11);
assert_eq!(strlen(""), 0);
}
#[test]
fn strpos_test() {
let haystack = "Hello World";
let needle = "World";
assert_eq!(strpos(haystack, needle, 0), Some(6));
assert_eq!(strpos(haystack, needle, 6), Some(6));
assert_eq!(strpos(haystack, needle, -5), Some(6));
assert_eq!(strpos(haystack, needle, -11), Some(6));
assert_eq!(strpos(haystack, needle, 7), None);
assert_eq!(strpos(haystack, needle, 11), None);
assert_eq!(strpos(haystack, needle, -12), None);
}
#[test]
fn stripos_test() {
assert_eq!(stripos("HELLO WORLD", "world", 0), Some(6));
}
#[test]
fn substr_test() {
let string = &"Hello World".to_string();
assert_eq!(substr(string, 0, 5), Some("Hello".to_string()));
assert_eq!(substr(string, 6, 5), Some("World".to_string()));
assert_eq!(substr(string, 0, 20), Some("Hello World".to_string()));
assert_eq!(substr(string, 0, -6), Some("Hello".to_string()));
assert_eq!(substr(string, 3, -3), Some("lo Wo".to_string()));
assert_eq!(substr(string, -11, 11), Some("Hello World".to_string()));
assert_eq!(substr(string, -20, 11), Some("Hello World".to_string()));
assert_eq!(substr(string, 0, 0), None);
assert_eq!(substr(string, 11, 1), None);
assert_eq!(substr(string, 7, -5), None);
}
fn bla() {
let pizza = "piece1 piece2 piece3 piece4 piece5 piece6".to_string();
let pieces = explode(&" ".to_string(), &pizza, std::isize::MAX).unwrap();
println!("### {:?}", pieces); println!("### {:?}", pizza);
assert_eq!(1, 0);
}
}