<commit_before>use crate::parser::{ParseError, ParseErrorKind, ParseResult};
use alloc::fmt;

const MAX_OID_LENGTH: usize = 63;

/// Represents an ASN.1 `OBJECT IDENTIFIER`. ObjectIdentifiers are opaque, the only thing may be
/// done with them is test if they are equal to another `ObjectIdentifier`. The generally
/// recommended practice for handling them is to create some `ObjectIdentifier` constants with
/// `asn1::oid!()` and then compare ObjectIdentifiers you get from parsing to
/// those.
///
/// `asn1::oid!()` takes a series of arcs, for example: `asn1::oid!(1, 2, 3)`.
///
/// rust-asn1 stores `ObjectIdentifier`s in a fixed-size buffer, therefore
/// they are limited to OID values whose DER encoding fits into that buffer.
/// This buffer is sufficiently large to fit all known publically known OIDs,
/// so this should not effect most people.
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct ObjectIdentifier {
    // Store the OID as DER encoded.
    der_encoded: [u8; MAX_OID_LENGTH],
    der_encoded_len: u8,
}

fn _read_base128_int<I: Iterator<Item = u8>>(mut reader: I) -> ParseResult<u32> {
    let mut ret = 0u32;
    for _ in 0..4 {
        let b = reader
            .next()
            .ok_or_else(|| ParseError::new(ParseErrorKind::InvalidValue))?;
        ret <<= 7;
        ret |= u32::from(b & 0x7f);
        if b & 0x80 == 0 {
            return Ok(ret);
        }
    }
    Err(ParseError::new(ParseErrorKind::InvalidValue))
}

fn _write_base128_int(mut data: &mut [u8], n: u32) -> Option<usize> {
    if n == 0 {
        if data.is_empty() {
            return None;
        }
        data[0] = 0;
        return Some(1);
    }

    let mut length = 0;
    let mut i = n;
    while i > 0 {
        length += 1;
        i >>= 7;
    }

    for i in (0..length).rev() {
        let mut o = (n >> (i * 7)) as u8;
        o &= 0x7f;
        if i != 0 {
            o |= 0x80;
        }
        if data.is_empty() {
            return None;
        }
        data[0] = o;
        data = &mut data[1..];
    }

    Some(length)
}

impl ObjectIdentifier {
    /// Parses an OID from a dotted string, e.g. `"1.2.840.113549"`.
    pub fn from_string(oid: &str) -> Option<ObjectIdentifier> {
        let mut parts = oid.split('.');

        let first = parts.next()?.parse::<u32>().ok()?;
        let second = parts.next()?.parse::<u32>().ok()?;
        if first > 2 || (first < 2 && second >= 40) {
            return None;
        }

        let mut der_data = [0; MAX_OID_LENGTH];
        let mut der_data_len = 0;
        der_data_len += _write_base128_int(&mut der_data[der_data_len..], 40 * first + second)?;
        for part in parts {
            der_data_len +=
                _write_base128_int(&mut der_data[der_data_len..], part.parse::<u32>().ok()?)?;
        }
        Some(ObjectIdentifier {
            der_encoded: der_data,
            der_encoded_len: der_data_len as u8,
        })
    }

    /// Creates an `ObjectIdentifier` from its DER representation. This does
    /// not perform any allocations or copies.
    pub fn from_der(data: &[u8]) -> ParseResult<ObjectIdentifier> {
        if data.is_empty() {
            return Err(ParseError::new(ParseErrorKind::InvalidValue));
        } else if data.len() > MAX_OID_LENGTH {
            return Err(ParseError::new(ParseErrorKind::OidTooLong));
        }
        let mut cursor = data.iter().copied();
        while cursor.len() > 0 {
            _read_base128_int(&mut cursor)?;
        }

        let mut storage = [0; MAX_OID_LENGTH];
        storage[..data.len()].copy_from_slice(data);

        Ok(ObjectIdentifier {
            der_encoded: storage,
            der_encoded_len: data.len() as u8,
        })
    }

    /// Creates an `ObjectIdentifier` from its DER representation. Does not
    /// check that the DER is valid. Intended only for use from the `oid!()`
    /// macro. Do not use yourself!
    #[doc(hidden)]
    pub const fn from_der_unchecked(data: [u8; MAX_OID_LENGTH], data_len: u8) -> ObjectIdentifier {
        ObjectIdentifier {
            der_encoded: data,
            der_encoded_len: data_len,
        }
    }

    pub(crate) fn as_der(&self) -> &[u8] {
        &self.der_encoded[..self.der_encoded_len as usize]
    }
}

impl fmt::Display for ObjectIdentifier {
    /// Converts an `ObjectIdentifier` to a dotted string, e.g.
    /// "1.2.840.113549".
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut cursor = self.as_der().iter().copied();

        let first = _read_base128_int(&mut cursor).unwrap();
        if first < 80 {
            write!(f, "{}.{}", first / 40, first % 40)?;
        } else {
            write!(f, "2.{}", first - 80)?;
        }

        while cursor.len() > 0 {
            let digit = _read_base128_int(&mut cursor).unwrap();
            write!(f, ".{}", digit)?;
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use crate::{ObjectIdentifier, ParseError, ParseErrorKind};

    #[test]
    fn test_object_identifier_from_string() {
        for val in &[
            "",
            "1",
            "3.10",
            "1.50",
            "2.12.a3.4",
            "a.4",
            "1.a",
            ".2.5",
            "2..5",
            "2.5.",
            "1.3.6.1.4.1.1248.1.1.2.1.3.21.69.112.115.111.110.32.83.116.121.108.117.115.32.80.114.111.32.52.57.48.48.123.124412.31.213321.123.110.32.83.116.121.108.117.115.32.80.114.111.32.52.57.48.48.123.124412.31.213321.123",
        ] {
            assert_eq!(ObjectIdentifier::from_string(val), None);
        }

        for val in &[
            "2.5",
            "2.5.2",
            "1.2.840.113549",
            "1.2.3.4",
            "1.2.840.133549.1.1.5",
            "2.100.3",
        ] {
            assert!(ObjectIdentifier::from_string(val).is_some());
        }
    }

    #[test]
    fn test_from_der() {
        assert_eq!(ObjectIdentifier::from_der(b"\x06\x40\x2b\x06\x01\x04\x01\x89\x60\x01\x01\x02\x01\x03\x15\x45\x70\x73\x6f\x6e\x20\x53\x74\x79\x6c\x75\x73\x20\x50\x72\x6f\x20\x34\x39\x30\x30\x7b\x87\xcb\x7c\x1f\x8d\x82\x49\x7b\x2b\x06\x01\x04\x01\x89\x60\x01\x01\x02\x01\x03\x15\x45\x70\x73\x6f\x6e\x20"), Err(ParseError::new(ParseErrorKind::OidTooLong)));
    }

    #[test]
    fn test_to_string() {
        for val in &[
            "0.4",
            "2.5",
            "2.5.2",
            "1.2.840.113549",
            "1.2.3.4",
            "1.2.840.133549.1.1.5",
            "2.100.3",
        ] {
            assert_eq!(
                &ObjectIdentifier::from_string(val).unwrap().to_string(),
                val
            );
        }
    }
}
<commit_msg>Refactor _read_base128_int to not use an Iterator (#258)<commit_after>use crate::parser::{ParseError, ParseErrorKind, ParseResult};
use alloc::fmt;

const MAX_OID_LENGTH: usize = 63;

/// Represents an ASN.1 `OBJECT IDENTIFIER`. ObjectIdentifiers are opaque, the only thing may be
/// done with them is test if they are equal to another `ObjectIdentifier`. The generally
/// recommended practice for handling them is to create some `ObjectIdentifier` constants with
/// `asn1::oid!()` and then compare ObjectIdentifiers you get from parsing to
/// those.
///
/// `asn1::oid!()` takes a series of arcs, for example: `asn1::oid!(1, 2, 3)`.
///
/// rust-asn1 stores `ObjectIdentifier`s in a fixed-size buffer, therefore
/// they are limited to OID values whose DER encoding fits into that buffer.
/// This buffer is sufficiently large to fit all known publically known OIDs,
/// so this should not effect most people.
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
pub struct ObjectIdentifier {
    // Store the OID as DER encoded.
    der_encoded: [u8; MAX_OID_LENGTH],
    der_encoded_len: u8,
}

fn _read_base128_int(mut data: &[u8]) -> ParseResult<(u32, &[u8])> {
    let mut ret = 0u32;
    for _ in 0..4 {
        let b = match data.first() {
            Some(b) => b,
            None => return Err(ParseError::new(ParseErrorKind::InvalidValue)),
        };
        data = &data[1..];
        ret <<= 7;
        ret |= u32::from(b & 0x7f);
        if b & 0x80 == 0 {
            return Ok((ret, data));
        }
    }
    Err(ParseError::new(ParseErrorKind::InvalidValue))
}

fn _write_base128_int(mut data: &mut [u8], n: u32) -> Option<usize> {
    if n == 0 {
        if data.is_empty() {
            return None;
        }
        data[0] = 0;
        return Some(1);
    }

    let mut length = 0;
    let mut i = n;
    while i > 0 {
        length += 1;
        i >>= 7;
    }

    for i in (0..length).rev() {
        let mut o = (n >> (i * 7)) as u8;
        o &= 0x7f;
        if i != 0 {
            o |= 0x80;
        }
        if data.is_empty() {
            return None;
        }
        data[0] = o;
        data = &mut data[1..];
    }

    Some(length)
}

impl ObjectIdentifier {
    /// Parses an OID from a dotted string, e.g. `"1.2.840.113549"`.
    pub fn from_string(oid: &str) -> Option<ObjectIdentifier> {
        let mut parts = oid.split('.');

        let first = parts.next()?.parse::<u32>().ok()?;
        let second = parts.next()?.parse::<u32>().ok()?;
        if first > 2 || (first < 2 && second >= 40) {
            return None;
        }

        let mut der_data = [0; MAX_OID_LENGTH];
        let mut der_data_len = 0;
        der_data_len += _write_base128_int(&mut der_data[der_data_len..], 40 * first + second)?;
        for part in parts {
            der_data_len +=
                _write_base128_int(&mut der_data[der_data_len..], part.parse::<u32>().ok()?)?;
        }
        Some(ObjectIdentifier {
            der_encoded: der_data,
            der_encoded_len: der_data_len as u8,
        })
    }

    /// Creates an `ObjectIdentifier` from its DER representation. This does
    /// not perform any allocations or copies.
    pub fn from_der(data: &[u8]) -> ParseResult<ObjectIdentifier> {
        if data.is_empty() {
            return Err(ParseError::new(ParseErrorKind::InvalidValue));
        } else if data.len() > MAX_OID_LENGTH {
            return Err(ParseError::new(ParseErrorKind::OidTooLong));
        }

        let mut parsed = (0, data);
        while !parsed.1.is_empty() {
            parsed = _read_base128_int(parsed.1)?;
        }

        let mut storage = [0; MAX_OID_LENGTH];
        storage[..data.len()].copy_from_slice(data);

        Ok(ObjectIdentifier {
            der_encoded: storage,
            der_encoded_len: data.len() as u8,
        })
    }

    /// Creates an `ObjectIdentifier` from its DER representation. Does not
    /// check that the DER is valid. Intended only for use from the `oid!()`
    /// macro. Do not use yourself!
    #[doc(hidden)]
    pub const fn from_der_unchecked(data: [u8; MAX_OID_LENGTH], data_len: u8) -> ObjectIdentifier {
        ObjectIdentifier {
            der_encoded: data,
            der_encoded_len: data_len,
        }
    }

    pub(crate) fn as_der(&self) -> &[u8] {
        &self.der_encoded[..self.der_encoded_len as usize]
    }
}

impl fmt::Display for ObjectIdentifier {
    /// Converts an `ObjectIdentifier` to a dotted string, e.g.
    /// "1.2.840.113549".
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut parsed = (0, self.as_der());

        parsed = _read_base128_int(parsed.1).unwrap();
        if parsed.0 < 80 {
            write!(f, "{}.{}", parsed.0 / 40, parsed.0 % 40)?;
        } else {
            write!(f, "2.{}", parsed.0 - 80)?;
        }

        while !parsed.1.is_empty() {
            parsed = _read_base128_int(parsed.1).unwrap();
            write!(f, ".{}", parsed.0)?;
        }

        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use crate::{ObjectIdentifier, ParseError, ParseErrorKind};

    #[test]
    fn test_object_identifier_from_string() {
        for val in &[
            "",
            "1",
            "3.10",
            "1.50",
            "2.12.a3.4",
            "a.4",
            "1.a",
            ".2.5",
            "2..5",
            "2.5.",
            "1.3.6.1.4.1.1248.1.1.2.1.3.21.69.112.115.111.110.32.83.116.121.108.117.115.32.80.114.111.32.52.57.48.48.123.124412.31.213321.123.110.32.83.116.121.108.117.115.32.80.114.111.32.52.57.48.48.123.124412.31.213321.123",
        ] {
            assert_eq!(ObjectIdentifier::from_string(val), None);
        }

        for val in &[
            "2.5",
            "2.5.2",
            "1.2.840.113549",
            "1.2.3.4",
            "1.2.840.133549.1.1.5",
            "2.100.3",
        ] {
            assert!(ObjectIdentifier::from_string(val).is_some());
        }
    }

    #[test]
    fn test_from_der() {
        assert_eq!(ObjectIdentifier::from_der(b"\x06\x40\x2b\x06\x01\x04\x01\x89\x60\x01\x01\x02\x01\x03\x15\x45\x70\x73\x6f\x6e\x20\x53\x74\x79\x6c\x75\x73\x20\x50\x72\x6f\x20\x34\x39\x30\x30\x7b\x87\xcb\x7c\x1f\x8d\x82\x49\x7b\x2b\x06\x01\x04\x01\x89\x60\x01\x01\x02\x01\x03\x15\x45\x70\x73\x6f\x6e\x20"), Err(ParseError::new(ParseErrorKind::OidTooLong)));
    }

    #[test]
    fn test_to_string() {
        for val in &[
            "0.4",
            "2.5",
            "2.5.2",
            "1.2.840.113549",
            "1.2.3.4",
            "1.2.840.133549.1.1.5",
            "2.100.3",
        ] {
            assert_eq!(
                &ObjectIdentifier::from_string(val).unwrap().to_string(),
                val
            );
        }
    }
}
<|endoftext|>


<commit_before>use base::{TeardownTree, TeardownTreeInternal, Item, Node};
use slot_stack::SlotStack;

pub trait TraversalDriver<T: Item> {
    #[inline(always)]
    fn decide(&self, key: &T::Key) -> TraversalDecision;
}

#[derive(Clone, Copy, Debug)]
pub struct TraversalDecision {
    pub left: bool,
    pub right: bool,
}

pub struct DeleteRangeCache {
    pub slots_min: SlotStack, pub slots_max: SlotStack,   // TODO: we no longer need both stacks, one is enough... but removing one causes 3% performance regression
}

impl Clone for DeleteRangeCache {
    fn clone(&self) -> Self {
        debug_assert!(self.slots_min.is_empty() && self.slots_max.is_empty());
        let capacity = self.slots_max.capacity;
        DeleteRangeCache::new(capacity)
    }
}

impl DeleteRangeCache {
    pub fn new(height: usize) -> DeleteRangeCache {
        let slots_min = SlotStack::new(height);
        let slots_max = SlotStack::new(height);
        DeleteRangeCache { slots_min: slots_min, slots_max: slots_max }
    }
}

pub struct DeleteRange<'a, T: 'a+Item> {
    tree: &'a mut TeardownTree<T>,
    slots_min: SlotStack, slots_max: SlotStack,
    pub output: &'a mut Vec<T>
}

impl<'a, T: Item> DeleteRange<'a, T> {
    pub fn new(tree: &'a mut TeardownTree<T>, output: &'a mut Vec<T>) -> DeleteRange<'a, T> {
        let cache = tree.delete_range_cache.take().unwrap();
        DeleteRange { tree: tree, slots_min: cache.slots_min, slots_max: cache.slots_max, output: output }
    }

    /// The items are not guaranteed to be returned in any particular order.
    pub fn delete_range<D: TraversalDriver<T>>(mut self, drv: &mut D) {
        self.delete_range_loop(drv, 0);
        debug_assert!(self.slots_min.is_empty() && self.slots_max.is_empty() && self.tree.traversal_stack.is_empty());

        self.tree.delete_range_cache = Some(DeleteRangeCache { slots_min: self.slots_min, slots_max: self.slots_max });
    }

    //---- helpers ---------------------------------------------------------------------------------
    #[inline(always)]
    fn node(&self, idx: usize) -> &Node<T> {
        self.tree.node(idx)
    }

    #[inline(always)]
    fn item(&mut self, idx: usize) -> &T {
        &self.node(idx).item
    }

    #[inline(always)]
    fn lefti(idx: usize) -> usize {
        TeardownTree::<T>::lefti(idx)
    }

    #[inline(always)]
    fn righti(idx: usize) -> usize {
        TeardownTree::<T>::righti(idx)
    }

    #[inline(always)]
    fn consume(&mut self, idx: usize) {
        let item = self.tree.take(idx);
        self.output.push(item);
    }
}

// v5
impl<'a, T: Item> DeleteRange<'a, T> {
    #[inline]
    fn delete_range_loop<D: TraversalDriver<T>>(&mut self, drv: &D, mut idx: usize) {
        loop {
            if self.tree.is_null(idx) {
                return;
            }

            let decision = drv.decide(&self.item(idx).key());

            if decision.left && decision.right {
                self.consume(idx);
                let removed = self.descend_delete_left(drv, idx, true);
                self.descend_delete_right(drv, idx, removed);
                return;
            } else if decision.left {
                idx = Self::lefti(idx);
            } else {
                debug_assert!(decision.right);
                idx = Self::righti(idx);
            }
        }
    }

