//! Functions for parsing DWARF debugging abbreviations.

use alloc::collections::btree_map;
use alloc::vec::Vec;
use core::convert::TryFrom;
use core::fmt::{self, Debug};
use core::iter::FromIterator;
use core::ops::Deref;

use crate::common::{DebugAbbrevOffset, Encoding, SectionId};
use crate::constants;
use crate::endianity::Endianity;
use crate::read::{EndianSlice, Error, Reader, Result, Section, UnitHeader};

/// The `DebugAbbrev` struct represents the abbreviations describing
/// `DebuggingInformationEntry`s' attribute names and forms found in the
/// `.debug_abbrev` section.
#[derive(Debug, Default, Clone, Copy)]
pub struct DebugAbbrev<R> {
    debug_abbrev_section: R,
}

impl<'input, Endian> DebugAbbrev<EndianSlice<'input, Endian>>
where
    Endian: Endianity,
{
    /// Construct a new `DebugAbbrev` instance from the data in the `.debug_abbrev`
    /// section.
    ///
    /// It is the caller's responsibility to read the `.debug_abbrev` section and
    /// present it as a `&[u8]` slice. That means using some ELF loader on
    /// Linux, a Mach-O loader on OSX, etc.
    ///
    /// ```
    /// use gimli::{DebugAbbrev, LittleEndian};
    ///
    /// # let buf = [0x00, 0x01, 0x02, 0x03];
    /// # let read_debug_abbrev_section_somehow = || &buf;
    /// let debug_abbrev = DebugAbbrev::new(read_debug_abbrev_section_somehow(), LittleEndian);
    /// ```
    pub fn new(debug_abbrev_section: &'input [u8], endian: Endian) -> Self {
        Self::from(EndianSlice::new(debug_abbrev_section, endian))
    }
}

impl<R: Reader> DebugAbbrev<R> {
    /// Parse the abbreviations at the given `offset` within this
    /// `.debug_abbrev` section.
    ///
    /// The `offset` should generally be retrieved from a unit header.
    pub fn abbreviations(
        &self,
        debug_abbrev_offset: DebugAbbrevOffset<R::Offset>,
    ) -> Result<Abbreviations> {
        let input = &mut self.debug_abbrev_section.clone();
        input.skip(debug_abbrev_offset.0)?;
        Abbreviations::parse(input)
    }
}

impl<T> DebugAbbrev<T> {
    /// Create a `DebugAbbrev` section that references the data in `self`.
    ///
    /// This is useful when `R` implements `Reader` but `T` does not.
    ///
    /// ## Example Usage
    ///
    /// ```rust,no_run
    /// # let load_section = || unimplemented!();
    /// // Read the DWARF section into a `Vec` with whatever object loader you're using.
    /// let owned_section: gimli::DebugAbbrev<Vec<u8>> = load_section();
    /// // Create a reference to the DWARF section.
    /// let section = owned_section.borrow(|section| {
    ///     gimli::EndianSlice::new(&section, gimli::LittleEndian)
    /// });
    /// ```
    pub fn borrow<'a, F, R>(&'a self, mut borrow: F) -> DebugAbbrev<R>
    where
        F: FnMut(&'a T) -> R,
    {
        borrow(&self.debug_abbrev_section).into()
    }
}

impl<R> Section<R> for DebugAbbrev<R> {
    fn id() -> SectionId {
        SectionId::DebugAbbrev
    }

    fn reader(&self) -> &R {
        &self.debug_abbrev_section
    }
}

impl<R> From<R> for DebugAbbrev<R> {
    fn from(debug_abbrev_section: R) -> Self {
        DebugAbbrev {
            debug_abbrev_section,
        }
    }
}

/// A set of type abbreviations.
///
/// Construct an `Abbreviations` instance with the
/// [`abbreviations()`](struct.UnitHeader.html#method.abbreviations)
/// method.
#[derive(Debug, Default, Clone)]
pub struct Abbreviations {
    vec: Vec<Abbreviation>,
    map: btree_map::BTreeMap<u64, Abbreviation>,
}

