use alloc::{boxed::Box, format, string::String, vec::Vec};
use core::iter::Peekable;

use serde::de::{self, Deserializer as _};

use super::{Error, Integer, Value};
use crate::core::tag;
use crate::tag::TagAccess;

impl From<Integer> for de::Unexpected<'_> {
    #[inline]
    fn from(value: Integer) -> Self {
        u64::try_from(value)
            .map(de::Unexpected::Unsigned)
            .unwrap_or_else(|_| {
                i64::try_from(value)
                    .map(de::Unexpected::Signed)
                    .unwrap_or(de::Unexpected::Other("large integer"))
            })
    }
}

impl<'a> From<&'a Value> for de::Unexpected<'a> {
    #[inline]
    fn from(value: &'a Value) -> Self {
        match value {
            Value::Bool(x) => Self::Bool(*x),
            Value::Integer(x) => Self::from(*x),
            Value::Float(x) => Self::Float(*x),
            Value::Bytes(x) => Self::Bytes(x),
            Value::Text(x) => Self::Str(x),
            Value::Array(..) => Self::Seq,
            Value::Map(..) => Self::Map,
            Value::Null => Self::Other("null"),
            Value::Tag(..) => Self::Other("tag"),
        }
    }
}

macro_rules! mkvisit {
    ($($f:ident($v:ty)),+ $(,)?) => {
        $(
            #[inline]
            fn $f<E: de::Error>(self, v: $v) -> Result<Self::Value, E> {
                Ok(v.into())
            }
        )+
    };
}

struct Visitor;

impl<'de> de::Visitor<'de> for Visitor {
    type Value = Value;

    fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "a valid CBOR item")
    }

    mkvisit! {
        visit_bool(bool),
        visit_f32(f32),
        visit_f64(f64),

        visit_i8(i8),
        visit_i16(i16),
        visit_i32(i32),
        visit_i64(i64),
        visit_i128(i128),

        visit_u8(u8),
        visit_u16(u16),
        visit_u32(u32),
        visit_u64(u64),
        visit_u128(u128),

        visit_char(char),
        visit_str(&str),
        visit_borrowed_str(&'de str),
        visit_string(String),

        visit_bytes(&[u8]),
        visit_borrowed_bytes(&'de [u8]),
        visit_byte_buf(Vec<u8>),
    }

    #[inline]
    fn visit_none<E: de::Error>(self) -> Result<Self::Value, E> {
        Ok(Value::Null)
    }

    #[inline]
    fn visit_some<D: de::Deserializer<'de>>(
        self,
        deserializer: D,
    ) -> Result<Self::Value, D::Error> {
        deserializer.deserialize_any(self)
    }

    #[inline]
    fn visit_unit<E: de::Error>(self) -> Result<Self::Value, E> {
        Ok(Value::Null)
    }

    #[inline]
    fn visit_newtype_struct<D: de::Deserializer<'de>>(
        self,
        deserializer: D,
    ) -> Result<Self::Value, D::Error> {
        deserializer.deserialize_any(self)
    }

    #[inline]
    fn visit_seq<A: de::SeqAccess<'de>>(self, mut acc: A) -> Result<Self::Value, A::Error> {
        let mut seq = Vec::new();

        while let Some(elem) = acc.next_element()? {
            seq.push(elem);
        }

        Ok(Value::Array(seq))
    }

    #[inline]
    fn visit_map<A: de::MapAccess<'de>>(self, mut acc: A) -> Result<Self::Value, A::Error> {
        let mut map = Vec::<(Value, Value)>::with_capacity(
            acc.size_hint().filter(|&l| l < 1024).unwrap_or(0),
        );

        while let Some(kv) = acc.next_entry()? {
            map.push(kv);
        }

        Ok(Value::Map(map))
    }

    // The only enum a `Value` can absorb is the internal tag protocol; see
    // the `tag` module.
    #[inline]
    fn visit_enum<A: de::EnumAccess<'de>>(self, acc: A) -> Result<Self::Value, A::Error> {
        use de::VariantAccess;

        struct Inner;

        impl<'de> de::Visitor<'de> for Inner {
            type Value = Value;

            fn expecting(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
                write!(f, "a tag number and a value")
            }

            #[inline]
            fn visit_seq<A: de::SeqAccess<'de>>(self, mut acc: A) -> Result<Self::Value, A::Error> {
                let tag: u64 = acc
                    .next_element()?
                    .ok_or_else(|| de::Error::custom("expected tag"))?;
                let val = acc
                    .next_element()?
                    .ok_or_else(|| de::Error::custom("expected value"))?;
                Ok(Value::Tag(tag, Box::new(val)))
            }
        }

        let (name, data): (String, _) = acc.variant()?;
        if name != crate::tag::TAGGED {
            return Err(de::Error::custom("expected tag"));
        }

        data.tuple_variant(2, Inner)
    }
}