    #[inline(never)]
    fn delete_range_min<D: TraversalDriver<T>>(&mut self, drv: &D, idx: usize) {
        let decision = drv.decide(&self.item(idx).key());
        debug_assert!(decision.left);

        if decision.right {
            // the root and the whole left subtree are inside the range
            self.consume(idx);
            self.consume_subtree(Self::lefti(idx));
            self.descend_delete_right(drv, idx, true);
        } else {
            // the root and the right subtree are outside the range
            self.descend_left(idx,
                   |this: &mut Self, child_idx| this.delete_range_min(drv, child_idx)
            );

            if self.slots_min.has_open() {
                self.slots_min.fill(self.tree, idx);
                self.descend_fill_right(idx);
            }
        }
    }

    #[inline(never)]
    fn delete_range_max<D: TraversalDriver<T>>(&mut self, drv: &D, idx: usize) {
        let decision = drv.decide(&self.item(idx).key());
        debug_assert!(decision.right);

        if decision.left {
            // the root and the whole right subtree are inside the range
            self.consume(idx);
            self.consume_subtree(Self::righti(idx));
            self.descend_delete_left(drv, idx, true);
        } else {
            // the root and the left subtree are outside the range
            self.descend_right(idx,
                   |this: &mut Self, child_idx| this.delete_range_max(drv, child_idx)
            );

            if self.slots_max.has_open() {
                self.slots_max.fill(self.tree, idx);
                self.descend_fill_left(idx);
            }
        }
    }

    //---- delete_subtree_* ---------------------------------------------------------------
    #[inline]
    fn consume_subtree(&mut self, root: usize) {
        debug_assert!(self.tree.traversal_stack.is_empty());

        self.tree.traverse_preorder(root, self.output, |tree, output, idx| {
            unsafe {
                let len = output.len();
                debug_assert!(len < output.capacity());
                let p = output.as_mut_ptr().offset(len as isize);
                output.set_len(len + 1);
                tree.move_to(idx, p)
            }
        });
    }

    //---- fill_slots_* -------------------------------------------------------------------
    #[inline(never)]
    fn fill_slots_min(&mut self, idx: usize) -> bool {
        if self.tree.is_null(idx) {
            return false;
        }

        let done = self.fill_slots_min(Self::lefti(idx));

        if done {
            true
        } else {
            debug_assert!(self.slots_min.has_open());

            self.slots_min.fill(self.tree, idx);

            self.descend_fill_right(idx);

            let done = !self.tree.is_null(idx);
            if done {
                true
            } else {
                !self.slots_min.has_open()
            }
        }
    }

    #[inline(never)]
    fn fill_slots_max(&mut self, idx: usize) -> bool {
        if self.tree.is_null(idx) {
            return false;
        }

        let done = self.fill_slots_max(Self::righti(idx));

        if done {
            true
        } else {
            debug_assert!(self.slots_max.has_open());

            self.slots_max.fill(self.tree, idx);

            self.descend_fill_left(idx);

            let done = !self.tree.is_null(idx);
            if done {
                true
            } else {
                !self.slots_max.has_open()
            }
        }
    }

    //---- descend_* -------------------------------------------------------------------------------

    #[inline(always)]
    fn descend_left<F>(&mut self, idx: usize, f: F)
        where F: Fn(&mut Self, usize) {
        let child_idx = Self::lefti(idx);
        if !self.tree.is_null(child_idx) {
            f(self, child_idx);
        }
    }

    #[inline(always)]
    fn descend_right<F>(&mut self, idx: usize, f: F)
        where F: Fn(&mut Self, usize) {
        let child_idx = Self::righti(idx);
        if !self.tree.is_null(child_idx) {
            f(self, child_idx);
        }
    }

    /// Returns true if the item is removed after recursive call, false otherwise.
    #[inline(always)]
    fn descend_left_with_slot<F>(&mut self, idx: usize, f: F) -> bool
                                                        where F: Fn(&mut Self, usize) {
        debug_assert!(self.tree.is_null(idx));

        let child_idx = Self::lefti(idx);
        if self.tree.is_null(child_idx) {
            return true;
        }

        self.slots_max.push(idx);

        f(self, child_idx);

        self.slots_max.pop();
        self.tree.is_null(idx)
    }

    /// Returns true if the item is removed after recursive call, false otherwise.
    #[inline(always)]
    fn descend_right_with_slot<F>(&mut self, idx: usize, f: F) -> bool
                                                        where F: Fn(&mut Self, usize) {
        debug_assert!(self.tree.is_null(idx));

        let child_idx = Self::righti(idx);
        if self.tree.is_null(child_idx) {
            return true;
        }

        self.slots_min.push(idx);

        f(self, child_idx);

        self.slots_min.pop();
        self.tree.is_null(idx)
    }

    #[inline(always)]
    fn descend_fill_left(&mut self, idx: usize) {
        self.descend_left_with_slot(idx, |this: &mut Self, child_idx| {
            this.fill_slots_max(child_idx);
        });
    }

    #[inline(always)]
    fn descend_fill_right(&mut self, idx: usize) {
        self.descend_right_with_slot(idx, |this: &mut Self, child_idx| {
            this.fill_slots_min(child_idx);
        });
    }

    /// Returns true if the item is removed after recursive call, false otherwise.
    #[inline(always)]
    fn descend_delete_left<D: TraversalDriver<T>>(&mut self, drv: &D, idx: usize, with_slot: bool) -> bool {
        if with_slot {
            self.descend_left_with_slot(idx,
                        |this: &mut Self, child_idx| this.delete_range_max(drv, child_idx)
            )
        } else {
            self.descend_left(idx,
                        |this: &mut Self, child_idx| this.delete_range_max(drv, child_idx)
            );

            false
        }
    }

