1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use indexmap::{map::Iter, IndexMap};
use nyar_error::NyarError;
use std::{
    fs::File,
    intrinsics::transmute,
    io::Write,
    path::{Path, PathBuf},
};
use wast::{core::Instruction, token::Span};

pub struct IndexedIterator<'i, T> {
    iter: Iter<'i, String, T>,
    index: usize,
}

impl<'i, T> Iterator for IndexedIterator<'i, T> {
    type Item = (usize, &'i str, &'i T);

    fn next(&mut self) -> Option<Self::Item> {
        let (name, item) = self.iter.next()?;
        let index = self.index;
        self.index += 1;
        Some((index, name, item))
    }
}
impl<'i, T> DoubleEndedIterator for IndexedIterator<'i, T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        let (name, item) = self.iter.next_back()?;
        let index = self.index;
        self.index += 1;
        Some((index, name, item))
    }
}

impl<'i, T> ExactSizeIterator for IndexedIterator<'i, T> {
    fn len(&self) -> usize {
        self.iter.len()
    }
}
impl<'i, T> IndexedIterator<'i, T> {
    pub fn new(map: &'i IndexMap<String, T>) -> Self {
        Self { iter: map.iter(), index: 0 }
    }
    pub fn with_index(self, index: usize) -> Self {
        Self { index, ..self }
    }
}

pub trait IntoWasm<'a, Item> {
    fn as_wast(&'a self) -> Item;
}

pub trait WasmInstruction {
    fn emit<'a, 'i>(&'a self, w: &mut Vec<Instruction<'i>>)
    where
        'a: 'i;
}

#[allow(dead_code)]
pub(crate) struct WasmName<'a> {
    name: &'a str,
    gen: u32,
    span: Span,
}

impl<'a> WasmName<'a> {
    pub fn new(name: &'a str) -> wast::token::Id<'a> {
        unsafe {
            let s = WasmName { name, gen: 0, span: Span::from_offset(0) };
            transmute::<WasmName, wast::token::Id>(s)
        }
    }
    pub fn id(name: &'a str) -> Option<wast::token::Id<'a>> {
        Some(Self::new(name))
    }
}

pub(crate) fn write_wasm_bytes(path: &Path, buffer: Result<Vec<u8>, wast::Error>) -> Result<PathBuf, NyarError> {
    match buffer {
        Ok(o) => {
            let mut file = File::create(path)?;
            file.write_all(&o)?;
        }
        Err(e) => Err(NyarError::custom(e))?,
    }
    Ok(path.canonicalize()?)
}