// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! The module contains the structures that get serialized and written to image file.
//! Some of these structures are visible to users of the library when they want to
//! query the state.
//!
//! On disk layout of image file looks something like the picture below.
//! +-------------------------+
//! | Header                  |
//! +-------------------------+
//! | ExtentCluster           |
//! | +---------------------+ |
//! | | ExtentClusterHeader | |
//! | +---------------------+ |
//! | | ExtentInfo []       | |
//! | +---------------------+ |
//! | | Extent Data []      | |
//! | +---------------------+ |
//! +-------------------------+
//! | More ExtentClusters..   |
//! +-------------------------+
//! # Header
//! Header describes the layout of the image file
//!  * alignment requirements
//!  * location of first extent cluster
//!  * other options like checksum and etc
//!
//! ExtentClusterHeader
//! A Extent cluster describes and holds a set of extents, their properties and
//! their data. In addition, cluster header may also point to next extent
//! cluster.
use {
    crate::{
        error::Error,
        extent::Extent,
        properties::{DataKind, ExtentKind, DEFAULT_ALIGNMENT},
        utils::ReadAndSeek,
    },
    bitfield::bitfield,
    crc,
    std::{convert::TryFrom, io::Write},
    zerocopy::{AsBytes, FromBytes, LayoutVerified},
};

const HEADER_MAGIC1: u64 = 0xe3761f4bd6343e64u64;
const HEADER_MAGIC2: u64 = 0x8aa02bf59a6f7bc5u64;
const HEADER_VERSION: u64 = 1;
const EXTENT_CLUSTER_HEADER_MAGIC1: u64 = 0x8ecc1d9bcdb27dfbu64;
const EXTENT_CLUSTER_HEADER_MAGIC2: u64 = 0x451681f35b024d65u64;

/// `Header` describes the layout and state of the extracted image file.
///
/// Typically header is found at offset 0 within the image file.
#[repr(C)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, FromBytes, AsBytes)]
pub struct Header {
    // Magic number to identify the content as extracted image.
    magic1: u64,

    // Magic number to identify the content as extracted image.
    magic2: u64,

    // Version of the extracted image.
    version: u64,

    // Points to offset within the image file where first extent cluster can be found.
    extent_cluster_offset: u64,

    // Image metadata and data is aligned to this number.
    pub(crate) alignment: u64,

    // crc32 of the structure. This includes crc of padding that gets added when
    // alignment is >1.
    crc32: u32,

    _padding: u32,
}

impl Default for Header {
    fn default() -> Self {
        Header::new(DEFAULT_ALIGNMENT)
    }
}

impl Header {
    pub fn new(alignment: u64) -> Header {
        Header {
            magic1: HEADER_MAGIC1,
            magic2: HEADER_MAGIC2,
            version: HEADER_VERSION,
            extent_cluster_offset: alignment as u64,
            alignment,
            crc32: 0,
            _padding: 0,
        }
    }

    /// Returns size of serialized header considering alignement.
    pub fn serialized_size(&self) -> u64 {
        assert_ne!(self.alignment, 0);
        ((self.as_bytes().len() as u64 + self.alignment - 1) / self.alignment) * self.alignment
    }

    /// Checks offset of extent cluster.
    pub fn check_extent_cluster_offset(&self, offset: u64) -> Result<(), Error> {
        if offset < self.serialized_size() {
            return Err(Error::InvalidOffset);
        }

        if offset % self.alignment != 0 {
            return Err(Error::InvalidOffset);
        }

        Ok(())
    }

    /// Updates extent cluster offset.
    pub fn set_extent_cluster_offset(&mut self, offset: u64) -> Result<(), Error> {
        self.check_extent_cluster_offset(offset)?;
        self.extent_cluster_offset = offset;
        Ok(())
    }

    /// Returns current extent cluster offset.
    pub fn get_extent_cluster_offset(&self) -> u64 {
        self.extent_cluster_offset
    }