    /// Returns true if the item is removed after recursive call, false otherwise.
    #[inline(always)]
    fn descend_delete_right<D: TraversalDriver<T>>(&mut self, drv: &D, idx: usize, with_slot: bool) -> bool {
        if with_slot {
            self.descend_right_with_slot(idx,
                        |this: &mut Self, child_idx| this.delete_range_min(drv, child_idx)
            )
        } else {
            self.descend_right(idx,
                        |this: &mut Self, child_idx| this.delete_range_min(drv, child_idx)
            );

            false
        }
    }
}
<commit_msg>shorter fill_slots_min/max<commit_after>use base::{TeardownTree, TeardownTreeInternal, Item, Node};
use slot_stack::SlotStack;

pub trait TraversalDriver<T: Item> {
    #[inline(always)]
    fn decide(&self, key: &T::Key) -> TraversalDecision;
}

#[derive(Clone, Copy, Debug)]
pub struct TraversalDecision {
    pub left: bool,
    pub right: bool,
}

pub struct DeleteRangeCache {
    pub slots_min: SlotStack, pub slots_max: SlotStack,   // TODO: we no longer need both stacks, one is enough... but removing one causes 3% performance regression
}

impl Clone for DeleteRangeCache {
    fn clone(&self) -> Self {
        debug_assert!(self.slots_min.is_empty() && self.slots_max.is_empty());
        let capacity = self.slots_max.capacity;
        DeleteRangeCache::new(capacity)
    }
}

impl DeleteRangeCache {
    pub fn new(height: usize) -> DeleteRangeCache {
        let slots_min = SlotStack::new(height);
        let slots_max = SlotStack::new(height);
        DeleteRangeCache { slots_min: slots_min, slots_max: slots_max }
    }
}

pub struct DeleteRange<'a, T: 'a+Item> {
    tree: &'a mut TeardownTree<T>,
    slots_min: SlotStack, slots_max: SlotStack,
    pub output: &'a mut Vec<T>
}

impl<'a, T: Item> DeleteRange<'a, T> {
    pub fn new(tree: &'a mut TeardownTree<T>, output: &'a mut Vec<T>) -> DeleteRange<'a, T> {
        let cache = tree.delete_range_cache.take().unwrap();
        DeleteRange { tree: tree, slots_min: cache.slots_min, slots_max: cache.slots_max, output: output }
    }

    /// The items are not guaranteed to be returned in any particular order.
    pub fn delete_range<D: TraversalDriver<T>>(mut self, drv: &mut D) {
        self.delete_range_loop(drv, 0);
        debug_assert!(self.slots_min.is_empty() && self.slots_max.is_empty() && self.tree.traversal_stack.is_empty());

        self.tree.delete_range_cache = Some(DeleteRangeCache { slots_min: self.slots_min, slots_max: self.slots_max });
    }

    //---- helpers ---------------------------------------------------------------------------------
    #[inline(always)]
    fn node(&self, idx: usize) -> &Node<T> {
        self.tree.node(idx)
    }

    #[inline(always)]
    fn item(&mut self, idx: usize) -> &T {
        &self.node(idx).item
    }

    #[inline(always)]
    fn lefti(idx: usize) -> usize {
        TeardownTree::<T>::lefti(idx)
    }

    #[inline(always)]
    fn righti(idx: usize) -> usize {
        TeardownTree::<T>::righti(idx)
    }

    #[inline(always)]
    fn consume(&mut self, idx: usize) {
        let item = self.tree.take(idx);
        self.output.push(item);
    }
}

// v5
impl<'a, T: Item> DeleteRange<'a, T> {
    #[inline]
    fn delete_range_loop<D: TraversalDriver<T>>(&mut self, drv: &D, mut idx: usize) {
        loop {
            if self.tree.is_null(idx) {
                return;
            }

            let decision = drv.decide(&self.item(idx).key());

            if decision.left && decision.right {
                self.consume(idx);
                let removed = self.descend_delete_left(drv, idx, true);
                self.descend_delete_right(drv, idx, removed);
                return;
            } else if decision.left {
                idx = Self::lefti(idx);
            } else {
                debug_assert!(decision.right);
                idx = Self::righti(idx);
            }
        }
    }

    #[inline(never)]
    fn delete_range_min<D: TraversalDriver<T>>(&mut self, drv: &D, idx: usize) {
        let decision = drv.decide(&self.item(idx).key());
        debug_assert!(decision.left);

        if decision.right {
            // the root and the whole left subtree are inside the range
            self.consume(idx);
            self.consume_subtree(Self::lefti(idx));
            self.descend_delete_right(drv, idx, true);
        } else {
            // the root and the right subtree are outside the range
            self.descend_left(idx,
                   |this: &mut Self, child_idx| this.delete_range_min(drv, child_idx)
            );

            if self.slots_min.has_open() {
                self.slots_min.fill(self.tree, idx);
                self.descend_fill_right(idx);
            }
        }
    }

    #[inline(never)]
    fn delete_range_max<D: TraversalDriver<T>>(&mut self, drv: &D, idx: usize) {
        let decision = drv.decide(&self.item(idx).key());
        debug_assert!(decision.right);

        if decision.left {
            // the root and the whole right subtree are inside the range
            self.consume(idx);
            self.consume_subtree(Self::righti(idx));
            self.descend_delete_left(drv, idx, true);
        } else {
            // the root and the left subtree are outside the range
            self.descend_right(idx,
                   |this: &mut Self, child_idx| this.delete_range_max(drv, child_idx)
            );

            if self.slots_max.has_open() {
                self.slots_max.fill(self.tree, idx);
                self.descend_fill_left(idx);
            }
        }
    }

    //---- delete_subtree_* ---------------------------------------------------------------
    #[inline]
    fn consume_subtree(&mut self, root: usize) {
        debug_assert!(self.tree.traversal_stack.is_empty());

        self.tree.traverse_preorder(root, self.output, |tree, output, idx| {
            unsafe {
                let len = output.len();
                debug_assert!(len < output.capacity());
                let p = output.as_mut_ptr().offset(len as isize);
                output.set_len(len + 1);
                tree.move_to(idx, p)
            }
        });
    }

    //---- fill_slots_* -------------------------------------------------------------------
    #[inline(never)]
    fn fill_slots_min(&mut self, idx: usize) -> bool {
        debug_assert!(!self.tree.is_null(idx));

        if self.tree.has_left(idx) {
            let done = self.fill_slots_min(Self::lefti(idx));
            if done {
                return true;
            }
        }

        debug_assert!(self.slots_min.has_open());

        self.slots_min.fill(self.tree, idx);

        let done = !self.descend_fill_right(idx);
        done || !self.slots_min.has_open()
    }

    #[inline(never)]
    fn fill_slots_max(&mut self, idx: usize) -> bool {
        debug_assert!(!self.tree.is_null(idx));

        if self.tree.has_right(idx) {
            let done = self.fill_slots_max(Self::righti(idx));
            if done {
                return true;
            }
        }

        debug_assert!(self.slots_max.has_open());

        self.slots_max.fill(self.tree, idx);

        let done = !self.descend_fill_left(idx);
        done || !self.slots_max.has_open()
    }

    //---- descend_* -------------------------------------------------------------------------------

    #[inline(always)]
    fn descend_left<F>(&mut self, idx: usize, f: F)
        where F: Fn(&mut Self, usize) {
        let child_idx = Self::lefti(idx);
        if !self.tree.is_null(child_idx) {
            f(self, child_idx);
        }
    }

    #[inline(always)]
    fn descend_right<F>(&mut self, idx: usize, f: F)
        where F: Fn(&mut Self, usize) {
        let child_idx = Self::righti(idx);
        if !self.tree.is_null(child_idx) {
            f(self, child_idx);
        }
    }

    /// Returns true if the item is removed after recursive call, false otherwise.
    #[inline(always)]
    fn descend_left_with_slot<F>(&mut self, idx: usize, f: F) -> bool
                                                        where F: Fn(&mut Self, usize) {
        debug_assert!(self.tree.is_null(idx));

        let child_idx = Self::lefti(idx);
        if self.tree.is_null(child_idx) {
            return true;
        }

        self.slots_max.push(idx);

        f(self, child_idx);

        self.slots_max.pop();
        self.tree.is_null(idx)
    }

    /// Returns true if the item is removed after recursive call, false otherwise.
    #[inline(always)]
    fn descend_right_with_slot<F>(&mut self, idx: usize, f: F) -> bool
                                                        where F: Fn(&mut Self, usize) {
        debug_assert!(self.tree.is_null(idx));

        let child_idx = Self::righti(idx);
        if self.tree.is_null(child_idx) {
            return true;
        }

        self.slots_min.push(idx);

        f(self, child_idx);

        self.slots_min.pop();
        self.tree.is_null(idx)
    }

    #[inline(always)]
    fn descend_fill_left(&mut self, idx: usize) -> bool {
        self.descend_left_with_slot(idx, |this: &mut Self, child_idx| {
            this.fill_slots_max(child_idx);
        })
    }

    #[inline(always)]
    fn descend_fill_right(&mut self, idx: usize) -> bool {
        self.descend_right_with_slot(idx, |this: &mut Self, child_idx| {
            this.fill_slots_min(child_idx);
        })
    }

    /// Returns true if the item is removed after recursive call, false otherwise.
    #[inline(always)]
    fn descend_delete_left<D: TraversalDriver<T>>(&mut self, drv: &D, idx: usize, with_slot: bool) -> bool {
        if with_slot {
            self.descend_left_with_slot(idx,
                        |this: &mut Self, child_idx| this.delete_range_max(drv, child_idx)
            )
        } else {
            self.descend_left(idx,
                        |this: &mut Self, child_idx| this.delete_range_max(drv, child_idx)
            );

            false
        }
    }

