#![no_std]
#![doc = include_str!("README.md")]
pub fn split_first_char(text: &str) -> Option<(char, &'_ str)> {
let mut iter = text.chars();
let first = iter.next()?;
let rest = iter.as_str();
Some((first, rest))
}
mod sealed {
pub trait Sealed {}
impl<'a> Sealed for &'a str {}
}
pub trait SplitFirstChar<'a>: sealed::Sealed + Sized {
fn split_first_char(self) -> Option<(char, &'a str)>;
}
impl<'a> SplitFirstChar<'a> for &'a str {
fn split_first_char(self) -> Option<(char, &'a str)> {
split_first_char(self)
}
}
#[cfg(test)]
mod test {
use super::{split_first_char, SplitFirstChar};
use core::ops::Deref;
#[test]
fn function() {
assert_eq!(split_first_char("abc"), Some(('a', "bc")));
assert_eq!(split_first_char("x"), Some(('x', "")));
assert_eq!(split_first_char(""), None);
}
#[test]
fn method() {
assert_eq!("abc".split_first_char(), Some(('a', "bc")));
assert_eq!("x".split_first_char(), Some(('x', "")));
assert_eq!("".split_first_char(), None);
}
#[test]
fn lifetime() {
fn _use_function(text: &str) -> Option<&'_ str> {
let (_, rest) = split_first_char(text)?;
Some(rest)
}
fn _use_method(text: &str) -> Option<&'_ str> {
let (_, rest) = text.split_first_char()?;
Some(rest)
}
}
#[test]
fn deref() {
enum Input {
None,
One,
Many,
}
impl Deref for Input {
type Target = str;
fn deref(&self) -> &Self::Target {
match self {
Input::None => "",
Input::One => "x",
Input::Many => "abc",
}
}
}
assert_eq!(Input::None.split_first_char(), None);
assert_eq!(Input::One.split_first_char(), Some(('x', "")));
assert_eq!(Input::Many.split_first_char(), Some(('a', "bc")));
}
}