//! A WebAssembly encoder.
//!
//! The main builder is the [`Module`]. You can build a section with a
//! section-specific builder, like [`TypeSection`] or [`ImportSection`], and
//! then add it to the module with [`Module::section`]. When you are finished
//! building the module, call either [`Module::as_slice`] or [`Module::finish`]
//! to get the encoded bytes. The former gives a shared reference to the
//! underlying bytes as a slice, while the latter gives you ownership of them as
//! a vector.
//!
//! # Example
//!
//! If we wanted to build this module:
//!
//! ```wasm
//! (module
//!   (type (func (param i32 i32) (result i32)))
//!   (func (type 0)
//!     local.get 0
//!     local.get 1
//!     i32.add)
//!   (export "f" (func 0)))
//! ```
//!
//! then we would do this:
//!
//! ```
//! use wasm_encoder::{
//!     CodeSection, ExportKind, ExportSection, Function, FunctionSection, Instruction,
//!     Module, TypeSection, ValType,
//! };
//!
//! let mut module = Module::new();
//!
//! // Encode the type section.
//! let mut types = TypeSection::new();
//! let params = vec![ValType::I32, ValType::I32];
//! let results = vec![ValType::I32];
//! types.function(params, results);
//! module.section(&types);
//!
//! // Encode the function section.
//! let mut functions = FunctionSection::new();
//! let type_index = 0;
//! functions.function(type_index);
//! module.section(&functions);
//!
//! // Encode the export section.
//! let mut exports = ExportSection::new();
//! exports.export("f", ExportKind::Func, 0);
//! module.section(&exports);
//!
//! // Encode the code section.
//! let mut codes = CodeSection::new();
//! let locals = vec![];
//! let mut f = Function::new(locals);
//! f.instruction(&Instruction::LocalGet(0));
//! f.instruction(&Instruction::LocalGet(1));
//! f.instruction(&Instruction::I32Add);
//! f.instruction(&Instruction::End);
//! codes.function(&f);
//! module.section(&codes);
//!
//! // Extract the encoded Wasm bytes for this module.
//! let wasm_bytes = module.finish();
//!
//! // We generated a valid Wasm module!
//! assert!(wasmparser::validate(&wasm_bytes).is_ok());
//! ```

#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![deny(missing_docs, missing_debug_implementations)]

mod component;
mod core;
mod raw;
#[cfg(feature = "wasmparser")]
pub mod reencode;

pub use self::component::*;
pub use self::core::*;
pub use self::raw::*;

/// Implemented by types that can be encoded into a byte sink.
pub trait Encode {
    /// Encode the type into the given byte sink.
    fn encode(&self, sink: &mut Vec<u8>);
}

impl<T: Encode + ?Sized> Encode for &'_ T {
    fn encode(&self, sink: &mut Vec<u8>) {
        T::encode(self, sink)
    }
}

impl<T: Encode> Encode for [T] {
    fn encode(&self, sink: &mut Vec<u8>) {
        self.len().encode(sink);
        for item in self {
            item.encode(sink);
        }
    }
}

impl Encode for [u8] {
    fn encode(&self, sink: &mut Vec<u8>) {
        self.len().encode(sink);
        sink.extend(self);
    }
}

impl Encode for str {
    fn encode(&self, sink: &mut Vec<u8>) {
        self.len().encode(sink);
        sink.extend_from_slice(self.as_bytes());
    }
}

impl Encode for usize {
    fn encode(&self, sink: &mut Vec<u8>) {
        assert!(*self <= u32::max_value() as usize);
        (*self as u32).encode(sink)
    }
}

impl Encode for u32 {
    fn encode(&self, sink: &mut Vec<u8>) {
        leb128::write::unsigned(sink, (*self).into()).unwrap();
    }
}

impl Encode for i32 {
    fn encode(&self, sink: &mut Vec<u8>) {
        leb128::write::signed(sink, (*self).into()).unwrap();
    }
}

impl Encode for u64 {
    fn encode(&self, sink: &mut Vec<u8>) {
        leb128::write::unsigned(sink, *self).unwrap();
    }
}

impl Encode for i64 {
    fn encode(&self, sink: &mut Vec<u8>) {
        leb128::write::signed(sink, *self).unwrap();
    }
}

impl Encode for f32 {
    fn encode(&self, sink: &mut Vec<u8>) {
        let bits = self.to_bits();
        sink.extend(bits.to_le_bytes())
    }
}

impl Encode for f64 {
    fn encode(&self, sink: &mut Vec<u8>) {
        let bits = self.to_bits();
        sink.extend(bits.to_le_bytes())
    }
}

fn encode_vec<T, V>(elements: V, sink: &mut Vec<u8>)
where
    T: Encode,
    V: IntoIterator<Item = T>,
    V::IntoIter: ExactSizeIterator,
{
    let elements = elements.into_iter();
    u32::try_from(elements.len()).unwrap().encode(sink);
    for x in elements {
        x.encode(sink);
    }
}

impl<T> Encode for Option<T>
where
    T: Encode,
{
    fn encode(&self, sink: &mut Vec<u8>) {
        match self {
            Some(v) => {
                sink.push(0x01);
                v.encode(sink);
            }
            None => sink.push(0x00),
        }
    }
}

fn encoding_size(n: u32) -> usize {
    let mut buf = [0u8; 5];
    leb128::write::unsigned(&mut &mut buf[..], n.into()).unwrap()
}

fn encode_section(sink: &mut Vec<u8>, count: u32, bytes: &[u8]) {
    (encoding_size(count) + bytes.len()).encode(sink);
    count.encode(sink);
    sink.extend(bytes);
}

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

    #[test]
    fn it_encodes_an_empty_module() {
        let bytes = Module::new().finish();
        assert_eq!(bytes, [0x00, b'a', b's', b'm', 0x01, 0x00, 0x00, 0x00]);
    }

    #[test]
    fn it_encodes_an_empty_component() {
        let bytes = Component::new().finish();
        assert_eq!(bytes, [0x00, b'a', b's', b'm', 0x0d, 0x00, 0x01, 0x00]);
    }
}