    /// Returns true if the item is removed after recursive call, false otherwise.
    #[inline(always)]
    fn descend_delete_right<D: TraversalDriver<T>>(&mut self, drv: &D, idx: usize, with_slot: bool) -> bool {
        if with_slot {
            self.descend_right_with_slot(idx,
                        |this: &mut Self, child_idx| this.delete_range_min(drv, child_idx)
            )
        } else {
            self.descend_right(idx,
                        |this: &mut Self, child_idx| this.delete_range_min(drv, child_idx)
            );

            false
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Shader handling.

#![allow(missing_doc)]

use std::fmt;

// Describing shader parameters
// TOOD: Remove GL-isms, especially in the documentation.

/// Number of components in a container type (vectors/matrices)
pub type Dimension = u8;

/// Whether the sampler samples an array texture.
#[deriving(Clone, PartialEq, Show)]
pub enum IsArray { Array, NoArray }

/// Whether the sampler samples a shadow texture (texture with a depth comparison)
#[deriving(Clone, PartialEq, Show)]
pub enum IsShadow { Shadow, NoShadow }

/// Whether the sampler samples a multisample texture.
#[deriving(Clone, PartialEq, Show)]
pub enum IsMultiSample { MultiSample, NoMultiSample }

/// Whether the sampler samples a rectangle texture.
///
/// Rectangle textures are the same as 2D textures, but accessed with absolute texture coordinates
/// (as opposed to the usual, normalized to [0, 1]).
#[deriving(Clone, PartialEq, Show)]
pub enum IsRect { Rect, NoRect }

/// Whether the matrix is column or row major.
#[deriving(Clone, PartialEq, Show)]
pub enum MatrixFormat { ColumnMajor, RowMajor }

/// What texture type this sampler samples from.
///
/// A single sampler cannot be used with multiple texture types.
#[deriving(Clone, PartialEq, Show)]
pub enum SamplerType {
    /// Sample from a buffer.
    SamplerBuffer,
    /// Sample from a 1D texture
    Sampler1D(IsArray, IsShadow),
    /// Sample from a 2D texture
    Sampler2D(IsArray, IsShadow, IsMultiSample, IsRect),
    /// Sample from a 3D texture
    Sampler3D,
    /// Sample from a cubemap.
    SamplerCube(IsShadow),
}

/// Base type of this shader parameter.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum BaseType {
    BaseF32,
    BaseF64,
    BaseI32,
    BaseU32,
    BaseBool,
}

/// Number of components this parameter represents.
#[deriving(Clone, PartialEq, Show)]
pub enum ContainerType {
    /// Scalar value
    Single,
    /// A vector with `Dimension` components.
    Vector(Dimension),
    /// A matrix.
    Matrix(MatrixFormat, Dimension, Dimension),
}

// Describing object data

/// Which program stage this shader represents.
#[allow(missing_doc)]
#[deriving(Show)]
pub enum Stage {
    Vertex,
    Geometry,
    Fragment,
}

// Describing program data

/// Location of a parameter in the program.
pub type Location = uint;

// unable to derive anything for fixed arrays
/// A value that can be uploaded to the device as a uniform.
#[allow(missing_doc)]
pub enum UniformValue {
    ValueI32(i32),
    ValueF32(f32),

    ValueI32Vector2([i32, ..2]),
    ValueI32Vector3([i32, ..3]),
    ValueI32Vector4([i32, ..4]),

    ValueF32Vector2([f32, ..2]),
    ValueF32Vector3([f32, ..3]),
    ValueF32Vector4([f32, ..4]),

    ValueF32Matrix2([[f32, ..2], ..2]),
    ValueF32Matrix3([[f32, ..3], ..3]),
    ValueF32Matrix4([[f32, ..4], ..4]),
}

impl UniformValue {
    /// Whether two `UniformValue`s have the same type.
    pub fn is_same_type(&self, other: &UniformValue) -> bool {
        match (*self, *other) {
            (ValueI32(_), ValueI32(_)) => true,
            (ValueF32(_), ValueF32(_)) => true,

            (ValueI32Vector2(_), ValueI32Vector2(_)) => true,
            (ValueI32Vector3(_), ValueI32Vector3(_)) => true,
            (ValueI32Vector4(_), ValueI32Vector4(_)) => true,

            (ValueF32Vector2(_), ValueF32Vector2(_)) => true,
            (ValueF32Vector3(_), ValueF32Vector3(_)) => true,
            (ValueF32Vector4(_), ValueF32Vector4(_)) => true,

            (ValueF32Matrix2(_), ValueF32Matrix2(_)) => true,
            (ValueF32Matrix3(_), ValueF32Matrix3(_)) => true,
            (ValueF32Matrix4(_), ValueF32Matrix4(_)) => true,

            _ => false,
        }
    }
}

impl Clone for UniformValue {
    fn clone(&self) -> UniformValue {
        match *self {
            ValueI32(val)      => ValueI32(val),
            ValueF32(val)      => ValueF32(val),

            ValueI32Vector2(v) => ValueI32Vector2(v),
            ValueI32Vector3(v) => ValueI32Vector3(v),
            ValueI32Vector4(v) => ValueI32Vector4(v),

            ValueF32Vector2(v) => ValueF32Vector2(v),
            ValueF32Vector3(v) => ValueF32Vector3(v),
            ValueF32Vector4(v) => ValueF32Vector4(v),

            ValueF32Matrix2(m) => ValueF32Matrix2(m),
            ValueF32Matrix3(m) => ValueF32Matrix3(m),
            ValueF32Matrix4(m) => ValueF32Matrix4(m),
        }
    }
}

impl fmt::Show for UniformValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ValueI32(x)            => write!(f, "ValueI32({})", x),
            ValueF32(x)            => write!(f, "ValueF32({})", x),

            ValueI32Vector2(ref v) => write!(f, "ValueI32Vector2({})", v.as_slice()),
            ValueI32Vector3(ref v) => write!(f, "ValueI32Vector3({})", v.as_slice()),
            ValueI32Vector4(ref v) => write!(f, "ValueI32Vector4({})", v.as_slice()),

            ValueF32Vector2(ref v) => write!(f, "ValueF32Vector2({})", v.as_slice()),
            ValueF32Vector3(ref v) => write!(f, "ValueF32Vector3({})", v.as_slice()),
            ValueF32Vector4(ref v) => write!(f, "ValueF32Vector4({})", v.as_slice()),

            ValueF32Matrix2(ref m) => {
                try!(write!(f, "ValueF32Matrix2("));
                for v in m.iter() {
                    try!(write!(f, "{}", v.as_slice()));
                }
                write!(f, ")")
            },
            ValueF32Matrix3(ref m) => {
                try!(write!(f, "ValueF32Matrix3("));
                for v in m.iter() {
                    try!(write!(f, "{}", v.as_slice()));
                }
                write!(f, ")")
            },
            ValueF32Matrix4(ref m) => {
                try!(write!(f, "ValueF32Matrix4("));
                for v in m.iter() {
                    try!(write!(f, "{}", v.as_slice()));
                }
                write!(f, ")")
            },
        }
    }
}

/// Vertex information that a shader takes as input.
#[deriving(Clone, PartialEq, Show)]
pub struct Attribute {
    /// Name of this attribute.
    pub name: String,
    /// Vertex attribute binding.
    pub location: uint,
    /// Number of elements this attribute represents.
    pub count: uint,
    /// Type that this attribute is composed of.
    pub base_type: BaseType,
    /// "Scalarness" of this attribute.
    pub container: ContainerType,
}

/// Uniform, a type of shader parameter representing data passed to the program.
#[deriving(Clone, PartialEq, Show)]
pub struct UniformVar {
    /// Name of this uniform.
    pub name: String,
    /// Location of this uniform in the program.
    pub location: Location,
    /// Number of elements this uniform represents.
    pub count: uint,
    /// Type that this uniform is composed of
    pub base_type: BaseType,
    /// "Scalarness" of this uniform.
    pub container: ContainerType,
}

/// A uniform block.
#[deriving(Clone, PartialEq, Show)]
pub struct BlockVar {
    /// Name of this uniform block.
    pub name: String,
    /// Size (in bytes) of this uniform block's data.
    pub size: uint,
    /// What program stage this uniform block can be used in, as a bitflag.
    pub usage: u8,
}

/// Sampler, a type of shader parameter representing a texture that can be sampled.
#[deriving(Clone, PartialEq, Show)]
pub struct SamplerVar {
    /// Name of this sampler variable.
    pub name: String,
    /// Location of this sampler in the program.
    pub location: Location,
    /// Base type for the sampler.
    pub base_type: BaseType,
    /// Type of this sampler.
    pub sampler_type: SamplerType,
}

/// Metadata about a program.
#[deriving(Clone, PartialEq, Show)]
pub struct ProgramInfo {
    /// Attributes in the program.
    pub attributes: Vec<Attribute>,
    /// Uniforms in the program
    pub uniforms: Vec<UniformVar>,
    /// Uniform blocks in the program
    pub blocks: Vec<BlockVar>,
    /// Samplers in the program
    pub textures: Vec<SamplerVar>,
}

/// Error type for trying to store a UniformValue in a UniformVar.
#[deriving(Show)]
pub enum CompatibilityError {
    /// Array sizes differ between the value and the var (trying to upload a vec2 as a vec4, etc)
    ErrorArraySize,
    /// Base types differ between the value and the var (trying to upload a f32 as a u16, etc)
    ErrorBaseType,
    /// Container-ness differs between the value and the var (trying to upload a scalar as a vec4,
    /// etc)
    ErrorContainer,
}

impl UniformVar {
    /// Whether a value is compatible with this variable. That is, whether the value can be stored
    /// in this variable.
    pub fn is_compatible(&self, value: &UniformValue) -> Result<(), CompatibilityError> {
        if self.count != 1 {
            return Err(ErrorArraySize)
        }
        match (self.base_type, self.container, *value) {
            (BaseI32, Single, ValueI32(_)) => Ok(()),
            (BaseF32, Single, ValueF32(_)) => Ok(()),

            (BaseF32, Vector(2), ValueF32Vector2(_)) => Ok(()),
            (BaseF32, Vector(3), ValueF32Vector3(_)) => Ok(()),
            (BaseF32, Vector(4), ValueF32Vector4(_)) => Ok(()),

            (BaseI32, Vector(2), ValueI32Vector2(_)) => Ok(()),
            (BaseI32, Vector(3), ValueI32Vector3(_)) => Ok(()),
            (BaseI32, Vector(4), ValueI32Vector4(_)) => Ok(()),

            (BaseF32, Matrix(_, 2,2), ValueF32Matrix2(_)) => Ok(()),
            (BaseF32, Matrix(_, 3,3), ValueF32Matrix3(_)) => Ok(()),
            (BaseF32, Matrix(_, 4,4), ValueF32Matrix4(_)) => Ok(()),

            _ => Err(ErrorBaseType)
        }
    }
}

/// Like `MaybeOwned` but for u8.
#[allow(missing_doc)]
#[deriving(Show, PartialEq, Clone)]
pub enum Bytes {
    StaticBytes(&'static [u8]),
    OwnedBytes(Vec<u8>),
}

impl Bytes {
    /// Get the byte data as a slice.
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        match *self {
            StaticBytes(ref b) => b.as_slice(),
            OwnedBytes(ref b) => b.as_slice(),
        }
    }
}

/// A type storing shader source for different graphics APIs and versions.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub struct ShaderSource {
    pub glsl_120: Option<Bytes>,
    pub glsl_150: Option<Bytes>,
    // TODO: hlsl_sm_N...
}

/// An error type for creating programs.
#[deriving(Clone, PartialEq, Show)]
pub enum CreateShaderError {
    /// The device does not support any of the shaders supplied.
    NoSupportedShaderProvided,
    /// The shader failed to compile.
    ShaderCompilationFailed
}

/// Shader model supported by the device, corresponds to the HLSL shader models.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, PartialOrd, Show)]
pub enum ShaderModel {
    ModelUnsupported,
    Model30,
    Model40,
    Model41,
    Model50,
}

impl ShaderModel {
    /// Return the shader model as a numeric value.
    ///
    /// Model30 turns to 30, etc.
    pub fn to_number(&self) -> u8 {
        match *self {
            ModelUnsupported => 0,  //ModelAncient, ModelPreHistoric, ModelMyGrandpaLikes
            Model30 => 30,
            Model40 => 40,
            Model41 => 41,
            Model50 => 50,
        }
    }
}
<commit_msg>Derived PartialEq for shader Stage<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Shader handling.

#![allow(missing_doc)]

use std::fmt;

// Describing shader parameters
// TOOD: Remove GL-isms, especially in the documentation.

/// Number of components in a container type (vectors/matrices)
pub type Dimension = u8;

/// Whether the sampler samples an array texture.
#[deriving(Clone, PartialEq, Show)]
pub enum IsArray { Array, NoArray }

/// Whether the sampler samples a shadow texture (texture with a depth comparison)
#[deriving(Clone, PartialEq, Show)]
pub enum IsShadow { Shadow, NoShadow }

/// Whether the sampler samples a multisample texture.
#[deriving(Clone, PartialEq, Show)]
pub enum IsMultiSample { MultiSample, NoMultiSample }

/// Whether the sampler samples a rectangle texture.
///
/// Rectangle textures are the same as 2D textures, but accessed with absolute texture coordinates
/// (as opposed to the usual, normalized to [0, 1]).
#[deriving(Clone, PartialEq, Show)]
pub enum IsRect { Rect, NoRect }

/// Whether the matrix is column or row major.
#[deriving(Clone, PartialEq, Show)]
pub enum MatrixFormat { ColumnMajor, RowMajor }

/// What texture type this sampler samples from.
///
/// A single sampler cannot be used with multiple texture types.
#[deriving(Clone, PartialEq, Show)]
pub enum SamplerType {
    /// Sample from a buffer.
    SamplerBuffer,
    /// Sample from a 1D texture
    Sampler1D(IsArray, IsShadow),
    /// Sample from a 2D texture
    Sampler2D(IsArray, IsShadow, IsMultiSample, IsRect),
    /// Sample from a 3D texture
    Sampler3D,
    /// Sample from a cubemap.
    SamplerCube(IsShadow),
}

/// Base type of this shader parameter.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum BaseType {
    BaseF32,
    BaseF64,
    BaseI32,
    BaseU32,
    BaseBool,
}

/// Number of components this parameter represents.
#[deriving(Clone, PartialEq, Show)]
pub enum ContainerType {
    /// Scalar value
    Single,
    /// A vector with `Dimension` components.
    Vector(Dimension),
    /// A matrix.
    Matrix(MatrixFormat, Dimension, Dimension),
}