impl Abbreviations {
    /// Construct a new, empty set of abbreviations.
    fn empty() -> Abbreviations {
        Abbreviations {
            vec: Vec::new(),
            map: btree_map::BTreeMap::new(),
        }
    }

    /// Insert an abbreviation into the set.
    ///
    /// Returns `Ok` if it is the first abbreviation in the set with its code,
    /// `Err` if the code is a duplicate and there already exists an
    /// abbreviation in the set with the given abbreviation's code.
    fn insert(&mut self, abbrev: Abbreviation) -> ::core::result::Result<(), ()> {
        let code_usize = abbrev.code as usize;
        if code_usize as u64 == abbrev.code {
            // Optimize for sequential abbreviation codes by storing them
            // in a Vec, as long as the map doesn't already contain them.
            // A potential further optimization would be to allow some
            // holes in the Vec, but there's no need for that yet.
            if code_usize - 1 < self.vec.len() {
                return Err(());
            } else if code_usize - 1 == self.vec.len() {
                if !self.map.is_empty() && self.map.contains_key(&abbrev.code) {
                    return Err(());
                } else {
                    self.vec.push(abbrev);
                    return Ok(());
                }
            }
        }
        match self.map.entry(abbrev.code) {
            btree_map::Entry::Occupied(_) => Err(()),
            btree_map::Entry::Vacant(entry) => {
                entry.insert(abbrev);
                Ok(())
            }
        }
    }

    /// Get the abbreviation associated with the given code.
    #[inline]
    pub fn get(&self, code: u64) -> Option<&Abbreviation> {
        if let Ok(code) = usize::try_from(code) {
            let index = code.checked_sub(1)?;
            if index < self.vec.len() {
                return Some(&self.vec[index]);
            }
        }

        self.map.get(&code)
    }

    /// Parse a series of abbreviations, terminated by a null abbreviation.
    fn parse<R: Reader>(input: &mut R) -> Result<Abbreviations> {
        let mut abbrevs = Abbreviations::empty();

        while let Some(abbrev) = Abbreviation::parse(input)? {
            if abbrevs.insert(abbrev).is_err() {
                return Err(Error::DuplicateAbbreviationCode);
            }
        }

        Ok(abbrevs)
    }
}

/// An abbreviation describes the shape of a `DebuggingInformationEntry`'s type:
/// its code, tag type, whether it has children, and its set of attributes.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Abbreviation {
    code: u64,
    tag: constants::DwTag,
    has_children: constants::DwChildren,
    attributes: Attributes,
}

impl Abbreviation {
    /// Construct a new `Abbreviation`.
    ///
    /// ### Panics
    ///
    /// Panics if `code` is `0`.
    pub(crate) fn new(
        code: u64,
        tag: constants::DwTag,
        has_children: constants::DwChildren,
        attributes: Attributes,
    ) -> Abbreviation {
        assert_ne!(code, 0);
        Abbreviation {
            code,
            tag,
            has_children,
            attributes,
        }
    }

    /// Get this abbreviation's code.
    #[inline]
    pub fn code(&self) -> u64 {
        self.code
    }

    /// Get this abbreviation's tag.
    #[inline]
    pub fn tag(&self) -> constants::DwTag {
        self.tag
    }

    /// Return true if this abbreviation's type has children, false otherwise.
    #[inline]
    pub fn has_children(&self) -> bool {
        self.has_children == constants::DW_CHILDREN_yes
    }

    /// Get this abbreviation's attributes.
    #[inline]
    pub fn attributes(&self) -> &[AttributeSpecification] {
        &self.attributes[..]
    }

    /// Parse an abbreviation's tag.
    fn parse_tag<R: Reader>(input: &mut R) -> Result<constants::DwTag> {
        let val = input.read_uleb128_u16()?;
        if val == 0 {
            Err(Error::AbbreviationTagZero)
        } else {
            Ok(constants::DwTag(val))
        }
    }

