#![cfg_attr(rustfmt, rustfmt_skip)]
#![cfg_attr(feature = "std", allow(deprecated))]
use core::{fmt, mem};
use core::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
use core::slice::{Iter, IterMut};
#[cfg(feature = "std")]
use std::error::Error;
#[cfg(feature = "std")]
use std::ascii::AsciiExt;
use ascii_char::AsciiChar;
#[cfg(feature = "std")]
use ascii_string::AsciiString;
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AsciiStr {
    slice: [AsciiChar],
}
impl AsciiStr {
    
    pub fn new<S: AsRef<AsciiStr> + ?Sized>(s: &S) -> &AsciiStr {
        s.as_ref()
    }
    
    #[inline]
    pub fn as_str(&self) -> &str {
        let ptr = self as *const AsciiStr as *const str;
        unsafe { &*ptr }
    }
    
    #[inline]
    pub fn as_bytes(&self) -> &[u8] {
        let ptr = self as *const AsciiStr as *const [u8];
        unsafe { &*ptr }
    }
    
    #[inline]
    pub fn as_slice(&self) -> &[AsciiChar] {
        &self.slice
    }
    
    #[inline]
    pub fn as_mut_slice(&mut self) -> &mut [AsciiChar] {
        &mut self.slice
    }
    
    
    
    
    
    #[inline]
    pub fn as_ptr(&self) -> *const AsciiChar {
        self.as_slice().as_ptr()
    }
    
    
    
    
    
    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut AsciiChar {
        self.as_mut_slice().as_mut_ptr()
    }
    
    #[cfg(feature = "std")]
    pub fn to_ascii_string(&self) -> AsciiString {
        AsciiString::from(self.slice.to_vec())
    }
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn from_ascii<B: ?Sized>(bytes: &B) -> Result<&AsciiStr, AsAsciiStrError>
    where
        B: AsRef<[u8]>,
    {
        bytes.as_ref().as_ascii_str()
    }
    
    
    
    
    
    
    
    
    
    #[inline]
    pub unsafe fn from_ascii_unchecked<B: ?Sized>(bytes: &B) -> &AsciiStr
    where
        B: AsRef<[u8]>,
    {
        bytes.as_ref().as_ascii_str_unchecked()
    }
    
    
    
    
    
    
    
    
    #[inline]
    pub fn len(&self) -> usize {
        self.slice.len()
    }
    
    
    
    
    
    
    
    
    
    
    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
    
    #[inline]
    pub fn chars(&self) -> Chars {
        self.slice.iter()
    }
    
    
    #[inline]
    pub fn chars_mut(&mut self) -> CharsMut {
        self.slice.iter_mut()
    }
    
    
    
    
    
    #[inline]
    pub fn lines(&self) -> Lines {
        Lines {
            string: self,
        }
    }
    
    
    
    
    
    
    
    
    pub fn trim(&self) -> &Self {
        self.trim_right().trim_left()
    }
    
    
    
    
    
    
    
    
    pub fn trim_left(&self) -> &Self {
        &self[self.chars().take_while(|a| a.is_whitespace()).count()..]
    }
    
    
    
    
    
    
    
    
    pub fn trim_right(&self) -> &Self {
        let trimmed = self.chars()
            .rev()
            .take_while(|a| a.is_whitespace())
            .count();
        &self[..self.len() - trimmed]
    }
    
    pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
        self.len() == other.len() &&
            self.chars().zip(other.chars()).all(|(a, b)| {
                a.eq_ignore_ascii_case(b)
            })
    }
    
    pub fn make_ascii_uppercase(&mut self) {
        for a in self.chars_mut() {
            *a = a.to_ascii_uppercase();
        }
    }
    
    pub fn make_ascii_lowercase(&mut self) {
        for a in self.chars_mut() {
            *a = a.to_ascii_lowercase();
        }
    }
    
    #[cfg(feature="std")]
    pub fn to_ascii_uppercase(&self) -> AsciiString {
        let mut ascii_string = self.to_ascii_string();
        ascii_string.make_ascii_uppercase();
        ascii_string
    }
    
    #[cfg(feature="std")]
    pub fn to_ascii_lowercase(&self) -> AsciiString {
        let mut ascii_string = self.to_ascii_string();
        ascii_string.make_ascii_lowercase();
        ascii_string
    }
}
impl PartialEq<str> for AsciiStr {
    #[inline]
    fn eq(&self, other: &str) -> bool {
        self.as_str() == other
    }
}
impl PartialEq<AsciiStr> for str {
    #[inline]
    fn eq(&self, other: &AsciiStr) -> bool {
        other.as_str() == self
    }
}
#[cfg(feature = "std")]
impl ToOwned for AsciiStr {
    type Owned = AsciiString;
    #[inline]
    fn to_owned(&self) -> AsciiString {
        self.to_ascii_string()
    }
}
impl AsRef<[u8]> for AsciiStr {
    #[inline]
    fn as_ref(&self) -> &[u8] {
        self.as_bytes()
    }
}
impl AsRef<str> for AsciiStr {
    #[inline]
    fn as_ref(&self) -> &str {
        self.as_str()
    }
}
impl AsRef<[AsciiChar]> for AsciiStr {
    #[inline]
    fn as_ref(&self) -> &[AsciiChar] {
        &self.slice
    }
}
impl AsMut<[AsciiChar]> for AsciiStr {
    #[inline]
    fn as_mut(&mut self) -> &mut [AsciiChar] {
        &mut self.slice
    }
}
impl Default for &'static AsciiStr {
    #[inline]
    fn default() -> &'static AsciiStr {
        unsafe { "".as_ascii_str_unchecked() }
    }
}
impl<'a> From<&'a [AsciiChar]> for &'a AsciiStr {
    #[inline]
    fn from(slice: &[AsciiChar]) -> &AsciiStr {
        let ptr = slice as *const [AsciiChar] as *const AsciiStr;
        unsafe { &*ptr }
    }
}
impl<'a> From<&'a mut [AsciiChar]> for &'a mut AsciiStr {
    #[inline]
    fn from(slice: &mut [AsciiChar]) -> &mut AsciiStr {
        let ptr = slice as *mut [AsciiChar] as *mut AsciiStr;
        unsafe { &mut *ptr }
    }
}
#[cfg(feature = "std")]
impl From<Box<[AsciiChar]>> for Box<AsciiStr> {
    #[inline]
    fn from(owned: Box<[AsciiChar]>) -> Box<AsciiStr> {
        let ptr = Box::into_raw(owned) as *mut AsciiStr;
        unsafe { Box::from_raw(ptr) }
    }
}
macro_rules! impl_into {
    ($wider: ty) => {
        impl<'a> From<&'a AsciiStr> for &'a$wider {
            #[inline]
            fn from(slice: &AsciiStr) -> &$wider {
                let ptr = slice as *const AsciiStr as *const $wider;
                unsafe { &*ptr }
            }
        }
        impl<'a> From<&'a mut AsciiStr> for &'a mut $wider {
            #[inline]
            fn from(slice: &mut AsciiStr) -> &mut $wider {
                let ptr = slice as *mut AsciiStr as *mut $wider;
                unsafe { &mut *ptr }
            }
        }
        #[cfg(feature = "std")]
        impl From<Box<AsciiStr>> for Box<$wider> {
            #[inline]
            fn from(owned: Box<AsciiStr>) -> Box<$wider> {
                let ptr = Box::into_raw(owned) as *mut $wider;
                unsafe { Box::from_raw(ptr) }
            }
        }
    }
}
impl_into! {[AsciiChar]}
impl_into! {[u8]}
impl_into! {str}
impl fmt::Display for AsciiStr {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(self.as_str(), f)
    }
}
impl fmt::Debug for AsciiStr {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(self.as_str(), f)
    }
}
macro_rules! impl_index {
    ($idx:ty) => {
        impl Index<$idx> for AsciiStr {
            type Output = AsciiStr;
            #[inline]
            fn index(&self, index: $idx) -> &AsciiStr {
                let ptr = &self.slice[index] as *const [AsciiChar] as *const AsciiStr;
                unsafe { &* ptr }
            }
        }
        impl IndexMut<$idx> for AsciiStr {
            #[inline]
            fn index_mut(&mut self, index: $idx) -> &mut AsciiStr {
                let ptr = &mut self.slice[index] as *mut [AsciiChar] as *mut AsciiStr;
                unsafe { &mut *ptr }
            }
        }
    }
}
impl_index! { Range<usize> }
impl_index! { RangeTo<usize> }
impl_index! { RangeFrom<usize> }
impl_index! { RangeFull }
impl Index<usize> for AsciiStr {
    type Output = AsciiChar;
    #[inline]
    fn index(&self, index: usize) -> &AsciiChar {
        unsafe { mem::transmute(&self.slice[index]) }
    }
}
impl IndexMut<usize> for AsciiStr {
    #[inline]
    fn index_mut(&mut self, index: usize) -> &mut AsciiChar {
        unsafe { mem::transmute(&mut self.slice[index]) }
    }
}
#[cfg(feature = "std")]
impl AsciiExt for AsciiStr {
    type Owned = AsciiString;
    #[inline]
    fn is_ascii(&self) -> bool {
        true
    }
    fn to_ascii_uppercase(&self) -> AsciiString {
        let mut ascii_string = self.to_ascii_string();
        ascii_string.make_ascii_uppercase();
        ascii_string
    }
    fn to_ascii_lowercase(&self) -> AsciiString {
        let mut ascii_string = self.to_ascii_string();
        ascii_string.make_ascii_lowercase();
        ascii_string
    }
    fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
        self.len() == other.len() &&
            self.chars().zip(other.chars()).all(|(a, b)| {
                a.eq_ignore_ascii_case(b)
            })
    }
    fn make_ascii_uppercase(&mut self) {
        for ascii in self.chars_mut() {
            ascii.make_ascii_uppercase();
        }
    }
    fn make_ascii_lowercase(&mut self) {
        for ascii in self.chars_mut() {
            ascii.make_ascii_lowercase();
        }
    }
}
impl<'a> IntoIterator for &'a AsciiStr {
    type Item = &'a AsciiChar;
    type IntoIter = Chars<'a>;
    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.chars()
    }
}
impl<'a> IntoIterator for &'a mut AsciiStr {
    type Item = &'a mut AsciiChar;
    type IntoIter = CharsMut<'a>;
    #[inline]
    fn into_iter(self) -> Self::IntoIter {
        self.chars_mut()
    }
}
pub type Chars<'a> = Iter<'a, AsciiChar>;
pub type CharsMut<'a> = IterMut<'a, AsciiChar>;
#[derive(Clone, Debug)]
pub struct Lines<'a> {
    string: &'a AsciiStr,
}
impl<'a> Iterator for Lines<'a> {
    type Item = &'a AsciiStr;
    fn next(&mut self) -> Option<&'a AsciiStr> {
        if self.string.is_empty() {
            return None;
        }
        if let Some(idx) = self.string
            .chars()
            .position(|&chr| chr == AsciiChar::LineFeed)
        {
            let line = if idx > 0 && self.string[idx - 1] == AsciiChar::CarriageReturn {
                &self.string[..idx - 1]
            } else {
                &self.string[..idx]
            };
            self.string = &self.string[idx + 1..];
            Some(line)
        } else {
            if !self.string.is_empty() {
                let line = self.string;
                self.string = &self.string[..0];
                Some(line)
            } else {
                None
            }
        }
    }
}
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct AsAsciiStrError(usize);
const ERRORMSG_STR: &'static str = "one or more bytes are not ASCII";
impl AsAsciiStrError {
    
    
    