// Describing object data

/// Which program stage this shader represents.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub enum Stage {
    Vertex,
    Geometry,
    Fragment,
}

// Describing program data

/// Location of a parameter in the program.
pub type Location = uint;

// unable to derive anything for fixed arrays
/// A value that can be uploaded to the device as a uniform.
#[allow(missing_doc)]
pub enum UniformValue {
    ValueI32(i32),
    ValueF32(f32),

    ValueI32Vector2([i32, ..2]),
    ValueI32Vector3([i32, ..3]),
    ValueI32Vector4([i32, ..4]),

    ValueF32Vector2([f32, ..2]),
    ValueF32Vector3([f32, ..3]),
    ValueF32Vector4([f32, ..4]),

    ValueF32Matrix2([[f32, ..2], ..2]),
    ValueF32Matrix3([[f32, ..3], ..3]),
    ValueF32Matrix4([[f32, ..4], ..4]),
}

impl UniformValue {
    /// Whether two `UniformValue`s have the same type.
    pub fn is_same_type(&self, other: &UniformValue) -> bool {
        match (*self, *other) {
            (ValueI32(_), ValueI32(_)) => true,
            (ValueF32(_), ValueF32(_)) => true,

            (ValueI32Vector2(_), ValueI32Vector2(_)) => true,
            (ValueI32Vector3(_), ValueI32Vector3(_)) => true,
            (ValueI32Vector4(_), ValueI32Vector4(_)) => true,

            (ValueF32Vector2(_), ValueF32Vector2(_)) => true,
            (ValueF32Vector3(_), ValueF32Vector3(_)) => true,
            (ValueF32Vector4(_), ValueF32Vector4(_)) => true,

            (ValueF32Matrix2(_), ValueF32Matrix2(_)) => true,
            (ValueF32Matrix3(_), ValueF32Matrix3(_)) => true,
            (ValueF32Matrix4(_), ValueF32Matrix4(_)) => true,

            _ => false,
        }
    }
}

impl Clone for UniformValue {
    fn clone(&self) -> UniformValue {
        match *self {
            ValueI32(val)      => ValueI32(val),
            ValueF32(val)      => ValueF32(val),

            ValueI32Vector2(v) => ValueI32Vector2(v),
            ValueI32Vector3(v) => ValueI32Vector3(v),
            ValueI32Vector4(v) => ValueI32Vector4(v),

            ValueF32Vector2(v) => ValueF32Vector2(v),
            ValueF32Vector3(v) => ValueF32Vector3(v),
            ValueF32Vector4(v) => ValueF32Vector4(v),

            ValueF32Matrix2(m) => ValueF32Matrix2(m),
            ValueF32Matrix3(m) => ValueF32Matrix3(m),
            ValueF32Matrix4(m) => ValueF32Matrix4(m),
        }
    }
}

impl fmt::Show for UniformValue {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ValueI32(x)            => write!(f, "ValueI32({})", x),
            ValueF32(x)            => write!(f, "ValueF32({})", x),

            ValueI32Vector2(ref v) => write!(f, "ValueI32Vector2({})", v.as_slice()),
            ValueI32Vector3(ref v) => write!(f, "ValueI32Vector3({})", v.as_slice()),
            ValueI32Vector4(ref v) => write!(f, "ValueI32Vector4({})", v.as_slice()),

            ValueF32Vector2(ref v) => write!(f, "ValueF32Vector2({})", v.as_slice()),
            ValueF32Vector3(ref v) => write!(f, "ValueF32Vector3({})", v.as_slice()),
            ValueF32Vector4(ref v) => write!(f, "ValueF32Vector4({})", v.as_slice()),

            ValueF32Matrix2(ref m) => {
                try!(write!(f, "ValueF32Matrix2("));
                for v in m.iter() {
                    try!(write!(f, "{}", v.as_slice()));
                }
                write!(f, ")")
            },
            ValueF32Matrix3(ref m) => {
                try!(write!(f, "ValueF32Matrix3("));
                for v in m.iter() {
                    try!(write!(f, "{}", v.as_slice()));
                }
                write!(f, ")")
            },
            ValueF32Matrix4(ref m) => {
                try!(write!(f, "ValueF32Matrix4("));
                for v in m.iter() {
                    try!(write!(f, "{}", v.as_slice()));
                }
                write!(f, ")")
            },
        }
    }
}

/// Vertex information that a shader takes as input.
#[deriving(Clone, PartialEq, Show)]
pub struct Attribute {
    /// Name of this attribute.
    pub name: String,
    /// Vertex attribute binding.
    pub location: uint,
    /// Number of elements this attribute represents.
    pub count: uint,
    /// Type that this attribute is composed of.
    pub base_type: BaseType,
    /// "Scalarness" of this attribute.
    pub container: ContainerType,
}

/// Uniform, a type of shader parameter representing data passed to the program.
#[deriving(Clone, PartialEq, Show)]
pub struct UniformVar {
    /// Name of this uniform.
    pub name: String,
    /// Location of this uniform in the program.
    pub location: Location,
    /// Number of elements this uniform represents.
    pub count: uint,
    /// Type that this uniform is composed of
    pub base_type: BaseType,
    /// "Scalarness" of this uniform.
    pub container: ContainerType,
}

/// A uniform block.
#[deriving(Clone, PartialEq, Show)]
pub struct BlockVar {
    /// Name of this uniform block.
    pub name: String,
    /// Size (in bytes) of this uniform block's data.
    pub size: uint,
    /// What program stage this uniform block can be used in, as a bitflag.
    pub usage: u8,
}

/// Sampler, a type of shader parameter representing a texture that can be sampled.
#[deriving(Clone, PartialEq, Show)]
pub struct SamplerVar {
    /// Name of this sampler variable.
    pub name: String,
    /// Location of this sampler in the program.
    pub location: Location,
    /// Base type for the sampler.
    pub base_type: BaseType,
    /// Type of this sampler.
    pub sampler_type: SamplerType,
}

/// Metadata about a program.
#[deriving(Clone, PartialEq, Show)]
pub struct ProgramInfo {
    /// Attributes in the program.
    pub attributes: Vec<Attribute>,
    /// Uniforms in the program
    pub uniforms: Vec<UniformVar>,
    /// Uniform blocks in the program
    pub blocks: Vec<BlockVar>,
    /// Samplers in the program
    pub textures: Vec<SamplerVar>,
}

/// Error type for trying to store a UniformValue in a UniformVar.
#[deriving(Show)]
pub enum CompatibilityError {
    /// Array sizes differ between the value and the var (trying to upload a vec2 as a vec4, etc)
    ErrorArraySize,
    /// Base types differ between the value and the var (trying to upload a f32 as a u16, etc)
    ErrorBaseType,
    /// Container-ness differs between the value and the var (trying to upload a scalar as a vec4,
    /// etc)
    ErrorContainer,
}

impl UniformVar {
    /// Whether a value is compatible with this variable. That is, whether the value can be stored
    /// in this variable.
    pub fn is_compatible(&self, value: &UniformValue) -> Result<(), CompatibilityError> {
        if self.count != 1 {
            return Err(ErrorArraySize)
        }
        match (self.base_type, self.container, *value) {
            (BaseI32, Single, ValueI32(_)) => Ok(()),
            (BaseF32, Single, ValueF32(_)) => Ok(()),

            (BaseF32, Vector(2), ValueF32Vector2(_)) => Ok(()),
            (BaseF32, Vector(3), ValueF32Vector3(_)) => Ok(()),
            (BaseF32, Vector(4), ValueF32Vector4(_)) => Ok(()),

            (BaseI32, Vector(2), ValueI32Vector2(_)) => Ok(()),
            (BaseI32, Vector(3), ValueI32Vector3(_)) => Ok(()),
            (BaseI32, Vector(4), ValueI32Vector4(_)) => Ok(()),

            (BaseF32, Matrix(_, 2,2), ValueF32Matrix2(_)) => Ok(()),
            (BaseF32, Matrix(_, 3,3), ValueF32Matrix3(_)) => Ok(()),
            (BaseF32, Matrix(_, 4,4), ValueF32Matrix4(_)) => Ok(()),

            _ => Err(ErrorBaseType)
        }
    }
}

/// Like `MaybeOwned` but for u8.
#[allow(missing_doc)]
#[deriving(Show, PartialEq, Clone)]
pub enum Bytes {
    StaticBytes(&'static [u8]),
    OwnedBytes(Vec<u8>),
}

impl Bytes {
    /// Get the byte data as a slice.
    pub fn as_slice<'a>(&'a self) -> &'a [u8] {
        match *self {
            StaticBytes(ref b) => b.as_slice(),
            OwnedBytes(ref b) => b.as_slice(),
        }
    }
}

/// A type storing shader source for different graphics APIs and versions.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, Show)]
pub struct ShaderSource {
    pub glsl_120: Option<Bytes>,
    pub glsl_150: Option<Bytes>,
    // TODO: hlsl_sm_N...
}

/// An error type for creating programs.
#[deriving(Clone, PartialEq, Show)]
pub enum CreateShaderError {
    /// The device does not support any of the shaders supplied.
    NoSupportedShaderProvided,
    /// The shader failed to compile.
    ShaderCompilationFailed
}

/// Shader model supported by the device, corresponds to the HLSL shader models.
#[allow(missing_doc)]
#[deriving(Clone, PartialEq, PartialOrd, Show)]
pub enum ShaderModel {
    ModelUnsupported,
    Model30,
    Model40,
    Model41,
    Model50,
}