    /// Parse an abbreviation's "does the type have children?" byte.
    fn parse_has_children<R: Reader>(input: &mut R) -> Result<constants::DwChildren> {
        let val = input.read_u8()?;
        let val = constants::DwChildren(val);
        if val == constants::DW_CHILDREN_no || val == constants::DW_CHILDREN_yes {
            Ok(val)
        } else {
            Err(Error::BadHasChildren)
        }
    }

    /// Parse a series of attribute specifications, terminated by a null attribute
    /// specification.
    fn parse_attributes<R: Reader>(input: &mut R) -> Result<Attributes> {
        let mut attrs = Attributes::new();

        while let Some(attr) = AttributeSpecification::parse(input)? {
            attrs.push(attr);
        }

        Ok(attrs)
    }

    /// Parse an abbreviation. Return `None` for the null abbreviation, `Some`
    /// for an actual abbreviation.
    fn parse<R: Reader>(input: &mut R) -> Result<Option<Abbreviation>> {
        let code = input.read_uleb128()?;
        if code == 0 {
            return Ok(None);
        }

        let tag = Self::parse_tag(input)?;
        let has_children = Self::parse_has_children(input)?;
        let attributes = Self::parse_attributes(input)?;
        let abbrev = Abbreviation::new(code, tag, has_children, attributes);
        Ok(Some(abbrev))
    }
}

/// A list of attributes found in an `Abbreviation`
#[derive(Clone)]
pub(crate) enum Attributes {
    Inline {
        buf: [AttributeSpecification; MAX_ATTRIBUTES_INLINE],
        len: usize,
    },
    Heap(Vec<AttributeSpecification>),
}

// Length of 5 based on benchmark results for both x86-64 and i686.
const MAX_ATTRIBUTES_INLINE: usize = 5;

impl Attributes {
    /// Returns a new empty list of attributes
    fn new() -> Attributes {
        let default =
            AttributeSpecification::new(constants::DW_AT_null, constants::DW_FORM_null, None);
        Attributes::Inline {
            buf: [default; 5],
            len: 0,
        }
    }

    /// Pushes a new value onto this list of attributes.
    fn push(&mut self, attr: AttributeSpecification) {
        match self {
            Attributes::Heap(list) => return list.push(attr),
            Attributes::Inline {
                buf,
                len: MAX_ATTRIBUTES_INLINE,
            } => {
                let mut list = buf.to_vec();
                list.push(attr);
                *self = Attributes::Heap(list);
            }
            Attributes::Inline { buf, len } => {
                buf[*len] = attr;
                *len += 1;
            }
        }
    }
}

impl Debug for Attributes {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        (&**self).fmt(f)
    }
}

impl PartialEq for Attributes {
    fn eq(&self, other: &Attributes) -> bool {
        &**self == &**other
    }
}

impl Eq for Attributes {}

impl Deref for Attributes {
    type Target = [AttributeSpecification];
    fn deref(&self) -> &[AttributeSpecification] {
        match self {
            Attributes::Inline { buf, len } => &buf[..*len],
            Attributes::Heap(list) => list,
        }
    }
}

impl FromIterator<AttributeSpecification> for Attributes {
    fn from_iter<I>(iter: I) -> Attributes
    where
        I: IntoIterator<Item = AttributeSpecification>,
    {
        let mut list = Attributes::new();
        for item in iter {
            list.push(item);
        }
        return list;
    }
}

impl From<Vec<AttributeSpecification>> for Attributes {
    fn from(list: Vec<AttributeSpecification>) -> Attributes {
        Attributes::Heap(list)
    }
}

/// The description of an attribute in an abbreviated type. It is a pair of name
/// and form.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct AttributeSpecification {
    name: constants::DwAt,
    form: constants::DwForm,
    implicit_const_value: i64,
}

impl AttributeSpecification {
    /// Construct a new `AttributeSpecification` from the given name and form
    /// and implicit const value.
    #[inline]
    pub fn new(
        name: constants::DwAt,
        form: constants::DwForm,
        implicit_const_value: Option<i64>,
    ) -> AttributeSpecification {
        debug_assert!(
            (form == constants::DW_FORM_implicit_const && implicit_const_value.is_some())
                || (form != constants::DW_FORM_implicit_const && implicit_const_value.is_none())
        );
        AttributeSpecification {
            name,
            form,
            implicit_const_value: implicit_const_value.unwrap_or(0),
        }
    }