    /// Serializes header to out. Computes and updates header crc.
    pub fn serialize_to(&mut self, out: &mut dyn Write) -> Result<u64, Error> {
        self.check_extent_cluster_offset(self.extent_cluster_offset)?;
        self.crc32 = 0;
        let crc32 = crc::crc32::update(0, &crc::crc32::IEEE_TABLE, self.as_bytes());
        let buffer = vec![0; self.serialized_size() as usize - self.as_bytes().len()];
        self.crc32 = crc::crc32::update(crc32, &crc::crc32::IEEE_TABLE, self.as_bytes());

        out.write_all(&self.as_bytes()).map_err(move |_| Error::WriteFailed)?;
        out.write_all(&buffer).map_err(move |_| Error::WriteFailed)?;
        Ok(self.serialized_size())
    }

    pub fn deserialize_from(in_stream: &mut dyn ReadAndSeek) -> Result<Self, Error> {
        let mut buffer = vec![0; std::mem::size_of::<Self>()];
        in_stream.read_exact(&mut buffer).map_err(move |_| Error::ReadFailed)?;
        let c_extent_or = LayoutVerified::<&[u8], Self>::new_from_prefix(&buffer);
        if c_extent_or.is_none() {
            return Err(Error::ReadFailed);
        }
        let (e, _) = c_extent_or.unwrap();
        Ok(e.clone())
    }

    #[cfg(test)]
    pub fn test_check(&self) -> bool {
        // TODO(auradkar) : check crc.
        self.magic1 == HEADER_MAGIC1
            && self.magic2 == HEADER_MAGIC2
            && self.version == HEADER_VERSION
            && self.alignment != 0
    }
}

pub const EXTENT_KIND_UNMAPPED: u8 = 0;
pub const EXTENT_KIND_UNUSED: u8 = 1;
pub const EXTENT_KIND_DATA: u8 = 2;
pub const EXTENT_KIND_PII: u8 = 3;

bitfield! {
#[repr(C)]
#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Debug, FromBytes, AsBytes)]
/// ExtentKind describes the type of the extent.
///
/// ExtentKind may mean different things based on the storage software.
/// ExtentKind priority is Unmapped<Unused<Data<Pii.
pub struct ExtentKindInfo(u8);
u8, kind, set_kind: 1, 0;
}

impl ExtentKindInfo {
    pub fn new(ekind: ExtentKind) -> Self {
        Self::from(ekind)
    }

    pub fn to_kind(&self) -> Result<ExtentKind, Error> {
        match self.kind() {
            EXTENT_KIND_UNMAPPED => Ok(ExtentKind::Unmmapped),
            EXTENT_KIND_UNUSED => Ok(ExtentKind::Unused),
            EXTENT_KIND_DATA => Ok(ExtentKind::Data),
            EXTENT_KIND_PII => Ok(ExtentKind::Pii),
            _ => Err(Error::ParseFailed),
        }
    }

    pub fn check(&self) -> Result<(), Error> {
        if self.0 > EXTENT_KIND_PII {
            return Err(Error::ParseFailed);
        }
        Ok(())
    }
}

impl TryFrom<u8> for ExtentKindInfo {
    type Error = Error;
    fn try_from(value: u8) -> Result<Self, Error> {
        if value > 3 {
            return Err(Error::InvalidArgument);
        }
        let mut skind: ExtentKindInfo = Default::default();
        skind.set_kind(value);
        Ok(skind)
    }
}

impl From<ExtentKind> for ExtentKindInfo {
    fn from(kind: ExtentKind) -> ExtentKindInfo {
        let mut info: ExtentKindInfo = Default::default();
        info.set_kind(match kind {
            ExtentKind::Unmmapped => EXTENT_KIND_UNMAPPED,
            ExtentKind::Unused => EXTENT_KIND_UNUSED,
            ExtentKind::Data => EXTENT_KIND_DATA,
            ExtentKind::Pii => EXTENT_KIND_PII,
        });
        info
    }
}

const DATA_KIND_SKIPPED: u8 = 0;
const DATA_KIND_ZEROES: u8 = 1;
const DATA_KIND_UNMODIFIED: u8 = 2;
const DATA_KIND_MODIFIED: u8 = 3;

bitfield! {
/// DataKind describes the type of the data within an extent.
/// DataKind priority is Skipped<Zeroes<Unmodified<Modified.
#[repr(C)]
#[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Debug, FromBytes, AsBytes)]
pub struct DataKindInfo(u8);
pub u8, kind, set_kind: 1, 0;
}