impl ShaderModel {
    /// Return the shader model as a numeric value.
    ///
    /// Model30 turns to 30, etc.
    pub fn to_number(&self) -> u8 {
        match *self {
            ModelUnsupported => 0,  //ModelAncient, ModelPreHistoric, ModelMyGrandpaLikes
            Model30 => 30,
            Model40 => 40,
            Model41 => 41,
            Model50 => 50,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Ilkka Rauta
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::iter::repeat;

use gl;

use super::super::util::slice_to_string;
use super::Program;

/// See the `type` argument of glGetActiveAttrib (the sixth one) for the set of values this enum's
/// variants correspond to.
#[derive(Debug)]
pub enum ShaderAttributeType {
    Float,
    FloatVec2,
    FloatVec3,
    FloatVec4,
    FloatMat2,
    FloatMat3,
    FloatMat4,
    FloatMat2x3,
    FloatMat2x4,
    FloatMat3x2,
    FloatMat3x4,
    FloatMat4x2,
    FloatMat4x3,
    Int,
    IntVec2,
    IntVec3,
    IntVec4,
    UnsignedInt,
    UnsignedIntVec2,
    UnsignedIntVec3,
    UnsignedIntVec4
}

/// Contains information on shader program's (vertex) attributes.
#[derive(Debug)]
pub struct ShaderAttributeInfo {
    /// List of attributes.
    pub attributes: Vec<ShaderAttribute>
}

impl ShaderAttributeInfo {
    /// A convenience method to find an attribute by name. Not particularly optimized. It might be
    /// a good idea to only do one lookup by name and use the integer indices, borrows, or
    /// something similar from there on.
    pub fn get_attribute(&self, name: &str) -> Option<&ShaderAttribute> {
        for attribute in self.attributes.iter() {
            if attribute.name == name {
                return Some(attribute);
            }
        }
        None
    }
}

/// Describes an (active) attribute of a shader program.
#[derive(Debug)]
pub struct ShaderAttribute {
    /// Name of the attribute
    pub name: String,
    /// Index of the attribute
    pub location: i32,
    /// Data type of the attribute
    pub attribute_type: Option<ShaderAttributeType>,
    pub size: i32
}

pub fn make_attribute_info_vec(program: &Program) -> ShaderAttributeInfo {
    let attr_count = program.get_value(gl::ACTIVE_ATTRIBUTES);
    let max_length = program.get_value(gl::ACTIVE_ATTRIBUTE_MAX_LENGTH);
    let mut name_vec: Vec<u8> = repeat(0u8).take(max_length as usize).collect();
    ShaderAttributeInfo { attributes: (0..attr_count as usize).map(|i| {
        let mut actual_length = 0;
        let mut size = 0;
        let mut gl_type = 0;
        let name_vec_ptr = name_vec.as_mut_ptr() as *mut i8;
        unsafe {
            gl::GetActiveAttrib(program.id, i as u32, name_vec.len() as i32, &mut actual_length, &mut size, &mut gl_type, name_vec_ptr);
        }
        let name = slice_to_string(&name_vec[0..actual_length as usize]);
        let attribute_type = attribute_type_from_u32(gl_type);
        let location = program.get_attribute_location(&name[..]);
        ShaderAttribute {
            name: name,
            location: location,
            attribute_type: attribute_type,
            size: size
        }
    }).collect()}
}

fn attribute_type_from_u32(gl_type: u32) -> Option<ShaderAttributeType> {
    match gl_type {
        gl::FLOAT => Some(ShaderAttributeType::Float),
        gl::FLOAT_VEC2 => Some(ShaderAttributeType::FloatVec2),
        gl::FLOAT_VEC3 => Some(ShaderAttributeType::FloatVec3),
        gl::FLOAT_VEC4 => Some(ShaderAttributeType::FloatVec4),
        gl::FLOAT_MAT2 => Some(ShaderAttributeType::FloatMat2),
        gl::FLOAT_MAT3 => Some(ShaderAttributeType::FloatMat3),
        gl::FLOAT_MAT4 => Some(ShaderAttributeType::FloatMat4),
        gl::FLOAT_MAT2x3 => Some(ShaderAttributeType::FloatMat2x3),
        gl::FLOAT_MAT2x4 => Some(ShaderAttributeType::FloatMat2x4),
        gl::FLOAT_MAT3x2 => Some(ShaderAttributeType::FloatMat3x2),
        gl::FLOAT_MAT3x4 => Some(ShaderAttributeType::FloatMat3x4),
        gl::FLOAT_MAT4x2 => Some(ShaderAttributeType::FloatMat4x2),
        gl::FLOAT_MAT4x3 => Some(ShaderAttributeType::FloatMat4x3),
        gl::INT => Some(ShaderAttributeType::Int),
        gl::INT_VEC2 => Some(ShaderAttributeType::IntVec2),
        gl::INT_VEC3 => Some(ShaderAttributeType::IntVec3),
        gl::INT_VEC4 => Some(ShaderAttributeType::IntVec4),
        gl::UNSIGNED_INT => Some(ShaderAttributeType::UnsignedInt),
        gl::UNSIGNED_INT_VEC2 => Some(ShaderAttributeType::UnsignedIntVec2),
        gl::UNSIGNED_INT_VEC3 => Some(ShaderAttributeType::UnsignedIntVec3),
        gl::UNSIGNED_INT_VEC4 => Some(ShaderAttributeType::UnsignedIntVec4),
        _ => None
    }
}<commit_msg>Change ShaderAttributeType to work without Option.<commit_after>// Copyright 2015 Ilkka Rauta
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::iter::repeat;

use gl;

use super::super::util::slice_to_string;
use super::Program;

/// See the `type` argument of glGetActiveAttrib (the sixth one) for the set of values this enum's
/// variants correspond to. Notice the UnrecognizedType that handles the cases this library
/// doesn't know of yet.
#[derive(Debug)]
pub enum ShaderAttributeType {
    Float,
    FloatVec2,
    FloatVec3,
    FloatVec4,
    FloatMat2,
    FloatMat3,
    FloatMat4,
    FloatMat2x3,
    FloatMat2x4,
    FloatMat3x2,
    FloatMat3x4,
    FloatMat4x2,
    FloatMat4x3,
    Int,
    IntVec2,
    IntVec3,
    IntVec4,
    UnsignedInt,
    UnsignedIntVec2,
    UnsignedIntVec3,
    UnsignedIntVec4,
    UnrecognizedType(u32)
}

/// Contains information on shader program's (vertex) attributes.
#[derive(Debug)]
pub struct ShaderAttributeInfo {
    /// List of attributes.
    pub attributes: Vec<ShaderAttribute>
}

impl ShaderAttributeInfo {
    /// A convenience method to find an attribute by name. Not particularly optimized. It might be
    /// a good idea to only do one lookup by name and use the integer indices, borrows, or
    /// something similar from there on.
    pub fn get_attribute(&self, name: &str) -> Option<&ShaderAttribute> {
        for attribute in self.attributes.iter() {
            if attribute.name == name {
                return Some(attribute);
            }
        }
        None
    }
}

/// Describes an (active) attribute of a shader program.
#[derive(Debug)]
pub struct ShaderAttribute {
    /// Name of the attribute
    pub name: String,
    /// Index of the attribute
    pub location: i32,
    /// Data type of the attribute
    pub attribute_type: ShaderAttributeType,
    pub size: i32
}

pub fn make_attribute_info_vec(program: &Program) -> ShaderAttributeInfo {
    let attr_count = program.get_value(gl::ACTIVE_ATTRIBUTES);
    let max_length = program.get_value(gl::ACTIVE_ATTRIBUTE_MAX_LENGTH);
    let mut name_vec: Vec<u8> = repeat(0u8).take(max_length as usize).collect();
    ShaderAttributeInfo { attributes: (0..attr_count as usize).map(|i| {
        let mut actual_length = 0;
        let mut size = 0;
        let mut gl_type = 0;
        let name_vec_ptr = name_vec.as_mut_ptr() as *mut i8;
        unsafe {
            gl::GetActiveAttrib(program.id, i as u32, name_vec.len() as i32, &mut actual_length, &mut size, &mut gl_type, name_vec_ptr);
        }
        let name = slice_to_string(&name_vec[0..actual_length as usize]);
        let attribute_type = attribute_type_from_u32(gl_type);
        let location = program.get_attribute_location(&name[..]);
        ShaderAttribute {
            name: name,
            location: location,
            attribute_type: attribute_type,
            size: size
        }
    }).collect()}
}

fn attribute_type_from_u32(gl_type: u32) -> ShaderAttributeType {
    match gl_type {
        gl::FLOAT => ShaderAttributeType::Float,
        gl::FLOAT_VEC2 => ShaderAttributeType::FloatVec2,
        gl::FLOAT_VEC3 => ShaderAttributeType::FloatVec3,
        gl::FLOAT_VEC4 => ShaderAttributeType::FloatVec4,
        gl::FLOAT_MAT2 => ShaderAttributeType::FloatMat2,
        gl::FLOAT_MAT3 => ShaderAttributeType::FloatMat3,
        gl::FLOAT_MAT4 => ShaderAttributeType::FloatMat4,
        gl::FLOAT_MAT2x3 => ShaderAttributeType::FloatMat2x3,
        gl::FLOAT_MAT2x4 => ShaderAttributeType::FloatMat2x4,
        gl::FLOAT_MAT3x2 => ShaderAttributeType::FloatMat3x2,
        gl::FLOAT_MAT3x4 => ShaderAttributeType::FloatMat3x4,
        gl::FLOAT_MAT4x2 => ShaderAttributeType::FloatMat4x2,
        gl::FLOAT_MAT4x3 => ShaderAttributeType::FloatMat4x3,
        gl::INT => ShaderAttributeType::Int,
        gl::INT_VEC2 => ShaderAttributeType::IntVec2,
        gl::INT_VEC3 => ShaderAttributeType::IntVec3,
        gl::INT_VEC4 => ShaderAttributeType::IntVec4,
        gl::UNSIGNED_INT => ShaderAttributeType::UnsignedInt,
        gl::UNSIGNED_INT_VEC2 => ShaderAttributeType::UnsignedIntVec2,
        gl::UNSIGNED_INT_VEC3 => ShaderAttributeType::UnsignedIntVec3,
        gl::UNSIGNED_INT_VEC4 => ShaderAttributeType::UnsignedIntVec4,
        _ => ShaderAttributeType::UnrecognizedType(gl_type)
    }
}<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
extern crate ctrlc;
extern crate env_logger;
extern crate libllama;

use std::env;
use std::io::{Read, stdin, stdout, Write};
use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};
use std::sync::Arc;
use std::time::{Duration, Instant};

use libllama::{dbgcore, hwcore};

fn from_hex(string: &str) -> Result<u32, std::num::ParseIntError> {
    let slice = if string.starts_with("0x") {
        &string[2..]
    } else {
        &string[..]
    };
    u32::from_str_radix(slice, 16)
}

static SIGINT_REQUESTED: AtomicBool = ATOMIC_BOOL_INIT;

fn sigint_trap() {
    ctrlc::set_handler(|| SIGINT_REQUESTED.store(true, Ordering::SeqCst));
}

fn sigint_triggered() -> bool {
    SIGINT_REQUESTED.compare_and_swap(true, false, Ordering::SeqCst)
}

/// Prints memory to the screen based on provided address, number of bytes
/// Command format: "mem <start address hex> [# bytes hex]"
///
/// `args`: Iterator over &str items
fn handle_mem_command<'a, It>(debugger: &mut dbgcore::DbgCore, mut args: It)
    where It: Iterator<Item=&'a str> {

    let (start_str, num_str) = match (args.next(), args.next()) {
        (Some(ss), Some(ns)) => (ss, ns),
        (Some(ss), None) => (ss, ss),
        (None, _) => { println!("Usage: `mem <start> [num]"); return }
    };

    let (start, num) = match from_hex(start_str).and_then(|s| Ok((s, from_hex(num_str)?))) {
        Ok((s, n)) if n > 0 => (s, n),
        Ok((s, _)) => (s, 1),
        _ => { println!("Error: could not parse hex value!"); return }
    };

    trace!("Printing {} bytes of RAM starting at 0x{:08X}", num, start);

    let ctx = debugger.get_ctx();
    print!("{:02X}", ctx.read_mem(start));
    for addr in start+1 .. (start + num) {
        print!(" {:02X}", ctx.read_mem(addr));
    }
    println!("");
}

/// Controls debugger behavior based on user-provided commands
///
/// `command`: Iterator over &str items
fn handle_command<'a, It>(debugger: &mut dbgcore::DbgCore, mut command: It) -> bool
    where It: Iterator<Item=&'a str> {
    let mut is_paused = true;

    match command.next() {
        Some("run") => { debugger.resume(); is_paused = false; },
        Some("mem") => handle_mem_command(debugger, command),
        Some("regs") => {
            let ctx = debugger.get_ctx();
            for i in 0..16 {
                println!("R{} = 0x{:08X}", i, ctx.read_reg(i));
            }
        }
        Some("quit") | Some("exit") => {
            debugger.hwcore_mut().stop();
            // TODO: Cleaner exit?
            std::process::exit(0);
        }
        None => println!("Error: No command"),
        Some(unk_cmd @ _) => println!("Error: Unrecognized command `{}`", unk_cmd),
    }

    return is_paused;
}

fn run_emulator(code: &Vec<u8>, load_offset: u32, entrypoint: u32) {
    let mem = hwcore::map_memory_regions();
    mem.write_buf(load_offset, code.as_slice());

    let mut hwcore = hwcore::HwCore::new(entrypoint, mem);
    let mut debugger = dbgcore::DbgCore::bind(hwcore);
    debugger.hwcore_mut().start();

    sigint_trap();
    let mut is_paused = false;
    loop {
        if sigint_triggered() {
            if is_paused { std::process::exit(0) }
            debugger.pause();
            is_paused = true;
        }

        if is_paused {
            // Print prompt text
            print!(" > ");
            stdout().flush();

            // Handle pause command
            let mut input = String::new();
            stdin().read_line(&mut input).unwrap();
            is_paused = handle_command(&mut debugger, input.trim_right().split_whitespace());
        } else {
            std::thread::sleep(Duration::from_millis(100));
        }
    }

    debugger.hwcore_mut().stop();
}