    /// Get the attribute's name.
    #[inline]
    pub fn name(&self) -> constants::DwAt {
        self.name
    }

    /// Get the attribute's form.
    #[inline]
    pub fn form(&self) -> constants::DwForm {
        self.form
    }

    /// Get the attribute's implicit const value.
    #[inline]
    pub fn implicit_const_value(&self) -> Option<i64> {
        if self.form == constants::DW_FORM_implicit_const {
            Some(self.implicit_const_value)
        } else {
            None
        }
    }

    /// Return the size of the attribute, in bytes.
    ///
    /// Note that because some attributes are variably sized, the size cannot
    /// always be known without parsing, in which case we return `None`.
    pub fn size<R: Reader>(&self, header: &UnitHeader<R>) -> Option<usize> {
        get_attribute_size(self.form, header.encoding()).map(usize::from)
    }

    /// Parse an attribute's form.
    fn parse_form<R: Reader>(input: &mut R) -> Result<constants::DwForm> {
        let val = input.read_uleb128_u16()?;
        if val == 0 {
            Err(Error::AttributeFormZero)
        } else {
            Ok(constants::DwForm(val))
        }
    }

    /// Parse an attribute specification. Returns `None` for the null attribute
    /// specification, `Some` for an actual attribute specification.
    fn parse<R: Reader>(input: &mut R) -> Result<Option<AttributeSpecification>> {
        let name = input.read_uleb128_u16()?;
        if name == 0 {
            // Parse the null attribute specification.
            let form = input.read_uleb128_u16()?;
            return if form == 0 {
                Ok(None)
            } else {
                Err(Error::ExpectedZero)
            };
        }

        let name = constants::DwAt(name);
        let form = Self::parse_form(input)?;
        let implicit_const_value = if form == constants::DW_FORM_implicit_const {
            Some(input.read_sleb128()?)
        } else {
            None
        };
        let spec = AttributeSpecification::new(name, form, implicit_const_value);
        Ok(Some(spec))
    }
}

#[inline]
pub(crate) fn get_attribute_size(form: constants::DwForm, encoding: Encoding) -> Option<u8> {
    match form {
        constants::DW_FORM_addr => Some(encoding.address_size),

        constants::DW_FORM_implicit_const |
        constants::DW_FORM_flag_present => Some(0),

        constants::DW_FORM_data1
        | constants::DW_FORM_flag
        | constants::DW_FORM_strx1
        | constants::DW_FORM_ref1
        | constants::DW_FORM_addrx1 => Some(1),

        constants::DW_FORM_data2
        | constants::DW_FORM_ref2
        | constants::DW_FORM_addrx2
        | constants::DW_FORM_strx2 => Some(2),

        constants::DW_FORM_addrx3 | constants::DW_FORM_strx3 => Some(3),

        constants::DW_FORM_data4
        | constants::DW_FORM_ref_sup4
        | constants::DW_FORM_ref4
        | constants::DW_FORM_strx4
        | constants::DW_FORM_addrx4 => Some(4),

        constants::DW_FORM_data8
        | constants::DW_FORM_ref8
        | constants::DW_FORM_ref_sig8
        | constants::DW_FORM_ref_sup8 => Some(8),

        constants::DW_FORM_data16  => Some(16),

        constants::DW_FORM_sec_offset
        | constants::DW_FORM_GNU_ref_alt
        | constants::DW_FORM_strp
        | constants::DW_FORM_strp_sup
        | constants::DW_FORM_GNU_strp_alt
        | constants::DW_FORM_line_strp => Some(encoding.format.word_size()),

        constants::DW_FORM_ref_addr => {
            // This is an offset, but DWARF version 2 specifies that DW_FORM_ref_addr
            // has the same size as an address on the target system.  This was changed
            // in DWARF version 3.
            Some(if encoding.version == 2 {
                encoding.address_size
            } else {
                encoding.format.word_size()
            })
        }

        // Variably sized forms.
        constants::DW_FORM_block |
        constants::DW_FORM_block1 |
        constants::DW_FORM_block2 |
        constants::DW_FORM_block4 |
        constants::DW_FORM_exprloc |
        constants::DW_FORM_ref_udata |
        constants::DW_FORM_string |
        constants::DW_FORM_sdata |
        constants::DW_FORM_udata |
        constants::DW_FORM_indirect |

        // We don't know the size of unknown forms.
        _ => None,
    }
}