impl DataKindInfo {
    pub fn new(kind: DataKind) -> Self {
        Self::from(kind)
    }

    pub fn to_kind(&self) -> Result<DataKind, Error> {
        match self.kind() {
            DATA_KIND_SKIPPED => Ok(DataKind::Skipped),
            DATA_KIND_ZEROES => Ok(DataKind::Zeroes),
            DATA_KIND_UNMODIFIED => Ok(DataKind::Unmodified),
            DATA_KIND_MODIFIED => Ok(DataKind::Modified),
            _ => Err(Error::ParseFailed),
        }
    }

    pub fn check(&self) -> Result<(), Error> {
        if self.0 > DATA_KIND_MODIFIED {
            return Err(Error::ParseFailed);
        }
        Ok(())
    }
}

impl TryFrom<u8> for DataKindInfo {
    type Error = Error;
    fn try_from(value: u8) -> Result<Self, Error> {
        if value > 3 {
            return Err(Error::InvalidArgument);
        }
        let mut dkind: DataKindInfo = Default::default();
        dkind.set_kind(value);
        Ok(dkind)
    }
}

impl From<DataKind> for DataKindInfo {
    fn from(kind: DataKind) -> DataKindInfo {
        let mut dkind: Self = Default::default();
        dkind.set_kind(match kind {
            DataKind::Skipped => DATA_KIND_SKIPPED,
            DataKind::Zeroes => DATA_KIND_ZEROES,
            DataKind::Unmodified => DATA_KIND_UNMODIFIED,
            DataKind::Modified => DATA_KIND_MODIFIED,
        });
        dkind
    }
}

/// Serializable extent info
#[repr(C)]
#[derive(Debug, Clone, AsBytes, FromBytes)]
pub struct ExtentInfo {
    /// Start offset, in bytes, where this extent maps into the disk.
    /// This is not an offset within the image file.
    pub start: u64,

    /// End offset, in bytes, where this extent maps into the disk.
    /// This is not an offset within the image file.
    pub end: u64,

    /// ExtentKind describes the type of the extent.
    ///
    /// ExtentKind may mean different things based on the storage software.
    /// ExtentKind priority is Unmapped<Unused<Data<Pii.
    /// See [`ExtentKind`]
    pub extent: ExtentKindInfo,

    /// DataKind describes the type of the data within an extent.
    /// DataKind priority is Skipped<Zeroes<Unmodified<Modified.
    /// See [`DataKind`]
    pub data: DataKindInfo,

    // Make zerocopy happy. zerocopy expects packed, aligned structure.
    _padding: [u8; 6],
}

impl From<Extent> for ExtentInfo {
    fn from(extent: Extent) -> Self {
        ExtentInfo {
            start: extent.storage_range().start,
            end: extent.storage_range().end,
            extent: ExtentKindInfo::new(extent.properties().extent_kind),
            data: DataKindInfo::new(extent.properties().data_kind),
            _padding: [0; 6],
        }
    }
}

impl ExtentInfo {
    pub fn check(&self) -> Result<(), Error> {
        if self.start >= self.end {
            return Err(Error::ParseFailed);
        }
        self.data.check()?;
        self.extent.check()?;

        Ok(())
    }

    pub fn serialized_size(&self) -> u64 {
        self.as_bytes().len() as u64
    }

    /// Serializes extent cluster to out.
    pub fn serialize_to(&self, out: &mut dyn Write) -> Result<u64, Error> {
        out.write_all(&self.as_bytes()).map_err(move |_| Error::WriteFailed)?;
        Ok(self.as_bytes().len() as u64)
    }

    pub fn deserialize_from(in_stream: &mut dyn ReadAndSeek) -> Result<Self, Error> {
        let mut buffer = vec![0; std::mem::size_of::<Self>()];
        in_stream.read_exact(&mut buffer).map_err(move |_| Error::ReadFailed)?;
        let c_extent_or = LayoutVerified::<&[u8], Self>::new_from_prefix(&buffer);
        if c_extent_or.is_none() {
            return Err(Error::ReadFailed);
        }
        let (e, _) = c_extent_or.unwrap();
        Ok(e.clone())
    }
}