fn main() {
    env_logger::init().unwrap();

    let filename = env::args().nth(1).unwrap();
    let load_offset = from_hex(&env::args().nth(2).unwrap()).unwrap();
    let entrypoint = from_hex(&env::args().nth(3).unwrap()).unwrap();

    let mut file = std::fs::File::open(filename).unwrap();
    let file_data = file.metadata().unwrap();
    let file_size = file_data.len();

    let mut filebuf = Vec::<u8>::with_capacity(file_size as usize);

    let size = file.read_to_end(&mut filebuf).unwrap();
    info!("Reading {} bytes from input file", size);
    assert!(size == file_size as usize);

    run_emulator(&filebuf, load_offset, entrypoint);
}
<commit_msg>Reset SIGINT handler on pause for better ^C handling<commit_after>#[macro_use]
extern crate log;
extern crate ctrlc;
extern crate env_logger;
extern crate libllama;

use std::env;
use std::io::{Read, stdin, stdout, Write};
use std::sync::atomic::{AtomicBool, Ordering, ATOMIC_BOOL_INIT};
use std::sync::Arc;
use std::time::{Duration, Instant};

use libllama::{dbgcore, hwcore};

fn from_hex(string: &str) -> Result<u32, std::num::ParseIntError> {
    let slice = if string.starts_with("0x") {
        &string[2..]
    } else {
        &string[..]
    };
    u32::from_str_radix(slice, 16)
}

static SIGINT_REQUESTED: AtomicBool = ATOMIC_BOOL_INIT;

#[inline(always)]
fn sigint_trap() {
    ctrlc::set_handler(|| SIGINT_REQUESTED.store(true, Ordering::SeqCst));
}

#[inline(always)]
fn sigint_reset() {
    ctrlc::set_handler(|| std::process::exit(0));
}

#[inline(always)]
fn sigint_triggered() -> bool {
    SIGINT_REQUESTED.compare_and_swap(true, false, Ordering::SeqCst)
}

/// Prints memory to the screen based on provided address, number of bytes
/// Command format: "mem <start address hex> [# bytes hex]"
///
/// `args`: Iterator over &str items
fn handle_mem_command<'a, It>(debugger: &mut dbgcore::DbgCore, mut args: It)
    where It: Iterator<Item=&'a str> {

    let (start_str, num_str) = match (args.next(), args.next()) {
        (Some(ss), Some(ns)) => (ss, ns),
        (Some(ss), None) => (ss, ss),
        (None, _) => { println!("Usage: `mem <start> [num]"); return }
    };

    let (start, num) = match from_hex(start_str).and_then(|s| Ok((s, from_hex(num_str)?))) {
        Ok((s, n)) if n > 0 => (s, n),
        Ok((s, _)) => (s, 1),
        _ => { println!("Error: could not parse hex value!"); return }
    };

    trace!("Printing {} bytes of RAM starting at 0x{:08X}", num, start);

    let ctx = debugger.get_ctx();
    print!("{:02X}", ctx.read_mem(start));
    for addr in start+1 .. (start + num) {
        print!(" {:02X}", ctx.read_mem(addr));
    }
    println!("");
}

/// Controls debugger behavior based on user-provided commands
///
/// `command`: Iterator over &str items
fn handle_command<'a, It>(debugger: &mut dbgcore::DbgCore, mut command: It) -> bool
    where It: Iterator<Item=&'a str> {
    let mut is_paused = true;

    match command.next() {
        Some("run") => { debugger.resume(); is_paused = false; },
        Some("mem") => handle_mem_command(debugger, command),
        Some("regs") => {
            let ctx = debugger.get_ctx();
            for i in 0..16 {
                println!("R{} = 0x{:08X}", i, ctx.read_reg(i));
            }
        }
        Some("quit") | Some("exit") => {
            debugger.hwcore_mut().stop();
            // TODO: Cleaner exit?
            std::process::exit(0);
        }
        None => println!("Error: No command"),
        Some(unk_cmd @ _) => println!("Error: Unrecognized command `{}`", unk_cmd),
    }

    return is_paused;
}

fn run_emulator(code: &Vec<u8>, load_offset: u32, entrypoint: u32) {
    let mem = hwcore::map_memory_regions();
    mem.write_buf(load_offset, code.as_slice());

    let mut hwcore = hwcore::HwCore::new(entrypoint, mem);
    let mut debugger = dbgcore::DbgCore::bind(hwcore);
    debugger.hwcore_mut().start();

    sigint_trap();
    let mut is_paused = false;
    loop {
        if sigint_triggered() {
            sigint_reset();
            debugger.pause();
            is_paused = true;
        }

        if is_paused {
            // Print prompt text
            print!(" > ");
            stdout().flush();

            // Handle pause command
            let mut input = String::new();
            stdin().read_line(&mut input).unwrap();
            is_paused = handle_command(&mut debugger, input.trim_right().split_whitespace());
        } else {
            std::thread::sleep(Duration::from_millis(100));
        }
    }

    debugger.hwcore_mut().stop();
}

fn main() {
    env_logger::init().unwrap();

    let filename = env::args().nth(1).unwrap();
    let load_offset = from_hex(&env::args().nth(2).unwrap()).unwrap();
    let entrypoint = from_hex(&env::args().nth(3).unwrap()).unwrap();

    let mut file = std::fs::File::open(filename).unwrap();
    let file_data = file.metadata().unwrap();
    let file_size = file_data.len();

    let mut filebuf = Vec::<u8>::with_capacity(file_size as usize);

    let size = file.read_to_end(&mut filebuf).unwrap();
    info!("Reading {} bytes from input file", size);
    assert!(size == file_size as usize);

    run_emulator(&filebuf, load_offset, entrypoint);
}
<|endoftext|>


<commit_before>use itertools::{multipeek, MultiPeek};
use std::str;

#[derive(Debug, PartialEq)]
pub enum Token {
    LeftParen,
    RightParen,
    LeftBrace,
    RightBrace,
    Comma,
    Dot,
    Minus,
    Plus,
    Semicolon,
    Slash,
    Star,
    Bang,
    BangEqual,
    Equal,
    EqualEqual,
    Greater,
    GreaterEqual,
    Less,
    LessEqual,
    Identifier(String),
    StringLiteral(String),
    NumberLiteral(f64),
    // Keywords
    And,
    Class,
    Else,
    False,
    Fun,
    For,
    If,
    Nil,
    Or,
    Print,
    Return,
    Super,
    This,
    True,
    Var,
    While,

    Eof,
    // The book doesn't have tokens for comments and
    // whitespaces. Introducing them the scanner can
    // deal with them uniformly and in a more
    // functional way.
    Comment,
    Whitespace,
}

#[derive(Debug,Clone,Copy)]
/// Represents a position in the source file.
/// Both line and column are represented by a 1-based
/// index, since this struct exists only to provide
/// context to the user.
struct Position {
    line: usize,
    column: usize,
}

impl Position {
    fn initial() -> Position {
        Position {
            line: 1,
            column: 1,
        }
    }

    fn increment_column(&mut self) -> () {
        self.column += 1;
    }

    fn increment_line(&mut self) -> () {
        self.line += 1;
        self.column = 1;
    }
}

#[derive(Debug)]
pub struct TokenWithContext {
    pub token: Token,
    // Takes a copy. Tokens can outlive the file they came from
    lexeme: String,
    /// Position of the first character of the token
    position: Position,
}

struct Scanner<'a> {
    current_position: Position,
    current_lexeme: String,
    source: MultiPeek<str::Chars<'a>>,
}

fn is_digit(c: char) -> bool {
    c >= '0' && c <= '9'
}

fn is_alpha(c: char) -> bool {
    (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
}

fn is_alphanumeric(c: char) -> bool {
    is_digit(c) || is_alpha(c)
}

fn is_whitespace(c: char) -> bool {
    match c {
        ' ' => true,
        '\r' => true,
        '\t' => true,
        '\n' => true,
        _ => false,
    }
}

impl<'a> Scanner<'a> {
    fn initialize(source: &String) -> Scanner {
        Scanner {
            current_position: Position::initial(),
            current_lexeme: "".into(),
            source: multipeek(source.chars()),
        }
    }

    fn peek_check(&mut self, check: &Fn(char) -> bool) -> bool {
        self.source.reset_peek();
        match self.source.peek() {
            Some(&c) => check(c),
            None => false,
        }
    }

    fn peek_check2(&mut self, check1: &Fn(char) -> bool, check2: &Fn(char) -> bool) -> bool {
        self.source.reset_peek();
        match self.source.peek() {
            Some(&p1) => {
                match self.source.peek() {
                    Some(&p2) => check1(p1) && check2(p2),
                    None => false,
                }
            }
            None => false,
        }
    }

    fn advance(&mut self) -> Option<char> {
        let next = self.source.next();
        match next {
            Some(c) => {
                self.current_lexeme.push(c);
                if c == '\n' {
                    self.current_position.increment_line();
                } else {
                    self.current_position.increment_column();;
                }
            }
            None => (),
        }
        next
    }

    fn advance_if_match(&mut self, expected: char) -> bool {
        if self.peek_check(&|c| c == expected) {
            let _ = self.advance();
            true
        } else {
            false
        }
    }

    fn advance_while(&mut self, condition: &Fn(char) -> bool) -> () {
        while self.peek_check(condition) {
            self.advance();
        }
    }

    fn add_context(&mut self, token: Token, initial_position: Position) -> TokenWithContext {
        let result = TokenWithContext {
            token: token,
            lexeme: self.current_lexeme.clone(),
            position: initial_position,
        };
        self.current_lexeme = "".into();
        result
    }

    fn string(&mut self) -> Result<Token, String> {
        let initial_line = self.current_position.line;
        self.advance_while(&|c| c != '"');
        if !self.advance_if_match('"') {
            return Err(format!("Unterminated string at line {}", initial_line));
        }
        let literal_length = self.current_lexeme.len() - 2;
        // Trims delimiters
        let literal = self.current_lexeme.chars().skip(1).take(literal_length).collect();
        Ok(Token::StringLiteral(literal))
    }

    fn number(&mut self) -> Token {
        self.advance_while(&is_digit);
        if self.peek_check2(&|p1| p1 == '.', &is_digit) {
            self.advance(); // Consume the .
            self.advance_while(&is_digit);
        }
        let value = self.current_lexeme.parse::<f64>().unwrap();
        Token::NumberLiteral(value)
    }

    fn identifier(&mut self) -> Token {
        self.advance_while(&is_alphanumeric);
        match self.current_lexeme.as_ref() {
            "and" => Token::And,
            "class" => Token::Class,
            "else" => Token::Else,
            "false" => Token::False,
            "for" => Token::For,
            "fun" => Token::Fun,
            "if" => Token::If,
            "nil" => Token::Nil,
            "or" => Token::Or,
            "print" => Token::Print,
            "return" => Token::Return,
            "super" => Token::Super,
            "this" => Token::This,
            "true" => Token::True,
            "var" => Token::Var,
            "while" => Token::While,
            identifier => Token::Identifier(identifier.into()),
        }

    }

    fn scan_next(&mut self) -> Result<TokenWithContext, String> {
        let initial_position = self.current_position;
        // Check if there is something left to iterate on.
        // Early return if we're done.
        let next_char = match self.advance() {
            Some(c) => c,
            None => {
                return Ok(TokenWithContext {
                    token: Token::Eof,
                    // Not very meaningful. Is Eof needed at all?
                    lexeme: "".into(),
                    position: initial_position,
                });
            }
        };
        let token = match next_char {
            '(' => Token::LeftParen,
            ')' => Token::RightParen,
            '{' => Token::LeftBrace,
            '}' => Token::RightBrace,
            ',' => Token::Comma,
            '.' => Token::Dot,
            '-' => Token::Minus,
            '+' => Token::Plus,
            ';' => Token::Semicolon,
            '*' => Token::Star,
            '!' => {
                if self.advance_if_match('=') {
                    Token::BangEqual
                } else {
                    Token::Bang
                }
            }
            '=' => {
                if self.advance_if_match('=') {
                    Token::EqualEqual
                } else {
                    Token::Equal
                }
            }
            '<' => {
                if self.advance_if_match('=') {
                    Token::LessEqual
                } else {
                    Token::Less
                }
            }
            '>' => {
                if self.advance_if_match('=') {
                    Token::GreaterEqual
                } else {
                    Token::Greater
                }
            }
            '/' => {
                if self.advance_if_match('/') {
                    // Comments go on till the end of the line
                    self.advance_while(&|c| c != '\n');
                    Token::Comment
                } else {
                    Token::Slash
                }
            }
            '"' => try!(self.string()),
            c if is_whitespace(c) => Token::Whitespace,
            c if is_digit(c) => self.number(),
            c if is_alpha(c) => self.identifier(),
            c => {
                return Err(format!("Unexpected character {} at line {}, column {}",
                                   c,
                                   self.current_position.line,
                                   self.current_position.column - 1));
            }
        };
        Ok(self.add_context(token, initial_position))
    }
}

pub fn scan(source: &String) -> Result<Vec<TokenWithContext>, String> {
    let mut scanner = Scanner::initialize(source);
    let mut tokens = Vec::new();
    let mut eof = false;
    while !eof {
        let token_with_context = try!(scanner.scan_next());
        match token_with_context.token {
            // Ignoring tokens we don't care about
            Token::Comment => {}
            Token::Whitespace => {}
            Token::Eof => {
                eof = true;
            }
            _ => tokens.push(token_with_context),
        }
    }
    Ok(tokens)
}

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

    #[test]
    fn single_token() {
        let tokens = scan(&"+".into()).unwrap();
        assert_eq!(tokens[0].token, Token::Plus);
    }

    #[test]
    fn expression() {
        let tokens = scan(&"1+2".into()).unwrap();
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
    }

    #[test]
    fn expression_with_whitespaces() {
        let tokens = scan(&"1 + 2".into()).unwrap();
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
    }

    #[test]
    fn assignement_with_comment() {
        let tokens = scan(&"var a = 1.0; // A comment".into()).unwrap();
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
    }

    #[test]
    fn multiline_statements() {
        let tokens = scan(&r#"var a = 1.0;
                              var b = "Hello";"#
                .into())
            .unwrap();
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
        assert_eq!(tokens[5].token, Token::Var);
        assert_eq!(tokens[6].token, Token::Identifier("b".into()));
        assert_eq!(tokens[7].token, Token::Equal);
        assert_eq!(tokens[8].token, Token::StringLiteral("Hello".into()));
        assert_eq!(tokens[9].token, Token::Semicolon);
        assert_eq!(tokens[1].position.line, 1);
        assert_eq!(tokens[1].position.column, 5);
        assert_eq!(tokens[9].position.line, 2);
        assert_eq!(tokens[9].position.column, 46); // There are 30 spaces before the text!
    }
}
<commit_msg>Completed removal of EOF<commit_after>use itertools::{multipeek, MultiPeek};
use std::str;