#[cfg(test)]
pub mod tests {
    use super::*;
    use crate::constants;
    use crate::endianity::LittleEndian;
    use crate::read::{EndianSlice, Error};
    use crate::test_util::GimliSectionMethods;
    #[cfg(target_pointer_width = "32")]
    use core::u32;
    use test_assembler::Section;

    pub trait AbbrevSectionMethods {
        fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self;
        fn abbrev_null(self) -> Self;
        fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self;
        fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self;
        fn abbrev_attr_null(self) -> Self;
    }

    impl AbbrevSectionMethods for Section {
        fn abbrev(self, code: u64, tag: constants::DwTag, children: constants::DwChildren) -> Self {
            self.uleb(code).uleb(tag.0.into()).D8(children.0)
        }

        fn abbrev_null(self) -> Self {
            self.D8(0)
        }

        fn abbrev_attr(self, name: constants::DwAt, form: constants::DwForm) -> Self {
            self.uleb(name.0.into()).uleb(form.0.into())
        }

        fn abbrev_attr_implicit_const(self, name: constants::DwAt, value: i64) -> Self {
            self.uleb(name.0.into())
                .uleb(constants::DW_FORM_implicit_const.0.into())
                .sleb(value)
        }

        fn abbrev_attr_null(self) -> Self {
            self.D8(0).D8(0)
        }
    }

    #[test]
    fn test_debug_abbrev_ok() {
        let extra_start = [1, 2, 3, 4];
        let expected_rest = [5, 6, 7, 8];
        #[rustfmt::skip]
        let buf = Section::new()
            .append_bytes(&extra_start)
            .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
                .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
                .abbrev_attr_null()
            .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
                .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
                .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
                .abbrev_attr_null()
            .abbrev_null()
            .append_bytes(&expected_rest)
            .get_contents()
            .unwrap();

        let abbrev1 = Abbreviation::new(
            1,
            constants::DW_TAG_compile_unit,
            constants::DW_CHILDREN_yes,
            vec![
                AttributeSpecification::new(
                    constants::DW_AT_producer,
                    constants::DW_FORM_strp,
                    None,
                ),
                AttributeSpecification::new(
                    constants::DW_AT_language,
                    constants::DW_FORM_data2,
                    None,
                ),
            ]
            .into(),
        );

        let abbrev2 = Abbreviation::new(
            2,
            constants::DW_TAG_subprogram,
            constants::DW_CHILDREN_no,
            vec![AttributeSpecification::new(
                constants::DW_AT_name,
                constants::DW_FORM_string,
                None,
            )]
            .into(),
        );

        let debug_abbrev = DebugAbbrev::new(&buf, LittleEndian);
        let debug_abbrev_offset = DebugAbbrevOffset(extra_start.len());
        let abbrevs = debug_abbrev
            .abbreviations(debug_abbrev_offset)
            .expect("Should parse abbreviations");
        assert_eq!(abbrevs.get(1), Some(&abbrev1));
        assert_eq!(abbrevs.get(2), Some(&abbrev2));
    }