#[repr(C)]
#[derive(Debug, PartialEq, Eq, Copy, Clone, AsBytes, FromBytes)]
pub struct ExtentClusterHeader {
    // Magic number to identify the content as extracted image.
    magic1: u64,

    // Magic number to identify the content as extracted image.
    magic2: u64,

    // Number of extents in this extent cluster.
    extent_count: u64,

    // Points to next extent cluster. 0 indiates no more extent clusters.
    // This is offset relative to beginning of the image.
    next_cluster_offset: u64,

    // If cluster has footer, then this is where it can be found.
    // 0 indiates no footer.
    footer_offset: u64,

    // crc of the extent cluster and all the extents in this cluster.
    // The padding, if any, needs to be zeroed.
    crc32: u32,

    // Explicit padding.
    _padding: u32,
}

impl ExtentClusterHeader {
    fn new(extent_count: u64, next_cluster_offset: u64) -> ExtentClusterHeader {
        let mut e = ExtentClusterHeader {
            magic1: EXTENT_CLUSTER_HEADER_MAGIC1,
            magic2: EXTENT_CLUSTER_HEADER_MAGIC2,
            extent_count,
            next_cluster_offset,
            crc32: 0,
            footer_offset: 0,
            _padding: 0,
        };
        e.crc32 = crc::crc32::checksum_ieee(e.as_bytes());
        e
    }

    pub fn serialized_size(&self) -> u64 {
        self.as_bytes().len() as u64
    }

    /// Serializes extent cluster to out.
    pub fn serialize_to(
        extent_count: u64,
        next_cluster_offset: u64,
        out: &mut dyn Write,
    ) -> Result<u64, Error> {
        let cluster = Self::new(extent_count, next_cluster_offset);
        out.write_all(&cluster.as_bytes()).map_err(move |_| Error::WriteFailed)?;
        Ok(cluster.as_bytes().len() as u64)
    }

    pub fn deserialize_from(in_stream: &mut dyn ReadAndSeek) -> Result<Self, Error> {
        let mut buffer = vec![0; std::mem::size_of::<Self>()];
        in_stream.read_exact(&mut buffer).map_err(move |_| Error::ReadFailed)?;
        let c_extent_or = LayoutVerified::<&[u8], Self>::new_from_prefix(&buffer);
        if c_extent_or.is_none() {
            return Err(Error::ReadFailed);
        }
        let (e, _) = c_extent_or.unwrap();
        Ok(e.clone())
    }

    pub fn get_extent_count(&self) -> u64 {
        self.extent_count
    }

    /// Checks/validates extent cluster.
    /// TODO(auradkar) : verify crc.
    #[cfg(test)]
    pub fn test_check(&self, extent_count: u64, next_cluster_offset: u64) -> bool {
        self.magic1 == EXTENT_CLUSTER_HEADER_MAGIC1
            && self.magic2 == EXTENT_CLUSTER_HEADER_MAGIC2
            && self.extent_count == extent_count
            && self.next_cluster_offset == next_cluster_offset
            && self.crc32 != 0
            && self.footer_offset == 0
    }
}

#[cfg(test)]
mod test {
    use {
        super::*, crate::properties::ExtentProperties, interval_tree::interval::Interval,
        std::io::Cursor,
    };

    #[test]
    fn test_header_serialized_size() {
        // Default header alignment is 8KiB. Serialized size should be greater than the size of
        // header which is much smaller in size.
        let header: Header = Default::default();
        assert!(header.serialized_size() as usize > std::mem::size_of::<Header>());
        assert!(header.serialized_size() >= DEFAULT_ALIGNMENT);
        assert!(header.serialized_size() % DEFAULT_ALIGNMENT == 0);

        // Smaller alignment.
        let alignment = 32;
        let header2 = Header::new(alignment);
        assert!(header2.serialized_size() as usize >= std::mem::size_of::<Header>());
        assert!(header2.serialized_size() >= alignment);
        assert!(header2.serialized_size() % alignment == 0);
        assert!(header.serialized_size() > header2.serialized_size());

        // No alignment - aka 1 byte alignment.
        let alignment = 1;
        let header3 = Header::new(alignment);
        assert!(header3.serialized_size() >= alignment);
        assert!(header.serialized_size() > header3.serialized_size());
    }