#[derive(Debug, PartialEq)]
pub enum Token {
    LeftParen,
    RightParen,
    LeftBrace,
    RightBrace,
    Comma,
    Dot,
    Minus,
    Plus,
    Semicolon,
    Slash,
    Star,
    Bang,
    BangEqual,
    Equal,
    EqualEqual,
    Greater,
    GreaterEqual,
    Less,
    LessEqual,
    Identifier(String),
    StringLiteral(String),
    NumberLiteral(f64),
    // Keywords
    And,
    Class,
    Else,
    False,
    Fun,
    For,
    If,
    Nil,
    Or,
    Print,
    Return,
    Super,
    This,
    True,
    Var,
    While,

    // The book doesn't have tokens for comments and
    // whitespaces. Introducing them the scanner can
    // deal with them uniformly and in a more
    // functional way.
    Comment,
    Whitespace,
}

#[derive(Debug,Clone,Copy)]
/// Represents a position in the source file.
/// Both line and column are represented by a 1-based
/// index, since this struct exists only to provide
/// context to the user.
struct Position {
    line: usize,
    column: usize,
}

impl Position {
    fn initial() -> Position {
        Position {
            line: 1,
            column: 1,
        }
    }

    fn increment_column(&mut self) -> () {
        self.column += 1;
    }

    fn increment_line(&mut self) -> () {
        self.line += 1;
        self.column = 1;
    }
}

#[derive(Debug)]
pub struct TokenWithContext {
    pub token: Token,
    // Takes a copy. Tokens can outlive the file they came from
    lexeme: String,
    /// Position of the first character of the token
    position: Position,
}

struct Scanner<'a> {
    current_position: Position,
    current_lexeme: String,
    source: MultiPeek<str::Chars<'a>>,
}

fn is_digit(c: char) -> bool {
    c >= '0' && c <= '9'
}

fn is_alpha(c: char) -> bool {
    (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'
}

fn is_alphanumeric(c: char) -> bool {
    is_digit(c) || is_alpha(c)
}

fn is_whitespace(c: char) -> bool {
    match c {
        ' ' => true,
        '\r' => true,
        '\t' => true,
        '\n' => true,
        _ => false,
    }
}

impl<'a> Scanner<'a> {
    fn initialize(source: &String) -> Scanner {
        Scanner {
            current_position: Position::initial(),
            current_lexeme: "".into(),
            source: multipeek(source.chars()),
        }
    }

    fn peek_check(&mut self, check: &Fn(char) -> bool) -> bool {
        self.source.reset_peek();
        match self.source.peek() {
            Some(&c) => check(c),
            None => false,
        }
    }

    fn peek_check2(&mut self, check1: &Fn(char) -> bool, check2: &Fn(char) -> bool) -> bool {
        self.source.reset_peek();
        match self.source.peek() {
            Some(&p1) => {
                match self.source.peek() {
                    Some(&p2) => check1(p1) && check2(p2),
                    None => false,
                }
            }
            None => false,
        }
    }

    fn advance(&mut self) -> Option<char> {
        let next = self.source.next();
        match next {
            Some(c) => {
                self.current_lexeme.push(c);
                if c == '\n' {
                    self.current_position.increment_line();
                } else {
                    self.current_position.increment_column();;
                }
            }
            None => (),
        }
        next
    }

    fn advance_if_match(&mut self, expected: char) -> bool {
        if self.peek_check(&|c| c == expected) {
            let _ = self.advance();
            true
        } else {
            false
        }
    }

    fn advance_while(&mut self, condition: &Fn(char) -> bool) -> () {
        while self.peek_check(condition) {
            self.advance();
        }
    }

    fn add_context(&mut self, token: Token, initial_position: Position) -> TokenWithContext {
        let result = TokenWithContext {
            token: token,
            lexeme: self.current_lexeme.clone(),
            position: initial_position,
        };
        self.current_lexeme = "".into();
        result
    }

    fn string(&mut self) -> Result<Token, String> {
        let initial_line = self.current_position.line;
        self.advance_while(&|c| c != '"');
        if !self.advance_if_match('"') {
            return Err(format!("Unterminated string at line {}", initial_line));
        }
        let literal_length = self.current_lexeme.len() - 2;
        // Trims delimiters
        let literal = self.current_lexeme.chars().skip(1).take(literal_length).collect();
        Ok(Token::StringLiteral(literal))
    }

    fn number(&mut self) -> Token {
        self.advance_while(&is_digit);
        if self.peek_check2(&|p1| p1 == '.', &is_digit) {
            self.advance(); // Consume the .
            self.advance_while(&is_digit);
        }
        let value = self.current_lexeme.parse::<f64>().unwrap();
        Token::NumberLiteral(value)
    }

    fn identifier(&mut self) -> Token {
        self.advance_while(&is_alphanumeric);
        match self.current_lexeme.as_ref() {
            "and" => Token::And,
            "class" => Token::Class,
            "else" => Token::Else,
            "false" => Token::False,
            "for" => Token::For,
            "fun" => Token::Fun,
            "if" => Token::If,
            "nil" => Token::Nil,
            "or" => Token::Or,
            "print" => Token::Print,
            "return" => Token::Return,
            "super" => Token::Super,
            "this" => Token::This,
            "true" => Token::True,
            "var" => Token::Var,
            "while" => Token::While,
            identifier => Token::Identifier(identifier.into()),
        }

    }

    fn scan_next(&mut self) -> Result<Option<TokenWithContext>, String> {
        let initial_position = self.current_position;
        // Check if there is something left to iterate on.
        // Early return if we're done.
        let next_char = match self.advance() {
            Some(c) => c,
            None => return Ok(None),
        };
        let token = match next_char {
            '(' => Token::LeftParen,
            ')' => Token::RightParen,
            '{' => Token::LeftBrace,
            '}' => Token::RightBrace,
            ',' => Token::Comma,
            '.' => Token::Dot,
            '-' => Token::Minus,
            '+' => Token::Plus,
            ';' => Token::Semicolon,
            '*' => Token::Star,
            '!' => {
                if self.advance_if_match('=') {
                    Token::BangEqual
                } else {
                    Token::Bang
                }
            }
            '=' => {
                if self.advance_if_match('=') {
                    Token::EqualEqual
                } else {
                    Token::Equal
                }
            }
            '<' => {
                if self.advance_if_match('=') {
                    Token::LessEqual
                } else {
                    Token::Less
                }
            }
            '>' => {
                if self.advance_if_match('=') {
                    Token::GreaterEqual
                } else {
                    Token::Greater
                }
            }
            '/' => {
                if self.advance_if_match('/') {
                    // Comments go on till the end of the line
                    self.advance_while(&|c| c != '\n');
                    Token::Comment
                } else {
                    Token::Slash
                }
            }
            '"' => try!(self.string()),
            c if is_whitespace(c) => Token::Whitespace,
            c if is_digit(c) => self.number(),
            c if is_alpha(c) => self.identifier(),
            c => {
                return Err(format!("Unexpected character {} at line {}, column {}",
                                   c,
                                   self.current_position.line,
                                   self.current_position.column - 1));
            }
        };
        Ok(Some(self.add_context(token, initial_position)))
    }
}

pub fn scan(source: &String) -> Result<Vec<TokenWithContext>, String> {
    let mut scanner = Scanner::initialize(source);
    let mut tokens = Vec::new();
    while let Some(token_with_context) = try!(scanner.scan_next()) {
        match token_with_context.token {
            // Ignoring tokens we don't care about
            Token::Comment => {}
            Token::Whitespace => {}
            _ => tokens.push(token_with_context),
        }
    }
    Ok(tokens)
}

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

    #[test]
    fn single_token() {
        let tokens = scan(&"+".into()).unwrap();
        assert_eq!(tokens[0].token, Token::Plus);
    }

    #[test]
    fn expression() {
        let tokens = scan(&"1+2".into()).unwrap();
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
    }

    #[test]
    fn expression_with_whitespaces() {
        let tokens = scan(&"1 + 2".into()).unwrap();
        assert_eq!(tokens[0].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[1].token, Token::Plus);
        assert_eq!(tokens[2].token, Token::NumberLiteral(2.0f64));
    }

    #[test]
    fn assignement_with_comment() {
        let tokens = scan(&"var a = 1.0; // A comment".into()).unwrap();
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
    }

    #[test]
    fn multiline_statements() {
        let tokens = scan(&r#"var a = 1.0;
                              var b = "Hello";"#
                .into())
            .unwrap();
        assert_eq!(tokens[0].token, Token::Var);
        assert_eq!(tokens[1].token, Token::Identifier("a".into()));
        assert_eq!(tokens[2].token, Token::Equal);
        assert_eq!(tokens[3].token, Token::NumberLiteral(1.0f64));
        assert_eq!(tokens[4].token, Token::Semicolon);
        assert_eq!(tokens[5].token, Token::Var);
        assert_eq!(tokens[6].token, Token::Identifier("b".into()));
        assert_eq!(tokens[7].token, Token::Equal);
        assert_eq!(tokens[8].token, Token::StringLiteral("Hello".into()));
        assert_eq!(tokens[9].token, Token::Semicolon);
        assert_eq!(tokens[1].position.line, 1);
        assert_eq!(tokens[1].position.column, 5);
        assert_eq!(tokens[9].position.line, 2);
        assert_eq!(tokens[9].position.column, 46); // There are 30 spaces before the text!
    }
}
<|endoftext|>