os_str_bytes 2.3.2

Traits for converting between byte sequences and platform-native strings
Documentation
use crate::error::EncodingError;

use super::is_continuation;
use super::EncodeWide;

const SURROGATE_LENGTH: usize = 3;

fn to_wide(
    string: &[u8],
) -> impl '_ + Iterator<Item = Result<u16, EncodingError>> {
    EncodeWide::new(string.iter().map(|&x| x))
}

pub(in super::super) fn ends_with(
    string: &[u8],
    mut suffix: &[u8],
) -> Option<bool> {
    if suffix.is_empty() {
        return Some(true);
    }

    let index = string.len().checked_sub(suffix.len())?;
    if is_continuation(string[index]) {
        let index = index.checked_sub(1)?;
        let mut wide_suffix = to_wide(suffix.get(..SURROGATE_LENGTH)?);
        let suffix_wchar = wide_suffix
            .next()
            .expect("failed decoding non-empty suffix");

        if suffix_wchar.is_err()
            || wide_suffix.next().is_some()
            || suffix_wchar != to_wide(&string[index..]).nth(1)?
        {
            return None;
        }
        suffix = &suffix[SURROGATE_LENGTH..];
    }
    Some(string.ends_with(suffix))
}

pub(in super::super) fn starts_with(
    string: &[u8],
    mut prefix: &[u8],
) -> Option<bool> {
    if prefix.is_empty() {
        return Some(true);
    }

    if let Some(&byte) = string.get(prefix.len()) {
        if is_continuation(byte) {
            let index = prefix.len().checked_sub(SURROGATE_LENGTH)?;
            let mut wide_prefix = to_wide(&prefix[index..]);
            let prefix_wchar = wide_prefix
                .next()
                .expect("failed decoding non-empty prefix");

            if prefix_wchar.is_err()
                || wide_prefix.next().is_some()
                || prefix_wchar != to_wide(&string[index..]).next()?
            {
                return None;
            }
            prefix = &prefix[..index];
        }
    }
    Some(string.starts_with(prefix))
}