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

/// Decode the length of a map from any suitable representation.
///
/// If a flexible map is decoded, this function returns [`Ok(None)`].
/// Otherwise, the decoded length is returned.
#[inline(always)]
pub fn read_map(buf: &mut ReadBuffer) -> Result<Option<usize>, Error> {
    __read_map(&buf.borrow())
}

pub(crate) fn __read_map(buf: &ReadBufferBorrowed) -> Result<Option<usize>, Error> {
    let snapshot = buf.snapshot();
    match __read_marker(buf)? {
        Marker::ImmMap { len } => Ok(Some(len as _)),

        Marker::M8 => read_arg!(buf as u8).map(|v| Some(v as _)),
        Marker::M16 => read_arg!(buf as u16).map(|v| Some(v as _)),
        Marker::M32 => read_arg!(buf as u32).map(|v| Some(v as _)),
        Marker::MFlex => Ok(None),

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

            Err(Error::Unexpected)
        }
    }
}