    #[inline]
    pub fn valid_up_to(self) -> usize {
        self.0
    }
    #[cfg(not(feature = "std"))]
    
    #[inline]
    pub fn description(&self) -> &'static str {
        ERRORMSG_STR
    }
}
impl fmt::Display for AsAsciiStrError {
    fn fmt(&self, fmtr: &mut fmt::Formatter) -> fmt::Result {
        write!(fmtr, "the byte at index {} is not ASCII", self.0)
    }
}
#[cfg(feature = "std")]
impl Error for AsAsciiStrError {
    #[inline]
    fn description(&self) -> &'static str {
        ERRORMSG_STR
    }
}
pub trait AsAsciiStr {
    
    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr;
    
    fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError>;
}
pub trait AsMutAsciiStr {
    
    unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr;
    
    fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr, AsAsciiStrError>;
}
impl<'a, T: ?Sized> AsAsciiStr for &'a T where T: AsAsciiStr {
    #[inline]
    fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
        <T as AsAsciiStr>::as_ascii_str(*self)
    }
    #[inline]
    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
        <T as AsAsciiStr>::as_ascii_str_unchecked(*self)
    }
}
impl<'a, T: ?Sized> AsAsciiStr for &'a mut T where T: AsAsciiStr {
    #[inline]
    fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
        <T as AsAsciiStr>::as_ascii_str(*self)
    }
    #[inline]
    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
        <T as AsAsciiStr>::as_ascii_str_unchecked(*self)
    }
}
impl<'a, T: ?Sized> AsMutAsciiStr for &'a mut T where T: AsMutAsciiStr {
    #[inline]
    fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr, AsAsciiStrError> {
        <T as AsMutAsciiStr>::as_mut_ascii_str(*self)
    }
    #[inline]
    unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
        <T as AsMutAsciiStr>::as_mut_ascii_str_unchecked(*self)
    }
}
impl AsAsciiStr for AsciiStr {
    #[inline]
    fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
        Ok(self)
    }
    #[inline]
    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
        self
    }
}
impl AsMutAsciiStr for AsciiStr {
    #[inline]
    fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr, AsAsciiStrError> {
        Ok(self)
    }
    #[inline]
    unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
        self
    }
}
impl AsAsciiStr for [AsciiChar] {
    #[inline]
    fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
        Ok(self.into())
    }
    #[inline]
    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
        self.into()
    }
}
impl AsMutAsciiStr for [AsciiChar] {
    #[inline]
    fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr, AsAsciiStrError> {
        Ok(self.into())
    }
    #[inline]
    unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
        self.into()
    }
}
impl AsAsciiStr for [u8] {
    fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
        match self.iter().position(|&b| b > 127) {
            Some(index) => Err(AsAsciiStrError(index)),
            None => unsafe { Ok(self.as_ascii_str_unchecked()) },
        }
    }
    #[inline]
    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
        let ptr = self as *const [u8] as *const AsciiStr;
        &*ptr
    }
}
impl AsMutAsciiStr for [u8] {
    fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr, AsAsciiStrError> {
        match self.iter().position(|&b| b > 127) {
            Some(index) => Err(AsAsciiStrError(index)),
            None => unsafe { Ok(self.as_mut_ascii_str_unchecked()) },
        }
    }
    #[inline]
    unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
        let ptr = self as *mut [u8] as *mut AsciiStr;
        &mut *ptr
    }
}
impl AsAsciiStr for str {
    fn as_ascii_str(&self) -> Result<&AsciiStr, AsAsciiStrError> {
        self.as_bytes().as_ascii_str()
    }
    #[inline]
    unsafe fn as_ascii_str_unchecked(&self) -> &AsciiStr {
        self.as_bytes().as_ascii_str_unchecked()
    }
}
impl AsMutAsciiStr for str {
    fn as_mut_ascii_str(&mut self) -> Result<&mut AsciiStr, AsAsciiStrError> {
        match self.bytes().position(|b| b > 127) {
            Some(index) => Err(AsAsciiStrError(index)),
            None => unsafe { Ok(self.as_mut_ascii_str_unchecked()) },
        }
    }
    #[inline]
    unsafe fn as_mut_ascii_str_unchecked(&mut self) -> &mut AsciiStr {
        let ptr = self as *mut str as *mut AsciiStr;
        &mut *ptr
    }
}
#[cfg(test)]
mod tests {
    use AsciiChar;
    use super::{AsciiStr, AsAsciiStr, AsMutAsciiStr, AsAsciiStrError};
    #[test]
    fn generic_as_ascii_str() {
        fn generic<C: AsAsciiStr + ?Sized>(c: &C) -> Result<&AsciiStr, AsAsciiStrError> {
            c.as_ascii_str()
        }
        let arr = [AsciiChar::A];
        let ascii_str: &AsciiStr = arr.as_ref().into();
        assert_eq!(generic("A"), Ok(ascii_str));
        assert_eq!(generic(&b"A"[..]), Ok(ascii_str));
        assert_eq!(generic(ascii_str), Ok(ascii_str));
        assert_eq!(generic(&"A"), Ok(ascii_str));
        assert_eq!(generic(&ascii_str), Ok(ascii_str));
        assert_eq!(generic(&mut "A"), Ok(ascii_str));
    }
    #[test]
    fn generic_as_mut_ascii_str() {
        fn generic_mut<C: AsMutAsciiStr + ?Sized>(
            c: &mut C,
        ) -> Result<&mut AsciiStr, AsAsciiStrError> {
            c.as_mut_ascii_str()
        }
        let mut arr_mut = [AsciiChar::B];
        let mut ascii_str_mut: &mut AsciiStr = arr_mut.as_mut().into();
        
        let mut arr_mut_2 = [AsciiChar::B];
        let ascii_str_mut_2: &mut AsciiStr = arr_mut_2.as_mut().into();
        assert_eq!(generic_mut(&mut ascii_str_mut), Ok(&mut *ascii_str_mut_2));
        assert_eq!(generic_mut(ascii_str_mut), Ok(&mut *ascii_str_mut_2));
    }
    #[test]
    #[cfg(feature = "std")]
    fn as_ascii_str() {
        macro_rules! err {{$i:expr} => {Err(AsAsciiStrError($i))}}
        let mut s: String = "abčd".to_string();
        let mut b: Vec<u8> = s.clone().into();
        assert_eq!(s.as_str().as_ascii_str(), err!(2));
        assert_eq!(s.as_mut_str().as_mut_ascii_str(), err!(2));
        assert_eq!(b.as_slice().as_ascii_str(), err!(2));
        assert_eq!(b.as_mut_slice().as_mut_ascii_str(), err!(2));
        let mut a = [AsciiChar::a, AsciiChar::b];
        assert_eq!((&s[..2]).as_ascii_str(), Ok((&a[..]).into()));
        assert_eq!((&b[..2]).as_ascii_str(), Ok((&a[..]).into()));
        let a = Ok((&mut a[..]).into());
        assert_eq!((&mut s[..2]).as_mut_ascii_str(), a);
        assert_eq!((&mut b[..2]).as_mut_ascii_str(), a);
    }
    #[test]
    fn default() {
        let default: &'static AsciiStr = Default::default();
        assert!(default.is_empty());
    }
    #[test]
    fn as_str() {
        let b = b"( ;";
        let v = AsciiStr::from_ascii(b).unwrap();
        assert_eq!(v.as_str(), "( ;");
        assert_eq!(AsRef::<str>::as_ref(v), "( ;");
    }
    #[test]
    fn as_bytes() {
        let b = b"( ;";
        let v = AsciiStr::from_ascii(b).unwrap();
        assert_eq!(v.as_bytes(), b"( ;");
        assert_eq!(AsRef::<[u8]>::as_ref(v), b"( ;");
    }
    #[test]
    fn make_ascii_case() {
        let mut bytes = ([b'a', b'@', b'A'], [b'A', b'@', b'a']);
        let a = bytes.0.as_mut_ascii_str().unwrap();
        let b = bytes.1.as_mut_ascii_str().unwrap();
        assert!(a.eq_ignore_ascii_case(b));
        assert!(b.eq_ignore_ascii_case(a));
        a.make_ascii_lowercase();
        b.make_ascii_uppercase();
        assert_eq!(a, "a@a");
        assert_eq!(b, "A@A");
    }
    #[test]
    #[cfg(feature = "std")]
    fn to_ascii_case() {
        let bytes = ([b'a', b'@', b'A'], [b'A', b'@', b'a']);
        let a = bytes.0.as_ascii_str().unwrap();
        let b = bytes.1.as_ascii_str().unwrap();
        assert_eq!(a.to_ascii_lowercase().as_str(), "a@a");
        assert_eq!(a.to_ascii_uppercase().as_str(), "A@A");
        assert_eq!(b.to_ascii_lowercase().as_str(), "a@a");
        assert_eq!(b.to_ascii_uppercase().as_str(), "A@A");
    }
    #[test]
    #[cfg(feature = "std")]
    fn ascii_ext() {
        #[allow(deprecated)]
        use std::ascii::AsciiExt;
        assert!(AsciiExt::is_ascii(<&AsciiStr>::default()));
        let mut mutable = String::from("a@AA@a");
        let parts = mutable.split_at_mut(3);
        let a = parts.0.as_mut_ascii_str().unwrap();
        let b = parts.1.as_mut_ascii_str().unwrap();
        assert!(AsciiExt::eq_ignore_ascii_case(a, b));
        assert_eq!(AsciiExt::to_ascii_lowercase(a).as_str(), "a@a");
        assert_eq!(AsciiExt::to_ascii_uppercase(b).as_str(), "A@A");
        AsciiExt::make_ascii_uppercase(a);
        AsciiExt::make_ascii_lowercase(b);
        assert_eq!(a, "A@A");
        assert_eq!(b, "a@a");
    }
    #[test]
    fn chars_iter() {
        let chars = &[b'h', b'e', b'l', b'l', b'o', b' ', b'w', b'o', b'r', b'l', b'd', b'\0'];
        let ascii = AsciiStr::from_ascii(chars).unwrap();
        for (achar, byte) in ascii.chars().zip(chars.iter()) {
            assert_eq!(achar, byte);
        }
    }
    #[test]
    fn chars_iter_mut() {
        let chars = &mut [b'h', b'e', b'l', b'l', b'o', b' ', b'w', b'o', b'r', b'l', b'd', b'\0'];
        let ascii = chars.as_mut_ascii_str().unwrap();
        *ascii.chars_mut().next().unwrap() = AsciiChar::H;
        assert_eq!(ascii[0], b'H');
    }
    #[test]
    fn lines_iter() {
        use core::iter::Iterator;
        let lines: [&str; 4] = ["foo", "bar", "", "baz"];
        let joined = "foo\r\nbar\n\nbaz\n";
        let ascii = AsciiStr::from_ascii(joined.as_bytes()).unwrap();
        for (asciiline, line) in ascii.lines().zip(&lines) {
            assert_eq!(asciiline, *line);
        }
        let lines: [&str; 4] = ["foo", "bar", "", "baz"];
        let joined = "foo\r\nbar\n\nbaz";
        let ascii = AsciiStr::from_ascii(joined.as_bytes()).unwrap();
        for (asciiline, line) in ascii.lines().zip(&lines) {
            assert_eq!(asciiline, *line);
        }
        let trailing_line_break = b"\n";
        let ascii = AsciiStr::from_ascii(&trailing_line_break).unwrap();
        let mut line_iter = ascii.lines();
        assert_eq!(line_iter.next(), Some(AsciiStr::from_ascii("").unwrap()));
        assert_eq!(line_iter.next(), None);
        let empty_lines = b"\n\r\n\n\r\n";
        let mut iter_count = 0;
        let ascii = AsciiStr::from_ascii(&empty_lines).unwrap();
        for line in ascii.lines() {
            iter_count += 1;
            assert!(line.is_empty());
        }
        assert_eq!(4, iter_count);
    }
    #[test]
    #[cfg(feature = "std")]
    fn fmt_ascii_str() {
        let s = "abc".as_ascii_str().unwrap();
        assert_eq!(format!("{}", s), "abc".to_string());
        assert_eq!(format!("{:?}", s), "\"abc\"".to_string());
    }
}