impl<'de> de::Deserialize<'de> for Value {
    #[inline]
    fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
        deserializer.deserialize_any(Visitor)
    }
}

struct Deserializer<T>(T);

impl Deserializer<&Value> {
    fn integer<N>(&self, kind: &'static str) -> Result<N, Error>
    where
        N: TryFrom<u128> + TryFrom<i128>,
    {
        fn raw(value: &Value) -> Result<u128, Error> {
            let mut buffer = [0u8; 16];

            let bytes = match value {
                Value::Bytes(bytes) => {
                    // Skip leading zeros...
                    let mut bytes: &[u8] = bytes.as_ref();
                    while bytes.len() > buffer.len() && bytes[0] == 0 {
                        bytes = &bytes[1..];
                    }

                    if bytes.len() > buffer.len() {
                        return Err(de::Error::custom("bigint too large"));
                    }

                    bytes
                }

                _ => return Err(de::Error::invalid_type(value.into(), &"bytes")),
            };

            buffer[16 - bytes.len()..].copy_from_slice(bytes);
            Ok(u128::from_be_bytes(buffer))
        }

        let err = || de::Error::invalid_type(self.0.into(), &kind);

        Ok(match self.0 {
            Value::Integer(x) => i128::from(*x).try_into().map_err(|_| err())?,
            Value::Tag(t, v) if *t == tag::BIGPOS => raw(v)?.try_into().map_err(|_| err())?,
            Value::Tag(t, v) if *t == tag::BIGNEG => i128::try_from(raw(v)?)
                .map(|x| x ^ !0)
                .map_err(|_| err())
                .and_then(|x| x.try_into().map_err(|_| err()))?,
            _ => return Err(de::Error::invalid_type(self.0.into(), &"(big)int")),
        })
    }
}

impl<'de> de::Deserializer<'de> for Deserializer<&Value> {
    type Error = Error;

    #[inline]
    fn deserialize_any<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        match self.0 {
            Value::Bytes(x) => visitor.visit_bytes(x),
            Value::Text(x) => visitor.visit_str(x),
            Value::Array(x) => visitor.visit_seq(Deserializer(x.iter())),
            Value::Map(x) => visitor.visit_map(Deserializer(x.iter().peekable())),
            Value::Bool(x) => visitor.visit_bool(*x),
            Value::Null => visitor.visit_none(),

            Value::Tag(t, v) => {
                let parent: Deserializer<&Value> = Deserializer(v);
                visitor.visit_enum(TagAccess::new(parent, Some(*t)))
            }

            Value::Integer(x) => {
                if let Ok(x) = u64::try_from(*x) {
                    visitor.visit_u64(x)
                } else if let Ok(x) = i64::try_from(*x) {
                    visitor.visit_i64(x)
                } else {
                    visitor.visit_i128(i128::from(*x))
                }
            }

            Value::Float(x) => visitor.visit_f64(*x),
        }
    }

    #[inline]
    fn deserialize_bool<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        let mut value = self.0;
        while let Value::Tag(.., v) = value {
            value = v;
        }