    #[test]
    fn test_abbreviations_insert() {
        fn abbrev(code: u16) -> Abbreviation {
            Abbreviation::new(
                code.into(),
                constants::DwTag(code),
                constants::DW_CHILDREN_no,
                vec![].into(),
            )
        }

        fn assert_abbrev(abbrevs: &Abbreviations, code: u16) {
            let abbrev = abbrevs.get(code.into()).unwrap();
            assert_eq!(abbrev.tag(), constants::DwTag(code));
        }

        // Sequential insert.
        let mut abbrevs = Abbreviations::empty();
        abbrevs.insert(abbrev(1)).unwrap();
        abbrevs.insert(abbrev(2)).unwrap();
        assert_eq!(abbrevs.vec.len(), 2);
        assert!(abbrevs.map.is_empty());
        assert_abbrev(&abbrevs, 1);
        assert_abbrev(&abbrevs, 2);

        // Out of order insert.
        let mut abbrevs = Abbreviations::empty();
        abbrevs.insert(abbrev(2)).unwrap();
        abbrevs.insert(abbrev(3)).unwrap();
        assert!(abbrevs.vec.is_empty());
        assert_abbrev(&abbrevs, 2);
        assert_abbrev(&abbrevs, 3);

        // Mixed order insert.
        let mut abbrevs = Abbreviations::empty();
        abbrevs.insert(abbrev(1)).unwrap();
        abbrevs.insert(abbrev(3)).unwrap();
        abbrevs.insert(abbrev(2)).unwrap();
        assert_eq!(abbrevs.vec.len(), 2);
        assert_abbrev(&abbrevs, 1);
        assert_abbrev(&abbrevs, 2);
        assert_abbrev(&abbrevs, 3);

        // Duplicate code in vec.
        let mut abbrevs = Abbreviations::empty();
        abbrevs.insert(abbrev(1)).unwrap();
        abbrevs.insert(abbrev(2)).unwrap();
        assert_eq!(abbrevs.insert(abbrev(1)), Err(()));
        assert_eq!(abbrevs.insert(abbrev(2)), Err(()));

        // Duplicate code in map when adding to map.
        let mut abbrevs = Abbreviations::empty();
        abbrevs.insert(abbrev(2)).unwrap();
        assert_eq!(abbrevs.insert(abbrev(2)), Err(()));

        // Duplicate code in map when adding to vec.
        let mut abbrevs = Abbreviations::empty();
        abbrevs.insert(abbrev(2)).unwrap();
        abbrevs.insert(abbrev(1)).unwrap();
        assert_eq!(abbrevs.insert(abbrev(2)), Err(()));

        // 32-bit usize conversions.
        let mut abbrevs = Abbreviations::empty();
        abbrevs.insert(abbrev(2)).unwrap();
    }

    #[test]
    #[cfg(target_pointer_width = "32")]
    fn test_abbreviations_insert_32() {
        fn abbrev(code: u64) -> Abbreviation {
            Abbreviation::new(
                code,
                constants::DwTag(code as u16),
                constants::DW_CHILDREN_no,
                vec![].into(),
            )
        }

        fn assert_abbrev(abbrevs: &Abbreviations, code: u64) {
            let abbrev = abbrevs.get(code).unwrap();
            assert_eq!(abbrev.tag(), constants::DwTag(code as u16));
        }

        let mut abbrevs = Abbreviations::empty();
        abbrevs.insert(abbrev(1)).unwrap();

        let wrap_code = (u32::MAX as u64 + 1) + 1;
        // `get` should not treat the wrapped code as `1`.
        assert_eq!(abbrevs.get(wrap_code), None);
        // `insert` should not treat the wrapped code as `1`.
        abbrevs.insert(abbrev(wrap_code)).unwrap();
        assert_abbrev(&abbrevs, 1);
        assert_abbrev(&abbrevs, wrap_code);
    }