    #[test]
    fn test_check_extent_cluster_offset() {
        let header: Header = Default::default();
        assert!(header.check_extent_cluster_offset(0).err().unwrap() == Error::InvalidOffset);
        assert!(
            header.check_extent_cluster_offset(header.serialized_size() - 1).err().unwrap()
                == Error::InvalidOffset
        );
        assert!(
            header.check_extent_cluster_offset(header.serialized_size() + 1).err().unwrap()
                == Error::InvalidOffset
        );
        assert!(header.check_extent_cluster_offset(header.serialized_size()).is_ok());
        assert!(header
            .check_extent_cluster_offset(header.serialized_size() + DEFAULT_ALIGNMENT)
            .is_ok());
    }

    #[test]
    fn test_set_extent_cluster_offset() {
        let mut header: Header = Default::default();
        let default_offset = header.get_extent_cluster_offset();
        assert!(header.set_extent_cluster_offset(0).err().unwrap() == Error::InvalidOffset);
        assert!(header.get_extent_cluster_offset() == default_offset);

        assert!(
            header.set_extent_cluster_offset(header.serialized_size() - 1).err().unwrap()
                == Error::InvalidOffset
        );
        assert!(header.get_extent_cluster_offset() == default_offset);

        assert!(
            header.set_extent_cluster_offset(header.serialized_size() + 1).err().unwrap()
                == Error::InvalidOffset
        );
        assert!(header.get_extent_cluster_offset() == default_offset);

        assert!(header.set_extent_cluster_offset(header.serialized_size()).is_ok());
        assert!(header.get_extent_cluster_offset() == header.serialized_size());

        assert!(header
            .set_extent_cluster_offset(header.serialized_size() + DEFAULT_ALIGNMENT)
            .is_ok());
        assert!(header.get_extent_cluster_offset() == header.serialized_size() + DEFAULT_ALIGNMENT);
    }

    #[test]
    fn test_header_serialize() {
        let mut header: Header = Default::default();
        let mut out_buffer = Cursor::new(Vec::new());
        let len = header.serialize_to(&mut out_buffer);
        assert!(len.is_ok());
        assert_eq!(out_buffer.get_ref().len(), header.serialized_size() as usize);
        assert_eq!(out_buffer.get_ref().len(), len.unwrap() as usize);
        assert_eq!(out_buffer.get_ref().len() % header.alignment as usize, 0);
        out_buffer.set_position(0);
        let read_header: Header = Header::deserialize_from(&mut out_buffer).unwrap();
        assert_eq!(header, read_header);
    }

    #[test]
    fn test_extent_kind_info_to_kind() {
        assert_eq!(
            ExtentKindInfo::new(ExtentKind::Unmmapped).to_kind().unwrap(),
            ExtentKind::Unmmapped
        );
        assert_eq!(ExtentKindInfo::new(ExtentKind::Unused).to_kind().unwrap(), ExtentKind::Unused);
        assert_eq!(ExtentKindInfo::new(ExtentKind::Data).to_kind().unwrap(), ExtentKind::Data);
        assert_eq!(ExtentKindInfo::new(ExtentKind::Pii).to_kind().unwrap(), ExtentKind::Pii);
    }

    #[test]
    fn test_extent_kind_info_try_from() {
        assert_eq!(
            ExtentKindInfo::try_from(EXTENT_KIND_UNMAPPED).unwrap().to_kind().unwrap(),
            ExtentKind::Unmmapped
        );
        assert_eq!(
            ExtentKindInfo::try_from(EXTENT_KIND_UNUSED).unwrap().to_kind().unwrap(),
            ExtentKind::Unused
        );
        assert_eq!(
            ExtentKindInfo::try_from(EXTENT_KIND_DATA).unwrap().to_kind().unwrap(),
            ExtentKind::Data
        );
        assert_eq!(
            ExtentKindInfo::try_from(EXTENT_KIND_PII).unwrap().to_kind().unwrap(),
            ExtentKind::Pii
        );
        assert_eq!(
            ExtentKindInfo::try_from(EXTENT_KIND_PII + 1).err().unwrap(),
            Error::InvalidArgument
        );
        assert_eq!(ExtentKindInfo::try_from(10).err().unwrap(), Error::InvalidArgument);
    }

