use crate::decode::{__read_marker, read_arg};
use crate::{Error, Marker, ReadBuffer, ReadBufferBorrowed};

/// Decode the length of a string from any suitable representation and the string itself.
#[inline(always)]
pub fn read_str<'de>(buf: &mut ReadBuffer<'de>) -> Result<&'de str, Error> {
    __read_str(&buf.borrow())
}

pub(crate) fn __read_str<'de>(buf: &ReadBufferBorrowed<'de>) -> Result<&'de str, Error> {
    let snapshot = buf.snapshot();
    let len = match __read_marker(buf)? {
        Marker::ImmStr { len } => len as usize,

        Marker::S8 => read_arg!(buf as u8)? as usize,
        Marker::S16 => read_arg!(buf as u16)? as usize,
        Marker::S32 => read_arg!(buf as u32)? as usize,

        _ => {
            // Undo the read_marker call.
            buf.restore(snapshot);

            return Err(Error::Unexpected);
        }
    };

    let bytes = buf.read_and_borrow(len)?;
    if !bytes.is_ascii() {
        return Err(Error::BadEncoding);
    }

    core::str::from_utf8(bytes).map_err(|_| Error::BadEncoding)
}