        match value {
            Value::Bool(x) => visitor.visit_bool(*x),
            _ => Err(de::Error::invalid_type(value.into(), &"bool")),
        }
    }

    #[inline]
    fn deserialize_f32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_f64(visitor)
    }

    #[inline]
    fn deserialize_f64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        let mut value = self.0;
        while let Value::Tag(.., v) = value {
            value = v;
        }

        match value {
            Value::Float(x) => visitor.visit_f64(*x),
            _ => Err(de::Error::invalid_type(value.into(), &"f64")),
        }
    }

    fn deserialize_i8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_i8(self.integer("i8")?)
    }

    fn deserialize_i16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_i16(self.integer("i16")?)
    }

    fn deserialize_i32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_i32(self.integer("i32")?)
    }

    fn deserialize_i64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_i64(self.integer("i64")?)
    }

    fn deserialize_i128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_i128(self.integer("i128")?)
    }

    fn deserialize_u8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_u8(self.integer("u8")?)
    }

    fn deserialize_u16<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_u16(self.integer("u16")?)
    }

    fn deserialize_u32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_u32(self.integer("u32")?)
    }

    fn deserialize_u64<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_u64(self.integer("u64")?)
    }

    fn deserialize_u128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        visitor.visit_u128(self.integer("u128")?)
    }

    fn deserialize_char<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        let mut value = self.0;
        while let Value::Tag(.., v) = value {
            value = v;
        }

        if let Value::Text(x) = value {
            let mut chars = x.chars();
            if let (Some(c), None) = (chars.next(), chars.next()) {
                return visitor.visit_char(c);
            }
        }

        Err(de::Error::invalid_type(value.into(), &"char"))
    }

    fn deserialize_str<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        let mut value = self.0;
        while let Value::Tag(.., v) = value {
            value = v;
        }

        match value {
            Value::Text(x) => visitor.visit_str(x),
            _ => Err(de::Error::invalid_type(value.into(), &"str")),
        }
    }

    fn deserialize_string<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        self.deserialize_str(visitor)
    }

    fn deserialize_bytes<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        let mut value = self.0;
        while let Value::Tag(.., v) = value {
            value = v;
        }

        match value {
            Value::Bytes(x) => visitor.visit_bytes(x),
            Value::Array(x) => visitor.visit_seq(Deserializer(x.iter())),
            _ => Err(de::Error::invalid_type(value.into(), &"bytes")),
        }
    }

    fn deserialize_byte_buf<V: de::Visitor<'de>>(
        self,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        self.deserialize_bytes(visitor)
    }

    fn deserialize_seq<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        let mut value = self.0;
        while let Value::Tag(.., v) = value {
            value = v;
        }

        match value {
            Value::Array(x) => visitor.visit_seq(Deserializer(x.iter())),
            _ => Err(de::Error::invalid_type(value.into(), &"array")),
        }
    }

    fn deserialize_map<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        let mut value = self.0;
        while let Value::Tag(.., v) = value {
            value = v;
        }

        match value {
            Value::Map(x) => visitor.visit_map(Deserializer(x.iter().peekable())),
            _ => Err(de::Error::invalid_type(value.into(), &"map")),
        }
    }

    fn deserialize_struct<V: de::Visitor<'de>>(
        self,
        name: &'static str,
        _fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        let Some(marker) = crate::ser::parse_struct_marker(name) else {
            return self.deserialize_map(visitor);
        };

        let mut value = self.0;
        if let Some(tag) = marker.tag {
            let mut seen = false;
            while let Value::Tag(t, v) = value {
                seen |= *t == tag;
                value = v;
            }
            if !seen {
                return Err(de::Error::custom(format!("expected tag({tag})")));
            }
        } else {
            while let Value::Tag(.., v) = value {
                value = v;
            }
        }

        match value {
            Value::Map(x) => visitor.visit_map(StructAccess {
                iter: x.iter().peekable(),
                keys: marker.keys,
            }),
            _ => Err(de::Error::invalid_type(value.into(), &"map")),
        }
    }

    fn deserialize_tuple<V: de::Visitor<'de>>(
        self,
        _len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        self.deserialize_seq(visitor)
    }

    fn deserialize_tuple_struct<V: de::Visitor<'de>>(
        self,
        name: &'static str,
        _len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        match unwrap_struct_tag(name, self.0)? {
            Some(value) => Deserializer(value).deserialize_seq(visitor),
            None => self.deserialize_seq(visitor),
        }
    }

    fn deserialize_identifier<V: de::Visitor<'de>>(
        self,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        let mut value = self.0;
        while let Value::Tag(.., v) = value {
            value = v;
        }

        match value {
            Value::Text(x) => visitor.visit_str(x),
            // Integer keys match struct fields through the key table of a
            // marked struct (handled in `StructAccess`); in any other
            // identifier position they take a placeholder form that
            // matches no field, so they are simply unknown.
            Value::Integer(x) => visitor.visit_str(&format!(
                "{}{}",
                crate::de::INT_KEY_PLACEHOLDER,
                i128::from(*x)
            )),
            _ => Err(de::Error::invalid_type(value.into(), &"str or integer")),
        }
    }

    fn deserialize_ignored_any<V: de::Visitor<'de>>(
        self,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        self.deserialize_any(visitor)
    }

    #[inline]
    fn deserialize_option<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        match self.0 {
            Value::Null => visitor.visit_none(),
            x => visitor.visit_some(Self(x)),
        }
    }

    #[inline]
    fn deserialize_unit<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value, Self::Error> {
        match self.0 {
            Value::Null => visitor.visit_unit(),
            _ => Err(de::Error::invalid_type(self.0.into(), &"null")),
        }
    }

    #[inline]
    fn deserialize_unit_struct<V: de::Visitor<'de>>(
        self,
        name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        match unwrap_struct_tag(name, self.0)? {
            Some(value) => Deserializer(value).deserialize_unit(visitor),
            None => self.deserialize_unit(visitor),
        }
    }

    #[inline]
    fn deserialize_newtype_struct<V: de::Visitor<'de>>(
        self,
        name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        // A `RawValue` captures the `Value` re-encoded in preferred form.
        if name == crate::raw::NAME {
            let bytes = crate::to_vec(self.0).map_err(de::Error::custom)?;
            return visitor.visit_byte_buf(bytes);
        }

        match unwrap_struct_tag(name, self.0)? {
            Some(value) => visitor.visit_newtype_struct(Deserializer(value)),
            None => visitor.visit_newtype_struct(self),
        }
    }

    #[inline]
    fn deserialize_enum<V: de::Visitor<'de>>(
        self,
        name: &'static str,
        variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        if name == crate::tag::NAME {
            let (tag, val) = match self.0 {
                Value::Tag(t, v) => (Some(*t), v.as_ref()),
                v => (None, v),
            };

            let parent: Deserializer<&Value> = Deserializer(val);
            return visitor.visit_enum(TagAccess::new(parent, tag));
        }

        match self.0 {
            Value::Tag(.., v) => Deserializer(v.as_ref()).deserialize_enum(name, variants, visitor),
            Value::Map(x) if x.len() == 1 => visitor.visit_enum(KeyedEnum {
                pair: &x[0],
                keys: crate::ser::parse_struct_marker(name).map_or("", |marker| marker.keys),
            }),
            x @ Value::Text(..) => visitor.visit_enum(Deserializer(x)),
            _ => Err(de::Error::invalid_type(self.0.into(), &"map")),
        }
    }

    #[inline]
    fn is_human_readable(&self) -> bool {
        false
    }
}