    #[test]
    fn test_parse_abbreviations_ok() {
        let expected_rest = [1, 2, 3, 4];
        #[rustfmt::skip]
        let buf = Section::new()
            .abbrev(2, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
                .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
                .abbrev_attr_null()
            .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
                .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
                .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
                .abbrev_attr_null()
            .abbrev_null()
            .append_bytes(&expected_rest)
            .get_contents()
            .unwrap();
        let rest = &mut EndianSlice::new(&*buf, LittleEndian);

        let abbrev1 = Abbreviation::new(
            1,
            constants::DW_TAG_compile_unit,
            constants::DW_CHILDREN_yes,
            vec![
                AttributeSpecification::new(
                    constants::DW_AT_producer,
                    constants::DW_FORM_strp,
                    None,
                ),
                AttributeSpecification::new(
                    constants::DW_AT_language,
                    constants::DW_FORM_data2,
                    None,
                ),
            ]
            .into(),
        );

        let abbrev2 = Abbreviation::new(
            2,
            constants::DW_TAG_subprogram,
            constants::DW_CHILDREN_no,
            vec![AttributeSpecification::new(
                constants::DW_AT_name,
                constants::DW_FORM_string,
                None,
            )]
            .into(),
        );

        let abbrevs = Abbreviations::parse(rest).expect("Should parse abbreviations");
        assert_eq!(abbrevs.get(1), Some(&abbrev1));
        assert_eq!(abbrevs.get(2), Some(&abbrev2));
        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
    }

    #[test]
    fn test_parse_abbreviations_duplicate() {
        let expected_rest = [1, 2, 3, 4];
        #[rustfmt::skip]
        let buf = Section::new()
            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
                .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
                .abbrev_attr_null()
            .abbrev(1, constants::DW_TAG_compile_unit, constants::DW_CHILDREN_yes)
                .abbrev_attr(constants::DW_AT_producer, constants::DW_FORM_strp)
                .abbrev_attr(constants::DW_AT_language, constants::DW_FORM_data2)
                .abbrev_attr_null()
            .abbrev_null()
            .append_bytes(&expected_rest)
            .get_contents()
            .unwrap();
        let buf = &mut EndianSlice::new(&*buf, LittleEndian);

        match Abbreviations::parse(buf) {
            Err(Error::DuplicateAbbreviationCode) => {}
            otherwise => panic!("Unexpected result: {:?}", otherwise),
        };
    }

    #[test]
    fn test_parse_abbreviation_tag_ok() {
        let buf = [0x01, 0x02];
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
        let tag = Abbreviation::parse_tag(rest).expect("Should parse tag");
        assert_eq!(tag, constants::DW_TAG_array_type);
        assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian));
    }

    #[test]
    fn test_parse_abbreviation_tag_zero() {
        let buf = [0x00];
        let buf = &mut EndianSlice::new(&buf, LittleEndian);
        match Abbreviation::parse_tag(buf) {
            Err(Error::AbbreviationTagZero) => {}
            otherwise => panic!("Unexpected result: {:?}", otherwise),
        };
    }

    #[test]
    fn test_parse_abbreviation_has_children() {
        let buf = [0x00, 0x01, 0x02];
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
        let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
        assert_eq!(val, constants::DW_CHILDREN_no);
        let val = Abbreviation::parse_has_children(rest).expect("Should parse children");
        assert_eq!(val, constants::DW_CHILDREN_yes);
        match Abbreviation::parse_has_children(rest) {
            Err(Error::BadHasChildren) => {}
            otherwise => panic!("Unexpected result: {:?}", otherwise),
        };
    }

    #[test]
    fn test_parse_abbreviation_ok() {
        let expected_rest = [0x01, 0x02, 0x03, 0x04];
        let buf = Section::new()
            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
            .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_string)
            .abbrev_attr_null()
            .append_bytes(&expected_rest)
            .get_contents()
            .unwrap();
        let rest = &mut EndianSlice::new(&*buf, LittleEndian);

        let expect = Some(Abbreviation::new(
            1,
            constants::DW_TAG_subprogram,
            constants::DW_CHILDREN_no,
            vec![AttributeSpecification::new(
                constants::DW_AT_name,
                constants::DW_FORM_string,
                None,
            )]
            .into(),
        ));

        let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
        assert_eq!(abbrev, expect);
        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
    }

    #[test]
    fn test_parse_abbreviation_implicit_const_ok() {
        let expected_rest = [0x01, 0x02, 0x03, 0x04];
        let buf = Section::new()
            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
            .abbrev_attr_implicit_const(constants::DW_AT_name, -42)
            .abbrev_attr_null()
            .append_bytes(&expected_rest)
            .get_contents()
            .unwrap();
        let rest = &mut EndianSlice::new(&*buf, LittleEndian);

        let expect = Some(Abbreviation::new(
            1,
            constants::DW_TAG_subprogram,
            constants::DW_CHILDREN_no,
            vec![AttributeSpecification::new(
                constants::DW_AT_name,
                constants::DW_FORM_implicit_const,
                Some(-42),
            )]
            .into(),
        ));

        let abbrev = Abbreviation::parse(rest).expect("Should parse abbreviation");
        assert_eq!(abbrev, expect);
        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
    }

    #[test]
    fn test_parse_abbreviation_implicit_const_no_const() {
        let buf = Section::new()
            .abbrev(1, constants::DW_TAG_subprogram, constants::DW_CHILDREN_no)
            .abbrev_attr(constants::DW_AT_name, constants::DW_FORM_implicit_const)
            .get_contents()
            .unwrap();
        let buf = &mut EndianSlice::new(&*buf, LittleEndian);

        match Abbreviation::parse(buf) {
            Err(Error::UnexpectedEof(_)) => {}
            otherwise => panic!("Unexpected result: {:?}", otherwise),
        }
    }

    #[test]
    fn test_parse_null_abbreviation_ok() {
        let expected_rest = [0x01, 0x02, 0x03, 0x04];
        let buf = Section::new()
            .abbrev_null()
            .append_bytes(&expected_rest)
            .get_contents()
            .unwrap();
        let rest = &mut EndianSlice::new(&*buf, LittleEndian);

        let abbrev = Abbreviation::parse(rest).expect("Should parse null abbreviation");
        assert!(abbrev.is_none());
        assert_eq!(*rest, EndianSlice::new(&expected_rest, LittleEndian));
    }

    #[test]
    fn test_parse_attribute_form_ok() {
        let buf = [0x01, 0x02];
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
        let tag = AttributeSpecification::parse_form(rest).expect("Should parse form");
        assert_eq!(tag, constants::DW_FORM_addr);
        assert_eq!(*rest, EndianSlice::new(&buf[1..], LittleEndian));
    }

    #[test]
    fn test_parse_attribute_form_zero() {
        let buf = [0x00];
        let buf = &mut EndianSlice::new(&buf, LittleEndian);
        match AttributeSpecification::parse_form(buf) {
            Err(Error::AttributeFormZero) => {}
            otherwise => panic!("Unexpected result: {:?}", otherwise),
        };
    }

    #[test]
    fn test_parse_null_attribute_specification_ok() {
        let buf = [0x00, 0x00, 0x01];
        let rest = &mut EndianSlice::new(&buf, LittleEndian);
        let attr =
            AttributeSpecification::parse(rest).expect("Should parse null attribute specification");
        assert!(attr.is_none());
        assert_eq!(*rest, EndianSlice::new(&buf[2..], LittleEndian));
    }

    #[test]
    fn test_parse_attribute_specifications_name_zero() {
        let buf = [0x00, 0x01, 0x00, 0x00];
        let buf = &mut EndianSlice::new(&buf, LittleEndian);
        match AttributeSpecification::parse(buf) {
            Err(Error::ExpectedZero) => {}
            otherwise => panic!("Unexpected result: {:?}", otherwise),
        };
    }

    #[test]
    fn test_parse_attribute_specifications_form_zero() {
        let buf = [0x01, 0x00, 0x00, 0x00];
        let buf = &mut EndianSlice::new(&buf, LittleEndian);
        match AttributeSpecification::parse(buf) {
            Err(Error::AttributeFormZero) => {}
            otherwise => panic!("Unexpected result: {:?}", otherwise),
        };
    }

    #[test]
    fn test_get_abbrev_zero() {
        let mut abbrevs = Abbreviations::empty();
        abbrevs
            .insert(Abbreviation::new(
                1,
                constants::DwTag(1),
                constants::DW_CHILDREN_no,
                vec![].into(),
            ))
            .unwrap();
        assert!(abbrevs.get(0).is_none());
    }
}