    #[test]
    fn test_data_kind_info_to_kind() {
        assert_eq!(DataKindInfo::new(DataKind::Skipped).to_kind().unwrap(), DataKind::Skipped);
        assert_eq!(DataKindInfo::new(DataKind::Zeroes).to_kind().unwrap(), DataKind::Zeroes);
        assert_eq!(
            DataKindInfo::new(DataKind::Unmodified).to_kind().unwrap(),
            DataKind::Unmodified
        );
        assert_eq!(DataKindInfo::new(DataKind::Modified).to_kind().unwrap(), DataKind::Modified);
    }

    #[test]
    fn test_data_kind_info_try_from() {
        assert_eq!(
            DataKindInfo::try_from(DATA_KIND_SKIPPED).unwrap().to_kind().unwrap(),
            DataKind::Skipped
        );
        assert_eq!(
            DataKindInfo::try_from(DATA_KIND_ZEROES).unwrap().to_kind().unwrap(),
            DataKind::Zeroes
        );
        assert_eq!(
            DataKindInfo::try_from(DATA_KIND_MODIFIED).unwrap().to_kind().unwrap(),
            DataKind::Modified
        );
        assert_eq!(
            DataKindInfo::try_from(DATA_KIND_UNMODIFIED).unwrap().to_kind().unwrap(),
            DataKind::Unmodified
        );
        assert_eq!(
            DataKindInfo::try_from(DATA_KIND_MODIFIED + 1).err().unwrap(),
            Error::InvalidArgument
        );
        assert_eq!(DataKindInfo::try_from(10).err().unwrap(), Error::InvalidArgument);
    }

    #[test]
    fn test_extent_info_deserialie() {
        let extent = Extent::new(
            10..20,
            ExtentProperties { extent_kind: ExtentKind::Pii, data_kind: DataKind::Modified },
            None,
        )
        .unwrap();

        let info = ExtentInfo::from(extent.clone());
        let mut buffer = Cursor::new(Vec::new());
        info.serialize_to(&mut buffer).unwrap();
        assert_eq!(buffer.get_ref().len() as u64, info.serialized_size());
        buffer.set_position(0);
        let read_extent = ExtentInfo::deserialize_from(&mut buffer).unwrap();
        assert_eq!(read_extent.start, extent.start());
        assert_eq!(read_extent.end, extent.end());
        assert_eq!(read_extent.data.to_kind().unwrap(), extent.properties.data_kind);
        assert_eq!(read_extent.extent.to_kind().unwrap(), extent.properties.extent_kind);
    }

    #[test]
    fn test_extent_cluster_header_serialize_all_zeroes() {
        let mut buffer = Cursor::new(Vec::new());
        ExtentClusterHeader::serialize_to(0, 0, &mut buffer).unwrap();
        assert!(buffer.get_ref().len() > 0);
        buffer.set_position(0);
        let cluster = ExtentClusterHeader::deserialize_from(&mut buffer).unwrap();
        assert_eq!(cluster.magic1, EXTENT_CLUSTER_HEADER_MAGIC1);
        assert_eq!(cluster.magic2, EXTENT_CLUSTER_HEADER_MAGIC2);
        assert_eq!(cluster.extent_count, 0);
        assert_eq!(cluster.next_cluster_offset, 0);
        assert_ne!(cluster.crc32, 0);
    }

    #[test]
    fn test_extent_cluster_header_serialize() {
        let mut buffer = Cursor::new(Vec::new());
        let len = ExtentClusterHeader::serialize_to(50, 100, &mut buffer).unwrap();
        buffer.set_position(0);
        assert_eq!(buffer.get_ref().len() as u64, len);
        let cluster = ExtentClusterHeader::deserialize_from(&mut buffer).unwrap();
        assert_eq!(buffer.get_ref().len(), cluster.serialized_size() as usize);
        assert_eq!(cluster.magic1, EXTENT_CLUSTER_HEADER_MAGIC1);
        assert_eq!(cluster.magic2, EXTENT_CLUSTER_HEADER_MAGIC2);
        assert_eq!(cluster.extent_count, 50);
        assert_eq!(cluster.next_cluster_offset, 100);
        assert_ne!(cluster.crc32, 0);
    }
}