impl<'a, 'de, T: Iterator<Item = &'a Value>> de::SeqAccess<'de> for Deserializer<T> {
    type Error = Error;

    #[inline]
    fn next_element_seed<U: de::DeserializeSeed<'de>>(
        &mut self,
        seed: U,
    ) -> Result<Option<U::Value>, Self::Error> {
        match self.0.next() {
            None => Ok(None),
            Some(v) => seed.deserialize(Deserializer(v)).map(Some),
        }
    }
}

impl<'a, 'de, T: Iterator<Item = &'a (Value, Value)>> de::MapAccess<'de>
    for Deserializer<Peekable<T>>
{
    type Error = Error;

    #[inline]
    fn next_key_seed<K: de::DeserializeSeed<'de>>(
        &mut self,
        seed: K,
    ) -> Result<Option<K::Value>, Self::Error> {
        match self.0.peek() {
            None => Ok(None),
            Some(x) => Ok(Some(seed.deserialize(Deserializer(&x.0))?)),
        }
    }

    #[inline]
    fn next_value_seed<V: de::DeserializeSeed<'de>>(
        &mut self,
        seed: V,
    ) -> Result<V::Value, Self::Error> {
        seed.deserialize(Deserializer(&self.0.next().unwrap().1))
    }

    #[inline]
    fn next_entry_seed<K: de::DeserializeSeed<'de>, V: de::DeserializeSeed<'de>>(
        &mut self,
        kseed: K,
        vseed: V,
    ) -> Result<Option<(K::Value, V::Value)>, Self::Error> {
        match self.0.next() {
            Some((k, v)) => Ok(Some((
                kseed.deserialize(Deserializer(k))?,
                vseed.deserialize(Deserializer(v))?,
            ))),
            None => Ok(None),
        }
    }

    #[inline]
    fn size_hint(&self) -> Option<usize> {
        match self.0.size_hint() {
            (lower, Some(upper)) if lower == upper => Some(upper),
            _ => None,
        }
    }
}

// Walks the tag layers of a marked struct's value, requiring the marker's
// tag if it declares one. Returns `None` — keep the value and the default
// handling — for unmarked structs.
fn unwrap_struct_tag<'x>(
    name: &'static str,
    mut value: &'x Value,
) -> Result<Option<&'x Value>, Error> {
    let Some(crate::ser::StructMarker { tag: Some(tag), .. }) =
        crate::ser::parse_struct_marker(name)
    else {
        return Ok(None);
    };

    let mut seen = false;
    while let Value::Tag(t, v) = value {
        seen |= *t == tag;
        value = v;
    }

    match seen {
        true => Ok(Some(value)),
        false => Err(de::Error::custom(format!("expected tag({tag})"))),
    }
}

// Map access for a marked struct: integer keys translate to field names
// through the `<field>=<key>` table of the container marker; everything
// else deserializes as usual.
struct StructAccess<'a, T: Iterator<Item = &'a (Value, Value)>> {
    iter: Peekable<T>,
    keys: &'static str,
}

impl<'a, 'de, T: Iterator<Item = &'a (Value, Value)>> de::MapAccess<'de> for StructAccess<'a, T> {
    type Error = Error;

    fn next_key_seed<K: de::DeserializeSeed<'de>>(
        &mut self,
        seed: K,
    ) -> Result<Option<K::Value>, Self::Error> {
        let Some(pair) = self.iter.peek() else {
            return Ok(None);
        };
        let pair: &'a (Value, Value) = pair;

        // Tags around a key are transparent, as in deserialize_identifier.
        let mut key = &pair.0;
        while let Value::Tag(.., v) = key {
            key = v;
        }

        let Value::Integer(x) = key else {
            return seed.deserialize(Deserializer(&pair.0)).map(Some);
        };

        let key = i128::from(*x);
        match crate::ser::field_for_key(self.keys, key) {
            Some(field) => seed
                .deserialize(de::value::StrDeserializer::new(field))
                .map(Some),
            // An unmapped integer key takes the placeholder form, so it
            // is an unknown field, exactly as in a plain struct.
            None => seed
                .deserialize(de::value::StringDeserializer::new(format!(
                    "{}{key}",
                    crate::de::INT_KEY_PLACEHOLDER
                )))
                .map(Some),
        }
    }

    #[inline]
    fn next_value_seed<V: de::DeserializeSeed<'de>>(
        &mut self,
        seed: V,
    ) -> Result<V::Value, Self::Error> {
        seed.deserialize(Deserializer(&self.iter.next().expect("peeked").1))
    }

    #[inline]
    fn size_hint(&self) -> Option<usize> {
        match self.iter.size_hint() {
            (lower, Some(upper)) if lower == upper => Some(upper),
            _ => None,
        }
    }
}

// Enum access for the single-entry map form, carrying the key table of a
// marked enum (empty otherwise) into its struct variants.
struct KeyedEnum<'a> {
    pair: &'a (Value, Value),
    keys: &'static str,
}

impl<'a, 'de> de::EnumAccess<'de> for KeyedEnum<'a> {
    type Error = Error;
    type Variant = KeyedVariant<'a>;

    #[inline]
    fn variant_seed<V: de::DeserializeSeed<'de>>(
        self,
        seed: V,
    ) -> Result<(V::Value, Self::Variant), Self::Error> {
        let key = seed.deserialize(Deserializer(&self.pair.0))?;
        Ok((
            key,
            KeyedVariant {
                value: &self.pair.1,
                keys: self.keys,
            },
        ))
    }
}

struct KeyedVariant<'a> {
    value: &'a Value,
    keys: &'static str,
}

impl<'de> de::VariantAccess<'de> for KeyedVariant<'_> {
    type Error = Error;

    #[inline]
    fn unit_variant(self) -> Result<(), Self::Error> {
        de::VariantAccess::unit_variant(Deserializer(self.value))
    }

    #[inline]
    fn newtype_variant_seed<U: de::DeserializeSeed<'de>>(
        self,
        seed: U,
    ) -> Result<U::Value, Self::Error> {
        seed.deserialize(Deserializer(self.value))
    }

    #[inline]
    fn tuple_variant<V: de::Visitor<'de>>(
        self,
        _len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        Deserializer(self.value).deserialize_seq(visitor)
    }

    #[inline]
    fn struct_variant<V: de::Visitor<'de>>(
        self,
        _fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        let mut value = self.value;
        while let Value::Tag(.., v) = value {
            value = v;
        }

        match value {
            Value::Map(x) => visitor.visit_map(StructAccess {
                iter: x.iter().peekable(),
                keys: self.keys,
            }),
            _ => Err(de::Error::invalid_type(value.into(), &"map")),
        }
    }
}

impl<'a, 'de> de::EnumAccess<'de> for Deserializer<&'a Value> {
    type Error = Error;
    type Variant = Deserializer<&'a Value>;

    #[inline]
    fn variant_seed<V: de::DeserializeSeed<'de>>(
        self,
        seed: V,
    ) -> Result<(V::Value, Self::Variant), Self::Error> {
        let key = seed.deserialize(self)?;
        Ok((key, Deserializer(&Value::Null)))
    }
}

impl<'de> de::VariantAccess<'de> for Deserializer<&Value> {
    type Error = Error;

    #[inline]
    fn unit_variant(self) -> Result<(), Self::Error> {
        match self.0 {
            Value::Null => Ok(()),
            _ => Err(de::Error::invalid_type(self.0.into(), &"unit")),
        }
    }

    #[inline]
    fn newtype_variant_seed<U: de::DeserializeSeed<'de>>(
        self,
        seed: U,
    ) -> Result<U::Value, Self::Error> {
        seed.deserialize(self)
    }

    #[inline]
    fn tuple_variant<V: de::Visitor<'de>>(
        self,
        _len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        self.deserialize_seq(visitor)
    }

    #[inline]
    fn struct_variant<V: de::Visitor<'de>>(
        self,
        _fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        self.deserialize_map(visitor)
    }
}

impl Value {
    /// Deserializes this `Value` into any `T: Deserialize`.
    ///
    /// Tags are preserved for `cbor2::tag` wrappers and skipped in typed
    /// positions where this crate's streaming deserializer also skips them.
    /// Integer map keys and struct tags use the same `#[derive(Cbor)]`
    /// marker protocol as byte-level decoding.
    ///
    /// ```rust
    /// use serde::Deserialize;
    ///
    /// #[derive(Debug, PartialEq, Deserialize)]
    /// struct Event {
    ///     level: String,
    ///     count: u64,
    /// }
    ///
    /// let value = cbor2::cbor!({ "level": "info", "count": 2 }).unwrap();
    /// let event: Event = value.deserialized().unwrap();
    /// assert_eq!(event, Event { level: "info".into(), count: 2 });
    /// ```
    #[inline]
    pub fn deserialized<'de, T: de::Deserialize<'de>>(&self) -> Result<T, Error> {
        T::deserialize(Deserializer(self))
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    // The generic map access reports an exact size hint only when the
    // underlying iterator provides one.
    #[test]
    fn size_hint_follows_the_iterator() {
        let pairs = [(Value::Null, Value::Null), (Value::Null, Value::Null)];

        let exact = Deserializer(pairs.iter().peekable());
        assert_eq!(de::MapAccess::size_hint(&exact), Some(2));

        // A filtered iterator no longer knows its exact length.
        let inexact = Deserializer(pairs.iter().filter(|_| true).peekable());
        assert_eq!(de::MapAccess::size_hint(&inexact), None);
    }
}
