<commit_before>//! A macro that parses brainfuck code at compile time.

#![crate_name="brainfuck_macros"]
#![crate_type="dylib"]

#![feature(quote, plugin_registrar, macro_rules)]

extern crate syntax;
extern crate rustc;

use std::gc::Gc;

use syntax::ast;
use syntax::codemap;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;

use rustc::plugin::Registry;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(registrar: &mut Registry) {
    registrar.register_macro("brainfuck", brainfuck)
}

// This essentially translates token-wise, using the symbol mappings
// given in the table at:
// http://en.wikipedia.org/wiki/Brainfuck#Commands
fn brainfuck(cx: &mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<MacResult+'static> {
    let bf = BF {
        array: quote_expr!(&mut *cx, _array),
        idx: quote_expr!(&mut *cx, _i),
        rdr: quote_expr!(&mut *cx, _r),
        wtr: quote_expr!(&mut *cx, _w),
        cx: cx,
    };
    let core_code = bf.tts_to_expr(sp, tts);

    MacExpr::new(quote_expr!(bf.cx, {
        fn run(_r: &mut Reader, _w: &mut Writer) -> ::std::io::IoResult<Vec<u8>> {
            let mut _array = Vec::from_elem(30_000, 0u8);
            let mut _i = 0;
            $core_code;
            Ok(_array)
        }
        run
    }))
}

struct BF<'a> {
    cx: &'a ExtCtxt<'a>,
    array: Gc<ast::Expr>,
    idx: Gc<ast::Expr>,
    rdr: Gc<ast::Expr>,
    wtr: Gc<ast::Expr>
}

impl<'a> BF<'a> {
    fn tts_to_expr(&self, sp: codemap::Span, tts: &[ast::TokenTree]) -> Gc<ast::Expr> {
        let v = tts.iter()
            .filter_map(|tt| self.tt_to_expr(sp,tt).map(|e| self.cx.stmt_expr(e)))
            .collect();

        let block = self.cx.block(sp, v, None);
        self.cx.expr_block(block)
    }

    fn tt_to_expr(&self, sp: codemap::Span, tt: &ast::TokenTree) -> Option<Gc<ast::Expr>> {
        match *tt {
            ast::TTTok(sp, ref tok) => self.token_to_expr(sp, tok),

            // [...] or (...) or {...}
            ast::TTDelim(ref toks) => {
                match (**toks)[0] {
                    // [...]
                    ast::TTTok(_, token::LBRACKET) => {
                        // drop the first and last (i.e. the [ & ]).
                        let centre = self.tts_to_expr(sp, toks.slice(1, toks.len() - 1));

                        let array = self.array;
                        let idx = self.idx;

                        Some(quote_expr!(self.cx, {
                            while *$array.get($idx) != 0 {
                                $centre
                            }
                        }))

                    }
                    _ => {
                        // not [...], so just translate directly (any
                        // invalid tokens (like the delimiters) will
                        // be automatically ignored)
                        Some(self.tts_to_expr(sp,toks.as_slice()))
                    }
                }
            }
            ast::TTSeq(sp, _, _, _) => {
                self.cx.span_err(sp, "sequences unsupported in `brainfuck!`");
                None
            }
            ast::TTNonterminal(sp, _) => {
                self.cx.span_err(sp, "nonterminals unsupported in `brainfuck!`");
                None
            }
        }
    }

    fn token_to_expr(&self, sp: codemap::Span,
                     tok: &token::Token) -> Option<Gc<ast::Expr>> {
        // some tokens consist of multiple characters that brainfuck
        // needs to know about, so we do the obvious thing of just
        // taking each one and combining into a single expression.
        macro_rules! recompose {
            ($($token: expr),*) => {
                {
                    let stmts = vec!(
                        $(
                            {
                                let e = self.token_to_expr(sp,&$token)
                                    .expect("brainfuck: invalid token decomposition?");
                                self.cx.stmt_expr(e)
                            } ),* );
                    Some(self.cx.expr_block(self.cx.block(sp, stmts, None)))
                }
            }
        }
        let idx = self.idx;
        let array = self.array;
        match *tok {
            token::LT | token::GT => {
                let left = *tok == token::LT;
                Some(quote_expr!(self.cx, {
                    if $left {
                        if $idx > 0 {
                            $idx -= 1;
                        }
                    } else {
                        if $idx < $array.len() - 1 {
                            $idx += 1;
                        }
                    }
                }))
            }
            // <<
            token::BINOP(token::SHL) => recompose!(token::LT, token::LT),
            // >>
            token::BINOP(token::SHR) => recompose!(token::GT, token::GT),

            token::DOT => {
                let wtr = self.wtr;
                Some(quote_expr!(self.cx, try!($wtr.write([*$array.get($idx)]))))
            }
            // ..
            token::DOTDOT => recompose!(token::DOT, token::DOT),
            // ...
            token::DOTDOTDOT => recompose!(token::DOT, token::DOT, token::DOT),

            token::COMMA => {
                let rdr = self.rdr;
                Some(quote_expr!(self.cx, {
                    use std::io;
                    *$array.get_mut($idx) = match $rdr.read_byte() {
                        Ok(b) => b,
                        Err(io::IoError { kind: io::EndOfFile, .. }) => -1,
                        Err(e) => return Err(e)
                    }
                }))
            }

            token::BINOP(a @ token::PLUS) | token::BINOP(a @ token::MINUS) => {
                let dir: u8 = if a == token::PLUS { 1 } else { -1 };

                Some(quote_expr!(self.cx, {
                    *$array.get_mut($idx) += $dir
                }))
            }
            // ->
            token::RARROW => recompose!(token::BINOP(token::MINUS), token::GT),
            // <-
            token::LARROW => recompose!(token::LT, token::BINOP(token::MINUS)),
            _ => {
                None
            }
        }
    }
}
<commit_msg>Update to f8426e2e2 2014-09-16 02:26:01 +0000.<commit_after>//! A macro that parses brainfuck code at compile time.

#![crate_name="brainfuck_macros"]
#![crate_type="dylib"]

#![feature(quote, plugin_registrar, macro_rules)]

extern crate syntax;
extern crate rustc;

use syntax::ast;
use syntax::ptr::P;
use syntax::codemap;
use syntax::ext::base::{ExtCtxt, MacResult, MacExpr};
use syntax::ext::build::AstBuilder;
use syntax::parse::token;

use rustc::plugin::Registry;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(registrar: &mut Registry) {
    registrar.register_macro("brainfuck", brainfuck)
}

// This essentially translates token-wise, using the symbol mappings
// given in the table at:
// http://en.wikipedia.org/wiki/Brainfuck#Commands
fn brainfuck(cx: &mut ExtCtxt, sp: codemap::Span, tts: &[ast::TokenTree]) -> Box<MacResult+'static> {
    let bf = BF {
        array: quote_expr!(&mut *cx, _array),
        idx: quote_expr!(&mut *cx, _i),
        rdr: quote_expr!(&mut *cx, _r),
        wtr: quote_expr!(&mut *cx, _w),
        cx: cx,
    };
    let core_code = bf.tts_to_expr(sp, tts);

    MacExpr::new(quote_expr!(bf.cx, {
        fn run(_r: &mut Reader, _w: &mut Writer) -> ::std::io::IoResult<Vec<u8>> {
            let mut _array = Vec::from_elem(30_000, 0u8);
            let mut _i = 0;
            $core_code;
            Ok(_array)
        }
        run
    }))
}

struct BF<'a> {
    cx: &'a ExtCtxt<'a>,
    array: P<ast::Expr>,
    idx: P<ast::Expr>,
    rdr: P<ast::Expr>,
    wtr: P<ast::Expr>
}

impl<'a> BF<'a> {
    fn tts_to_expr(&self, sp: codemap::Span, tts: &[ast::TokenTree]) -> P<ast::Expr> {
        let v = tts.iter()
            .filter_map(|tt| self.tt_to_expr(sp,tt).map(|e| self.cx.stmt_expr(e)))
            .collect();

        let block = self.cx.block(sp, v, None);
        self.cx.expr_block(block)
    }

    fn tt_to_expr(&self, sp: codemap::Span, tt: &ast::TokenTree) -> Option<P<ast::Expr>> {
        match *tt {
            ast::TTTok(sp, ref tok) => self.token_to_expr(sp, tok),

            // [...] or (...) or {...}
            ast::TTDelim(ref toks) => {
                match (**toks)[0] {
                    // [...]
                    ast::TTTok(_, token::LBRACKET) => {
                        // drop the first and last (i.e. the [ & ]).
                        let centre = self.tts_to_expr(sp, toks.slice(1, toks.len() - 1));

                        let array = &self.array;
                        let idx = &self.idx;

                        Some(quote_expr!(self.cx, {
                            while *$array.get($idx) != 0 {
                                $centre
                            }
                        }))

                    }
                    _ => {
                        // not [...], so just translate directly (any
                        // invalid tokens (like the delimiters) will
                        // be automatically ignored)
                        Some(self.tts_to_expr(sp,toks.as_slice()))
                    }
                }
            }
            ast::TTSeq(sp, _, _, _) => {
                self.cx.span_err(sp, "sequences unsupported in `brainfuck!`");
                None
            }
            ast::TTNonterminal(sp, _) => {
                self.cx.span_err(sp, "nonterminals unsupported in `brainfuck!`");
                None
            }
        }
    }

    fn token_to_expr(&self, sp: codemap::Span,
                     tok: &token::Token) -> Option<P<ast::Expr>> {
        // some tokens consist of multiple characters that brainfuck
        // needs to know about, so we do the obvious thing of just
        // taking each one and combining into a single expression.
        macro_rules! recompose {
            ($($token: expr),*) => {
                {
                    let stmts = vec!(
                        $(
                            {
                                let e = self.token_to_expr(sp,&$token)
                                    .expect("brainfuck: invalid token decomposition?");
                                self.cx.stmt_expr(e)
                            } ),* );
                    Some(self.cx.expr_block(self.cx.block(sp, stmts, None)))
                }
            }
        }
        let idx = &self.idx;
        let array = &self.array;
        match *tok {
            token::LT | token::GT => {
                let left = *tok == token::LT;
                Some(quote_expr!(self.cx, {
                    if $left {
                        if $idx > 0 {
                            $idx -= 1;
                        }
                    } else {
                        if $idx < $array.len() - 1 {
                            $idx += 1;
                        }
                    }
                }))
            }
            // <<
            token::BINOP(token::SHL) => recompose!(token::LT, token::LT),
            // >>
            token::BINOP(token::SHR) => recompose!(token::GT, token::GT),

            token::DOT => {
                let wtr = &self.wtr;
                Some(quote_expr!(self.cx, try!($wtr.write([*$array.get($idx)]))))
            }
            // ..
            token::DOTDOT => recompose!(token::DOT, token::DOT),
            // ...
            token::DOTDOTDOT => recompose!(token::DOT, token::DOT, token::DOT),

            token::COMMA => {
                let rdr = &self.rdr;
                Some(quote_expr!(self.cx, {
                    use std::io;
                    *$array.get_mut($idx) = match $rdr.read_byte() {
                        Ok(b) => b,
                        Err(io::IoError { kind: io::EndOfFile, .. }) => -1,
                        Err(e) => return Err(e)
                    }
                }))
            }

            token::BINOP(a @ token::PLUS) | token::BINOP(a @ token::MINUS) => {
                let dir: u8 = if a == token::PLUS { 1 } else { -1 };

                Some(quote_expr!(self.cx, {
                    *$array.get_mut($idx) += $dir
                }))
            }
            // ->
            token::RARROW => recompose!(token::BINOP(token::MINUS), token::GT),
            // <-
            token::LARROW => recompose!(token::LT, token::BINOP(token::MINUS)),
            _ => {
                None
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::ops;
use std::cmp::Ordering;

// I wonder if the order property of the sorted slices and vecs are
// optimized away.

pub trait Sorted {}

#[derive(Debug)]
pub struct SortedSlice<'a,T,S>
where
    T:'a,
    S: SortOrder<T>
{
    inner: &'a[T],
    order: S
}

impl<'a,T,S> SortedSlice<'a,T,S>
where
    T: Ord,
    S: SortOrder<T>
{
    pub fn by_sorting(slice: &'a mut [T], order: S) -> Self {
        S::sort(slice);
        Self {inner: slice, order}
    }
}

impl<'a,T,S> ops::Index<usize> for SortedSlice<'a,T,S>
where
    S: SortOrder<T>
{
    type Output = T;
    fn index(&self, i: usize) -> &Self::Output {
        &self.inner[i]
    }
}

impl<'a,T,S> ops::Deref for SortedSlice<'a,T,S>
where
    S: SortOrder<T>
{
    type Target = [T];
    fn deref(&self) -> &[T] {
        self.inner
    }
}

impl<'a,T,S> Sorted for SortedSlice<'a,T,S>
where S: SortOrder<T>
{}

#[derive(Debug)]
pub struct SortedVec<T,S: SortOrder<T>> {
    inner: Vec<T>,
    order: S,
}

impl<T,S> SortedVec<T,S>
where
    S: SortOrder<T>
{
    pub fn by_sorting<I>(unsorted: I, order: S) -> Self
    where
        I: IntoIterator<Item=T>
    {
        let mut inner: Vec<T> = unsorted.into_iter().collect();
        S::sort(&mut inner);
        Self {inner, order}
    }

    pub fn slice(&self) -> SortedSlice<T,S> {
        SortedSlice{
            inner: &self.inner[..],
            order: self.order
        }
    }
}

// Can't deref to SortedSlice from SortedVec. SortOrder must be made completely
// static.

impl<T,S> Into<Vec<T>> for SortedVec<T,S>
where
    S: SortOrder<T>
{
    fn into(self) -> Vec<T> {
        self.inner
    }
}

pub trait SortOrder<T> : Clone + Copy {
    fn sort(&mut [T]);
}

#[derive(Debug, Clone, Copy)]
pub struct DefaultOrder;

impl<T> SortOrder<T> for DefaultOrder
where T: Ord {
    fn sort(s: &mut [T]) {
        s.sort();
    }
}

macro_rules! order_by_key {
    ($name:ident: $(fn ($($gen:tt)*) ($entry:ident: $t:ty) -> $r:ty $blk:block)*) => (
        #[derive(Debug, Clone, Copy)]
        struct $name;

        $(impl<$($gen)*> SortOrder<$t> for $name
        {
            fn sort(s: &mut [$t]) {
                fn key<$($gen)*>($entry: &$t) -> $r $blk
                s.sort_by_key(key)
            }
        })*
    );
}

order_by_key!{ SortByFirst:
    fn (T: Ord + Clone)(entry: (T,T)) -> T { entry.0.clone() }
    fn (T: Ord + Clone)(entry: (T,T,T)) -> T { entry.0.clone() }
}

#[test]
fn test_sort_by_first() {
    let s: [(i32,i32);3] = [(5,3),(2,7),(3,4)];
    let v = SortedVec::by_sorting(s.iter().cloned(), SortByFirst);
    println!("{:?}", v);
}<commit_msg>Using PhantomData to associate the SortOrder type.<commit_after>use std::ops;
use std::cmp::Ordering;
use std::marker::PhantomData;
use std::mem;

// I wonder if the order property of the sorted slices and vecs are
// optimized away.

pub trait Sorted {}

#[derive(Debug)]
pub struct SortedSlice<'a,T,S>
where
    T:'a,
    S: SortOrder<T>
{
    inner: &'a[T],
    order: PhantomData<*const S>
}

impl<'a,T,S> SortedSlice<'a,T,S>
where
    T: Ord,
    S: SortOrder<T>
{
    pub fn by_sorting(slice: &'a mut [T], _: S) -> Self {
        S::sort(slice);
        Self {inner: slice, order: PhantomData}
    }
}

impl<'a,T,S> ops::Index<usize> for SortedSlice<'a,T,S>
where
    S: SortOrder<T>
{
    type Output = T;
    fn index(&self, i: usize) -> &Self::Output {
        &self.inner[i]
    }
}

impl<'a,T,S> ops::Deref for SortedSlice<'a,T,S>
where
    S: SortOrder<T>
{
    type Target = [T];
    fn deref(&self) -> &[T] {
        self.inner
    }
}

impl<'a,T,S> Sorted for SortedSlice<'a,T,S>
where S: SortOrder<T>
{}

#[derive(Debug)]
pub struct SortedVec<T,S: SortOrder<T>> {
    inner: Vec<T>,
    order: PhantomData<*const S>
}

impl<T,S> SortedVec<T,S>
where
    S: SortOrder<T>
{
    pub fn by_sorting<I>(unsorted: I, _: S) -> Self
    where
        I: IntoIterator<Item=T>
    {
        let mut inner: Vec<T> = unsorted.into_iter().collect();
        S::sort(&mut inner);
        Self {inner, order: PhantomData}
    }

    pub fn as_sorted_slice(&self) -> SortedSlice<T,S> {
        SortedSlice{
            inner: &self.inner,
            order: self.order
        }
    }

    pub fn as_slice(&self) -> &[T] {
        &self.inner
    }
}

impl<'a,T,S> From<&'a SortedVec<T,S>> for SortedSlice<'a,T,S>
where
    S: SortOrder<T>
{
    fn from(v: &'a SortedVec<T,S>) -> Self {
        SortedSlice {
            inner: v.as_slice(),
            order: PhantomData
        }
    }
}

impl<T,S> Into<Vec<T>> for SortedVec<T,S>
where
    S: SortOrder<T>
{
    fn into(self) -> Vec<T> {
        self.inner
    }
}

pub trait SortOrder<T> : Clone + Copy {
    fn sort(&mut [T]);
}

#[derive(Debug, Clone, Copy)]
pub struct DefaultOrder;

impl<T> SortOrder<T> for DefaultOrder
where T: Ord {
    fn sort(s: &mut [T]) {
        s.sort();
    }
}

macro_rules! order_by_key {
    ($name:ident: $(fn ($($gen:tt)*) ($entry:ident: $t:ty) -> $r:ty $blk:block)*) => (
        #[derive(Debug, Clone, Copy)]
        struct $name;

        $(impl<$($gen)*> SortOrder<$t> for $name
        {
            fn sort(s: &mut [$t]) {
                fn key<$($gen)*>($entry: &$t) -> $r $blk
                s.sort_by_key(key)
            }
        })*
    );
}

order_by_key!{ SortByFirst:
    fn (T: Ord + Clone)(entry: (T,T)) -> T { entry.0.clone() }
}

order_by_key!{ SortBySecond:
    fn (T: Ord + Clone)(entry: (T,T)) -> T { entry.1.clone() }
}

#[test]
fn test_sort_by_first() {
    let s = vec![(5,3),(2,7),(3,4)];
    let v = SortedVec::by_sorting(s, SortBySecond);
    assert_eq!(
        &[(5,3),(3,4),(2,7)],
        v.as_slice()
    );
}<|endoftext|>


<commit_before>//! Type safe registers

#![feature(core)]
#![feature(no_std)]
#![no_std]

extern crate core;

#[macro_export]
macro_rules! reg {
    ($register:ident: $ty:ident {
        $($bit:ident: $nth:expr),+,
    }) => {
        reg!($register: $ty {
            bits {
                $($bit: $nth),+,
            }
            bitfields {}
        });
    };

    ($register:ident: $ty:ident {
        bits {
            $($bit:ident: $nth:expr),+,
        }
        bitfields {
            $($bitfield:ident: $offset:expr { $($state:ident: $value:expr),+, }),*
        }
    }) => {
        pub mod $register {
            pub mod prelude {
                pub use super::Bit::*;
            }

            use core::ops::{BitAnd, BitOr, Not};

            use volatile::Into;

            #[derive(Copy)]
            #[repr(C)]
            pub struct Register($ty);

            pub enum Bit {
                $($bit,)+
            }

            impl Bit {
                fn $ty(&self) -> $ty {
                    use self::Bit::*;

                    match *self {
                        $($bit => 1 << $nth),+
                    }
                }
            }

            impl BitAnd<$crate::Not<Bit>> for Register {
                type Output = Register;

                fn bitand(self, rhs: $crate::Not<Bit>) -> Register {
                    Register(self.0 & !(rhs.into_inner()).$ty())
                }
            }

            impl BitOr for Bit {
                type Output = Register;

                fn bitor(self, rhs: Bit) -> Register {
                    Register(self.$ty() | rhs.$ty())
                }
            }

            impl BitOr<Bit> for Register {
                type Output = Register;

                fn bitor(mut self, rhs: Bit) -> Register {
                    self.0 |= rhs.$ty();
                    self
                }
            }

            impl BitOr<Register> for Bit {
                type Output = Register;

                fn bitor(self, rhs: Register) -> Register {
                    rhs | self
                }
            }

            impl Not for Bit {
                type Output = $crate::Not<Bit>;

                fn not(self) -> $crate::Not<Bit> {
                    $crate::Not::new(self)
                }
            }

            impl Into<Register> for Bit {
                fn convert_into(self) -> Register {
                    Register(self.$ty())
                }
            }

            $(
                pub enum $bitfield {
                    $($state),+,
                }

                impl $bitfield {
                    fn $ty(&self) -> $ty {
                        use self::$bitfield::*;

                        match *self {
                            $($state => $value << $offset),+
                        }
                    }
                }

                impl BitOr<$bitfield> for Register {
                    type Output = Register;

                    fn bitor(mut self, rhs: $bitfield) -> Register {
                        const MASK: $ty = ($($value)|+) << $offset;

                        self.0 &= !MASK;
                        self.0 |= rhs.$ty();
                        self
                    }
                }

                impl BitOr<Register> for $bitfield{
                    type Output = Register;

                    fn bitor(self, rhs: Register) -> Register {
                        rhs | self
                    }
                }

                impl BitOr<$bitfield> for Bit {
                    type Output = Register;

                    fn bitor(self, rhs: $bitfield) -> Register {
                        Register(self.$ty() | rhs.$ty())
                    }
                }

                impl BitOr<Bit> for $bitfield {
                    type Output = Register;

                    fn bitor(self, rhs: Bit) -> Register {
                        rhs | self
                    }
                }
             )*
        }
    };

    ($register:ident: $ty:ident {
        bitfields {
            $($bitfield:ident: $offset:expr { $($state:ident: $value:expr),+, }),+,
        }
    }) => {
        pub mod $register {
            #![allow(non_camel_case_types)]

            pub mod prelude {
                use super::Bit::*;
            }

            use core::ops::BitOr;

            #[derive(Copy)]
            #[repr(C)]
            pub struct Register($ty);

            $(
                pub enum $bitfield {
                    $($state),+,
                }

                impl $bitfield {
                    fn $ty(&self) -> $ty {
                        use self::$bitfield::*;

                        match *self {
                            $($state => $value << $offset),+
                        }
                    }
                }

                impl BitOr<$bitfield> for Register {
                    type Output = Register;

                    fn bitor(mut self, rhs: $bitfield) -> Register {
                        const MASK: $ty = ($($value)|+) << $offset;

                        self.0 &= !MASK;
                        self.0 |= rhs.$ty();
                        self
                    }
                }

                impl BitOr<Register> for $bitfield{
                    type Output = Register;

                    fn bitor(self, rhs: Register) -> Register {
                        rhs | self
                    }
                }
             )+
        }
    };
}

/// Lazy bitwise negation `!x`
pub struct Not<T>(T);

impl<T> Not<T> {
    #[doc(hidden)]
    pub fn new(bit: T) -> Not<T> {
        Not(bit)
    }

    #[doc(hidden)]
    pub fn into_inner(self) -> T {
        self.0
    }
}
<commit_msg>feat(prelude): also export bitfields<commit_after>//! Type safe registers

#![feature(core)]
#![feature(no_std)]
#![no_std]

extern crate core;

#[macro_export]
macro_rules! reg {
    ($register:ident: $ty:ident {
        $($bit:ident: $nth:expr),+,
    }) => {
        reg!($register: $ty {
            bits {
                $($bit: $nth),+,
            }
            bitfields {}
        });
    };

    ($register:ident: $ty:ident {
        bits {
            $($bit:ident: $nth:expr),+,
        }
        bitfields {
            $($bitfield:ident: $offset:expr { $($state:ident: $value:expr),+, }),*
        }
    }) => {
        pub mod $register {
            pub mod prelude {
                pub use super::Bit::*;
                pub use super::{$($bitfield),*};
            }

            use core::ops::{BitAnd, BitOr, Not};

            use volatile::Into;

            #[derive(Copy)]
            #[repr(C)]
            pub struct Register($ty);

            pub enum Bit {
                $($bit,)+
            }

            impl Bit {
                fn $ty(&self) -> $ty {
                    use self::Bit::*;

                    match *self {
                        $($bit => 1 << $nth),+
                    }
                }
            }

            impl BitAnd<$crate::Not<Bit>> for Register {
                type Output = Register;

                fn bitand(self, rhs: $crate::Not<Bit>) -> Register {
                    Register(self.0 & !(rhs.into_inner()).$ty())
                }
            }

            impl BitOr for Bit {
                type Output = Register;

                fn bitor(self, rhs: Bit) -> Register {
                    Register(self.$ty() | rhs.$ty())
                }
            }

            impl BitOr<Bit> for Register {
                type Output = Register;

                fn bitor(mut self, rhs: Bit) -> Register {
                    self.0 |= rhs.$ty();
                    self
                }
            }

            impl BitOr<Register> for Bit {
                type Output = Register;

                fn bitor(self, rhs: Register) -> Register {
                    rhs | self
                }
            }

            impl Not for Bit {
                type Output = $crate::Not<Bit>;

                fn not(self) -> $crate::Not<Bit> {
                    $crate::Not::new(self)
                }
            }

            impl Into<Register> for Bit {
                fn convert_into(self) -> Register {
                    Register(self.$ty())
                }
            }

            $(
                pub enum $bitfield {
                    $($state),+,
                }

                impl $bitfield {
                    fn $ty(&self) -> $ty {
                        use self::$bitfield::*;

                        match *self {
                            $($state => $value << $offset),+
                        }
                    }
                }

                impl BitOr<$bitfield> for Register {
                    type Output = Register;

                    fn bitor(mut self, rhs: $bitfield) -> Register {
                        const MASK: $ty = ($($value)|+) << $offset;

                        self.0 &= !MASK;
                        self.0 |= rhs.$ty();
                        self
                    }
                }

                impl BitOr<Register> for $bitfield{
                    type Output = Register;

                    fn bitor(self, rhs: Register) -> Register {
                        rhs | self
                    }
                }

                impl BitOr<$bitfield> for Bit {
                    type Output = Register;

                    fn bitor(self, rhs: $bitfield) -> Register {
                        Register(self.$ty() | rhs.$ty())
                    }
                }

                impl BitOr<Bit> for $bitfield {
                    type Output = Register;

                    fn bitor(self, rhs: Bit) -> Register {
                        rhs | self
                    }
                }
             )*
        }
    };

    ($register:ident: $ty:ident {
        bitfields {
            $($bitfield:ident: $offset:expr { $($state:ident: $value:expr),+, }),+,
        }
    }) => {
        pub mod $register {
            #![allow(non_camel_case_types)]

            pub mod prelude {
                pub use super::{$($bitfield),+};
            }

            use core::ops::BitOr;

            #[derive(Copy)]
            #[repr(C)]
            pub struct Register($ty);

            $(
                pub enum $bitfield {
                    $($state),+,
                }

                impl $bitfield {
                    fn $ty(&self) -> $ty {
                        use self::$bitfield::*;

                        match *self {
                            $($state => $value << $offset),+
                        }
                    }
                }

                impl BitOr<$bitfield> for Register {
                    type Output = Register;

                    fn bitor(mut self, rhs: $bitfield) -> Register {
                        const MASK: $ty = ($($value)|+) << $offset;

                        self.0 &= !MASK;
                        self.0 |= rhs.$ty();
                        self
                    }
                }

                impl BitOr<Register> for $bitfield{
                    type Output = Register;

                    fn bitor(self, rhs: Register) -> Register {
                        rhs | self
                    }
                }
             )+
        }
    };
}

/// Lazy bitwise negation `!x`
pub struct Not<T>(T);

impl<T> Not<T> {
    #[doc(hidden)]
    pub fn new(bit: T) -> Not<T> {
        Not(bit)
    }

    #[doc(hidden)]
    pub fn into_inner(self) -> T {
        self.0
    }
}
<|endoftext|>


<commit_before>// Systray Lib

extern crate log;
#[cfg(target_os = "linux")]
extern crate glib;
#[cfg(target_os = "linux")]
extern crate gtk;
#[cfg(target_os = "linux")]
extern crate libappindicator;
#[cfg(target_os = "windows")]
extern crate libc;
#[cfg(target_os = "windows")]
extern crate winapi;

pub mod api;

use std::collections::HashMap;
use std::sync::mpsc::{channel, Receiver};

#[derive(Clone, Debug)]
pub enum SystrayError {
    OsError(String),
    NotImplementedError,
    UnknownError,
}

pub struct SystrayEvent {
    menu_index: u32,
}

impl std::fmt::Display for SystrayError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match self {
            &SystrayError::OsError(ref err_str) => write!(f, "OsError: {}", err_str),
            &SystrayError::NotImplementedError => write!(f, "Functionality is not implemented yet"),
            &SystrayError::UnknownError => write!(f, "Unknown error occurrred"),
        }
    }
}

pub struct Application {
    window: api::api::Window,
    menu_idx: u32,
    callback: HashMap<u32, Callback>,
    // Each platform-specific window module will set up its own thread for
    // dealing with the OS main loop. Use this channel for receiving events from
    // that thread.
    rx: Receiver<SystrayEvent>,
}

type Callback = Box<(dyn Fn(&mut Application) -> () + 'static)>;

fn make_callback<F>(f: F) -> Callback
where
    F: std::ops::Fn(&mut Application) -> () + 'static,
{
    Box::new(f) as Callback
}

impl Application {
    pub fn new() -> Result<Application, SystrayError> {
        let (event_tx, event_rx) = channel();
        match api::api::Window::new(event_tx) {
            Ok(w) => Ok(Application {
                window: w,
                menu_idx: 0,
                callback: HashMap::new(),
                rx: event_rx,
            }),
            Err(e) => Err(e),
        }
    }

    pub fn add_menu_item<F>(&mut self, item_name: &str, f: F) -> Result<u32, SystrayError>
    where
        F: std::ops::Fn(&mut Application) -> () + 'static,
    {
        let idx = self.menu_idx;
        if let Err(e) = self.window.add_menu_entry(idx, item_name) {
            return Err(e);
        }
        self.callback.insert(idx, make_callback(f));
        self.menu_idx += 1;
        Ok(idx)
    }

    pub fn add_menu_separator(&mut self) -> Result<u32, SystrayError> {
        let idx = self.menu_idx;
        if let Err(e) = self.window.add_menu_separator(idx) {
            return Err(e);
        }
        self.menu_idx += 1;
        Ok(idx)
    }

    pub fn set_icon_from_file(&self, file: &str) -> Result<(), SystrayError> {
        self.window.set_icon_from_file(file)
    }

    pub fn set_icon_from_resource(&self, resource: &str) -> Result<(), SystrayError> {
        self.window.set_icon_from_resource(resource)
    }

    pub fn shutdown(&self) -> Result<(), SystrayError> {
        self.window.shutdown()
    }

    pub fn set_tooltip(&self, tooltip: &str) -> Result<(), SystrayError> {
        self.window.set_tooltip(tooltip)
    }

    pub fn quit(&mut self) {
        self.window.quit()
    }

    pub fn wait_for_message(&mut self) {
        loop {
            let msg;
            match self.rx.recv() {
                Ok(m) => msg = m,
                Err(_) => {
                    self.quit();
                    break;
                }
            }
            if self.callback.contains_key(&msg.menu_index) {
                let f = self.callback.remove(&msg.menu_index).unwrap();
                f(self);
                self.callback.insert(msg.menu_index, f);
            }
        }
    }
}

impl Drop for Application {
    fn drop(&mut self) {
        self.shutdown().ok();
    }
}
<commit_msg>Implement std::error::Error for SystrayError<commit_after>// Systray Lib

extern crate log;
#[cfg(target_os = "linux")]
extern crate glib;
#[cfg(target_os = "linux")]
extern crate gtk;
#[cfg(target_os = "linux")]
extern crate libappindicator;
#[cfg(target_os = "windows")]
extern crate libc;
#[cfg(target_os = "windows")]
extern crate winapi;

pub mod api;

use std::collections::HashMap;
use std::sync::mpsc::{channel, Receiver};

#[derive(Clone, Debug)]
pub enum SystrayError {
    OsError(String),
    NotImplementedError,
    UnknownError,
}

pub struct SystrayEvent {
    menu_index: u32,
}

impl std::error::Error for SystrayError {
}

impl std::fmt::Display for SystrayError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match self {
            &SystrayError::OsError(ref err_str) => write!(f, "OsError: {}", err_str),
            &SystrayError::NotImplementedError => write!(f, "Functionality is not implemented yet"),
            &SystrayError::UnknownError => write!(f, "Unknown error occurrred"),
        }
    }
}

pub struct Application {
    window: api::api::Window,
    menu_idx: u32,
    callback: HashMap<u32, Callback>,
    // Each platform-specific window module will set up its own thread for
    // dealing with the OS main loop. Use this channel for receiving events from
    // that thread.
    rx: Receiver<SystrayEvent>,
}

type Callback = Box<(dyn Fn(&mut Application) -> () + 'static)>;

fn make_callback<F>(f: F) -> Callback
where
    F: std::ops::Fn(&mut Application) -> () + 'static,
{
    Box::new(f) as Callback
}

impl Application {
    pub fn new() -> Result<Application, SystrayError> {
        let (event_tx, event_rx) = channel();
        match api::api::Window::new(event_tx) {
            Ok(w) => Ok(Application {
                window: w,
                menu_idx: 0,
                callback: HashMap::new(),
                rx: event_rx,
            }),
            Err(e) => Err(e),
        }
    }

    pub fn add_menu_item<F>(&mut self, item_name: &str, f: F) -> Result<u32, SystrayError>
    where
        F: std::ops::Fn(&mut Application) -> () + 'static,
    {
        let idx = self.menu_idx;
        if let Err(e) = self.window.add_menu_entry(idx, item_name) {
            return Err(e);
        }
        self.callback.insert(idx, make_callback(f));
        self.menu_idx += 1;
        Ok(idx)
    }

    pub fn add_menu_separator(&mut self) -> Result<u32, SystrayError> {
        let idx = self.menu_idx;
        if let Err(e) = self.window.add_menu_separator(idx) {
            return Err(e);
        }
        self.menu_idx += 1;
        Ok(idx)
    }

    pub fn set_icon_from_file(&self, file: &str) -> Result<(), SystrayError> {
        self.window.set_icon_from_file(file)
    }

    pub fn set_icon_from_resource(&self, resource: &str) -> Result<(), SystrayError> {
        self.window.set_icon_from_resource(resource)
    }

    pub fn shutdown(&self) -> Result<(), SystrayError> {
        self.window.shutdown()
    }

    pub fn set_tooltip(&self, tooltip: &str) -> Result<(), SystrayError> {
        self.window.set_tooltip(tooltip)
    }

    pub fn quit(&mut self) {
        self.window.quit()
    }

    pub fn wait_for_message(&mut self) {
        loop {
            let msg;
            match self.rx.recv() {
                Ok(m) => msg = m,
                Err(_) => {
                    self.quit();
                    break;
                }
            }
            if self.callback.contains_key(&msg.menu_index) {
                let f = self.callback.remove(&msg.menu_index).unwrap();
                f(self);
                self.callback.insert(msg.menu_index, f);
            }
        }
    }
}

impl Drop for Application {
    fn drop(&mut self) {
        self.shutdown().ok();
    }
}
<|endoftext|>


<commit_before>#![deny(missing_docs, warnings)]
#![feature(libc)]

//! Termios bindings + safe wrapper
//!
//! # Examples
//!
//! Check the [`Termios`](struct.Termios.html#method.fetch) struct.
//!
//! # Dependencies
//!
//! - libclang-3.6-dev to generate the bindings

extern crate libc;

use libc::c_int;
use std::default::Default;
use std::{fmt, io, mem};

use self::BaudRate::*;
use self::When::*;

pub mod control;
pub mod input;
pub mod local;
pub mod output;
pub mod prelude;
pub mod raw;
pub mod traits;

const FAILURE: c_int = -1;
const SUCCESS: c_int = 0;

/// Safe wrapper around `raw::Termios`
#[derive(Copy)]
#[repr(C)]
pub struct Termios {
    /// Input flags
    pub iflag: input::Flags,
    /// Output flags
    pub oflag: output::Flags,
    /// Control flags
    pub cflag: control::Flags,
    /// Local flags
    pub lflag: local::Flags,
    #[cfg(target_os = "linux")] _line: raw::cc_t,
    /// Control characters
    pub cc: control::Chars,
    _ispeed: raw::speed_t,
    _ospeed: raw::speed_t,
}

impl Termios {
    /// Returns the `Termios` structure associated with the `fd` (file descriptor)
    ///
    /// # Examples
    ///
    /// Inspect your TTY.
    ///
    /// ``` no_run
    /// // examples/stdin.rs
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use termios::prelude::*;
    ///
    /// fn main() {
    ///     println!("{:?}", Termios::fetch(libc::STDIN_FILENO).unwrap());
    /// }
    /// ```
    ///
    /// ``` text
    /// $ ./stdin
    /// iflag:  ICRNL | IXON
    /// oflag:  ONLCR | OPOST
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK | ECHO | ICANON | IEXTEN | ISIG
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    ///
    /// $ echo 'this will panic!' | ./stdin
    /// called `Result::unwrap()` on an `Err` value: file descriptor is not a TTY
    /// ```
    ///
    /// The second call panicked because `./stdin`'s stdin was not connected to a TTY, the
    /// following ASCII art shows how the standard streams are wired in that case:
    ///
    /// ``` text
    ///        +-----------------+  `|`   +---------------------+
    /// TTY => |stdin      stdout| =====> |stdin          stdout| => TTY
    ///        |     `echo`      |        |     `./stdin`       |
    ///        |           stderr| => TTY |               stderr| => TTY
    ///        +-----------------+        +---------------------+
    /// ```
    pub fn fetch(fd: c_int) -> io::Result<Termios> {
        let mut termios: raw::Termios = Default::default();

        unsafe {
            match raw::tcgetattr(fd, &mut termios) {
                FAILURE => Err(io::Error::last_os_error()),
                SUCCESS => Ok(Termios::from_raw(termios)),
                _ => unreachable!(),
            }
        }
    }

    /// Updates the `Termios` structure associated with the `fd` (file descriptor)
    ///
    /// # Examples
    ///
    /// Unbuffered TTY input.
    ///
    /// Consider the following application:
    ///
    /// ``` no_run
    /// // examples/buffered.rs
    /// use std::io::{Read, self};
    ///
    /// fn main() {
    ///     let stdin = io::stdin();
    ///
    ///     for byte in stdin.lock().bytes() {
    ///         match byte {
    ///             Err(e) => panic!("{}", e),
    ///             Ok(byte) => println!("Got {}", byte),
    ///         }
    ///     }
    /// }
    /// ```
    ///
    /// You'll expect the application to print back each byte as you type, however if you run the
    /// application and type: `a b c ENTER CTRL+D`, you get the following output:
    ///
    /// ``` text
    /// $ ./buffered
    /// abc
    /// Got 97
    /// Got 98
    /// Got 99
    /// Got 10
    /// ```
    ///
    /// You'll notice two things:
    ///
    /// - The application prints back what you type.
    /// - The application doesn't process your input until you hit ENTER.
    ///
    /// The difference between the observed behavior and your expectations is caused by the TTY
    /// (the terminal emulator you are using). By default, the TTY echoes back what you type (this
    /// is essential when you are typing commands in a shell!), and also buffers (line by line)
    /// your input before sending it to the application.
    ///
    /// If you want the application to match your expectations, then you'll have to modify the
    /// behavior of the TTY using `Termios`. The following code disables both echoing and line
    /// buffering:
    ///
    /// ``` no_run
    /// // examples/unbuffered.rs
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use std::io::{Read, self};
    ///
    /// use termios::prelude::*;
    ///
    /// // a.k.a. "Ctrl+D"
    /// const END_OF_TRANSMISSION: u8 = 4;
    ///
    /// fn main() {
    ///     let old_termios = Termios::fetch(libc::STDIN_FILENO).unwrap();
    ///     let mut new_termios = old_termios;
    ///
    ///     // Disable line buffering
    ///     new_termios.clear(local::Flag::ICANON);
    ///
    ///     // Disable echo
    ///     new_termios.clear(local::Flag::ECHO);
    ///
    ///     // Change the behavior of the TTY
    ///     new_termios.update(libc::STDIN_FILENO, When::Now).unwrap();
    ///
    ///     let stdin = io::stdin();
    ///
    ///     for byte in stdin.lock().bytes() {
    ///         match byte {
    ///             Err(e) => panic!("{}", e),
    ///             Ok(END_OF_TRANSMISSION) => break,
    ///             Ok(byte) => println!("Got {}", byte),
    ///         }
    ///     }
    ///
    ///     // Restore the original behavior of the TTY
    ///     old_termios.update(libc::STDIN_FILENO, When::Now).unwrap();
    /// }
    /// ```
    ///
    /// If you run this example, you'll receive the `"Got XYZ"` message each time you press a key.
    pub fn update(&self, fd: c_int, when: When) -> io::Result<()> {
        unsafe {
            match raw::tcsetattr(fd, when.to_raw(), self.as_raw()) {
                FAILURE => Err(io::Error::last_os_error()),
                SUCCESS => Ok(()),
                _ => unreachable!(),
            }
        }
    }

    /// Puts `Termios` in "raw" mode
    ///
    /// # Examples
    ///
    /// Compare "cooked" and "raw" modes
    ///
    /// ``` no_run
    /// // examples/raw.rs
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use termios::prelude::*;
    ///
    /// fn main() {
    ///     let mut termios = Termios::fetch(libc::STDIN_FILENO).unwrap();
    ///     println!("Cooked:\n{:?}", termios);
    ///     termios.make_raw();
    ///     println!("\nRaw:\n{:?}", termios);
    /// }
    /// ```
    ///
    /// ``` text
    /// Cooked:
    /// iflag:  ICRNL | IXON
    /// oflag:  ONLCR | OPOST
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK | ECHO | ICANON | IEXTEN | ISIG
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    ///
    /// Raw:
    /// iflag:
    /// oflag:  ONLCR
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    /// ```
    pub fn make_raw(&mut self) {
        unsafe {
            raw::cfmakeraw(self.as_raw_mut())
        }
    }

    /// Returns the input baud rate
    pub fn ispeed(&self) -> BaudRate {
        unsafe {
            BaudRate::from_raw(raw::cfgetispeed(self.as_raw()))
        }
    }

    /// Returns the output baud rate
    pub fn ospeed(&self) -> BaudRate {
        unsafe {
            BaudRate::from_raw(raw::cfgetospeed(self.as_raw()))
        }
    }

    /// Sets the input baud rate
    pub fn set_ispeed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetispeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Sets the output baud rate
    pub fn set_ospeed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetospeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Sets both the input and the output baud rates
    pub fn set_speed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetspeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Borrows the safe wrapper as its raw representation
    pub fn as_raw(&self) -> &raw::Termios {
        unsafe {
            mem::transmute(self)
        }
    }

    /// Mutably borrows the safe wrapper as its raw representation
    pub unsafe fn as_raw_mut(&mut self) -> &mut raw::Termios {
        mem::transmute(self)
    }

    /// Puts `raw::Termios` into a safe wrapper without performing any check
    pub unsafe fn from_raw(termios: raw::Termios) -> Termios {
        mem::transmute(termios)
    }

    /// Converts the safe wrapper into its raw representation
    pub fn into_raw(self) -> raw::Termios {
        unsafe {
            mem::transmute(self)
        }
    }
}

// XXX (Debug) Formatting may change
impl fmt::Debug for Termios {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "iflag:\t{:?}", self.iflag));
        try!(writeln!(f, "oflag:\t{:?}", self.oflag));
        try!(writeln!(f, "cflag:\t{:?}", self.cflag));
        try!(writeln!(f, "lflag:\t{:?}", self.lflag));
        try!(writeln!(f, "cc:\t{:?}", self.cc));
        try!(writeln!(f, "ispeed:\t{:?}", self.ispeed()));
        try!(write!(f, "ospeed:\t{:?}", self.ospeed()));
        Ok(())
    }
}

/// Standard baud rates
#[allow(missing_docs)]
#[derive(Copy, Debug, PartialEq)]
pub enum BaudRate {
    B0,
    B50,
    B75,
    B110,
    B134,
    B150,
    B200,
    B300,
    B600,
    B1200,
    B1800,
    B2400,
    B4800,
    B9600,
    B19200,
    B38400,
    B57600,
    B115200,
    B230400,
}

impl BaudRate {
    fn from_raw(speed: raw::tcflag_t) -> BaudRate {
        use BaudRate::*;

        match speed {
            raw::B0 => B0,
            raw::B50 => B50,
            raw::B75 => B75,
            raw::B110 => B110,
            raw::B134 => B134,
            raw::B150 => B150,
            raw::B200 => B200,
            raw::B300 => B300,
            raw::B600 => B600,
            raw::B1200 => B1200,
            raw::B1800 => B1800,
            raw::B2400 => B2400,
            raw::B4800 => B4800,
            raw::B9600 => B9600,
            raw::B19200 => B19200,
            raw::B38400 => B38400,
            raw::B57600 => B57600,
            raw::B115200 => B115200,
            raw::B230400 => B230400,
            _ => panic!("Unknown baud rate flag: {}", speed),
        }
    }

    fn to_raw(&self) -> raw::speed_t {
        match *self {
            B0 => raw::B0,
            B50 => raw::B50,
            B75 => raw::B75,
            B110 => raw::B110,
            B134 => raw::B134,
            B150 => raw::B150,
            B200 => raw::B200,
            B300 => raw::B300,
            B600 => raw::B600,
            B1200 => raw::B1200,
            B1800 => raw::B1800,
            B2400 => raw::B2400,
            B4800 => raw::B4800,
            B9600 => raw::B9600,
            B19200 => raw::B19200,
            B38400 => raw::B38400,
            B57600 => raw::B57600,
            B115200 => raw::B115200,
            B230400 => raw::B230400,
        }
    }
}

/// When to update the underlying `raw::Termios` structure
pub enum When {
    /// Make change immediate
    Now,
    /// Drain output, then change
    AfterDrain,
    /// Drain output, flush input, then change
    AfterFlush,
}

impl When {
    fn to_raw(&self) -> c_int {
        match *self {
            Now => raw::TCSANOW,
            AfterDrain => raw::TCSADRAIN,
            AfterFlush => raw::TCSAFLUSH,
        }
    }
}

#[cfg(test)]
mod test {
    use libc;

    use Termios;

    #[test]
    fn stderr() {
        Termios::fetch(libc::STDERR_FILENO).unwrap();
    }

    #[test]
    fn stdin() {
        Termios::fetch(libc::STDIN_FILENO).unwrap();
    }

    #[test]
    fn stdout() {
        Termios::fetch(libc::STDOUT_FILENO).unwrap();
    }
}
<commit_msg>fix(doctests): add feature gates to doctests<commit_after>#![deny(missing_docs, warnings)]
#![feature(libc)]

//! Termios bindings + safe wrapper
//!
//! # Examples
//!
//! Check the [`Termios`](struct.Termios.html#method.fetch) struct.
//!
//! # Dependencies
//!
//! - libclang-3.6-dev to generate the bindings

extern crate libc;

use libc::c_int;
use std::default::Default;
use std::{fmt, io, mem};

use self::BaudRate::*;
use self::When::*;

pub mod control;
pub mod input;
pub mod local;
pub mod output;
pub mod prelude;
pub mod raw;
pub mod traits;

const FAILURE: c_int = -1;
const SUCCESS: c_int = 0;

/// Safe wrapper around `raw::Termios`
#[derive(Copy)]
#[repr(C)]
pub struct Termios {
    /// Input flags
    pub iflag: input::Flags,
    /// Output flags
    pub oflag: output::Flags,
    /// Control flags
    pub cflag: control::Flags,
    /// Local flags
    pub lflag: local::Flags,
    #[cfg(target_os = "linux")] _line: raw::cc_t,
    /// Control characters
    pub cc: control::Chars,
    _ispeed: raw::speed_t,
    _ospeed: raw::speed_t,
}

impl Termios {
    /// Returns the `Termios` structure associated with the `fd` (file descriptor)
    ///
    /// # Examples
    ///
    /// Inspect your TTY.
    ///
    /// ``` no_run
    /// // examples/stdin.rs
    /// #![feature(libc)]
    ///
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use termios::prelude::*;
    ///
    /// fn main() {
    ///     println!("{:?}", Termios::fetch(libc::STDIN_FILENO).unwrap());
    /// }
    /// ```
    ///
    /// ``` text
    /// $ ./stdin
    /// iflag:  ICRNL | IXON
    /// oflag:  ONLCR | OPOST
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK | ECHO | ICANON | IEXTEN | ISIG
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    ///
    /// $ echo 'this will panic!' | ./stdin
    /// called `Result::unwrap()` on an `Err` value: file descriptor is not a TTY
    /// ```
    ///
    /// The second call panicked because `./stdin`'s stdin was not connected to a TTY, the
    /// following ASCII art shows how the standard streams are wired in that case:
    ///
    /// ``` text
    ///        +-----------------+  `|`   +---------------------+
    /// TTY => |stdin      stdout| =====> |stdin          stdout| => TTY
    ///        |     `echo`      |        |     `./stdin`       |
    ///        |           stderr| => TTY |               stderr| => TTY
    ///        +-----------------+        +---------------------+
    /// ```
    pub fn fetch(fd: c_int) -> io::Result<Termios> {
        let mut termios: raw::Termios = Default::default();

        unsafe {
            match raw::tcgetattr(fd, &mut termios) {
                FAILURE => Err(io::Error::last_os_error()),
                SUCCESS => Ok(Termios::from_raw(termios)),
                _ => unreachable!(),
            }
        }
    }

    /// Updates the `Termios` structure associated with the `fd` (file descriptor)
    ///
    /// # Examples
    ///
    /// Unbuffered TTY input.
    ///
    /// Consider the following application:
    ///
    /// ``` no_run
    /// // examples/buffered.rs
    /// use std::io::{Read, self};
    ///
    /// fn main() {
    ///     let stdin = io::stdin();
    ///
    ///     for byte in stdin.lock().bytes() {
    ///         match byte {
    ///             Err(e) => panic!("{}", e),
    ///             Ok(byte) => println!("Got {}", byte),
    ///         }
    ///     }
    /// }
    /// ```
    ///
    /// You'll expect the application to print back each byte as you type, however if you run the
    /// application and type: `a b c ENTER CTRL+D`, you get the following output:
    ///
    /// ``` text
    /// $ ./buffered
    /// abc
    /// Got 97
    /// Got 98
    /// Got 99
    /// Got 10
    /// ```
    ///
    /// You'll notice two things:
    ///
    /// - The application prints back what you type.
    /// - The application doesn't process your input until you hit ENTER.
    ///
    /// The difference between the observed behavior and your expectations is caused by the TTY
    /// (the terminal emulator you are using). By default, the TTY echoes back what you type (this
    /// is essential when you are typing commands in a shell!), and also buffers (line by line)
    /// your input before sending it to the application.
    ///
    /// If you want the application to match your expectations, then you'll have to modify the
    /// behavior of the TTY using `Termios`. The following code disables both echoing and line
    /// buffering:
    ///
    /// ``` no_run
    /// // examples/unbuffered.rs
    /// #![feature(libc)]
    ///
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use std::io::{Read, self};
    ///
    /// use termios::prelude::*;
    ///
    /// // a.k.a. "Ctrl+D"
    /// const END_OF_TRANSMISSION: u8 = 4;
    ///
    /// fn main() {
    ///     let old_termios = Termios::fetch(libc::STDIN_FILENO).unwrap();
    ///     let mut new_termios = old_termios;
    ///
    ///     // Disable line buffering
    ///     new_termios.clear(local::Flag::ICANON);
    ///
    ///     // Disable echo
    ///     new_termios.clear(local::Flag::ECHO);
    ///
    ///     // Change the behavior of the TTY
    ///     new_termios.update(libc::STDIN_FILENO, When::Now).unwrap();
    ///
    ///     let stdin = io::stdin();
    ///
    ///     for byte in stdin.lock().bytes() {
    ///         match byte {
    ///             Err(e) => panic!("{}", e),
    ///             Ok(END_OF_TRANSMISSION) => break,
    ///             Ok(byte) => println!("Got {}", byte),
    ///         }
    ///     }
    ///
    ///     // Restore the original behavior of the TTY
    ///     old_termios.update(libc::STDIN_FILENO, When::Now).unwrap();
    /// }
    /// ```
    ///
    /// If you run this example, you'll receive the `"Got XYZ"` message each time you press a key.
    pub fn update(&self, fd: c_int, when: When) -> io::Result<()> {
        unsafe {
            match raw::tcsetattr(fd, when.to_raw(), self.as_raw()) {
                FAILURE => Err(io::Error::last_os_error()),
                SUCCESS => Ok(()),
                _ => unreachable!(),
            }
        }
    }

    /// Puts `Termios` in "raw" mode
    ///
    /// # Examples
    ///
    /// Compare "cooked" and "raw" modes
    ///
    /// ``` no_run
    /// // examples/raw.rs
    /// #![feature(libc)]
    ///
    /// extern crate libc;
    /// extern crate termios;
    ///
    /// use termios::prelude::*;
    ///
    /// fn main() {
    ///     let mut termios = Termios::fetch(libc::STDIN_FILENO).unwrap();
    ///     println!("Cooked:\n{:?}", termios);
    ///     termios.make_raw();
    ///     println!("\nRaw:\n{:?}", termios);
    /// }
    /// ```
    ///
    /// ``` text
    /// Cooked:
    /// iflag:  ICRNL | IXON
    /// oflag:  ONLCR | OPOST
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK | ECHO | ICANON | IEXTEN | ISIG
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    ///
    /// Raw:
    /// iflag:
    /// oflag:  ONLCR
    /// cflag:  CS8 | CREAD
    /// lflag:  ECHOCTL | ECHOE | ECHOKE | ECHOK
    /// cc:     VDISCARD: 15, VEOF: 4, VEOL2: 0, (..)
    /// ispeed: B38400
    /// ospeed: B38400
    /// ```
    pub fn make_raw(&mut self) {
        unsafe {
            raw::cfmakeraw(self.as_raw_mut())
        }
    }

    /// Returns the input baud rate
    pub fn ispeed(&self) -> BaudRate {
        unsafe {
            BaudRate::from_raw(raw::cfgetispeed(self.as_raw()))
        }
    }

    /// Returns the output baud rate
    pub fn ospeed(&self) -> BaudRate {
        unsafe {
            BaudRate::from_raw(raw::cfgetospeed(self.as_raw()))
        }
    }

    /// Sets the input baud rate
    pub fn set_ispeed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetispeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Sets the output baud rate
    pub fn set_ospeed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetospeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Sets both the input and the output baud rates
    pub fn set_speed(&mut self, rate: BaudRate) {
        unsafe {
            match raw::cfsetspeed(self.as_raw_mut(), rate.to_raw()) {
                FAILURE => {
                    // NB This operation can only panic if self is null (impossible in safe code)
                    // or if `rate.to_raw()` is an invalid value (that would be a bug)
                    unreachable!();
                },
                SUCCESS => {},
                _ => unreachable!(),
            }
        }
    }

    /// Borrows the safe wrapper as its raw representation
    pub fn as_raw(&self) -> &raw::Termios {
        unsafe {
            mem::transmute(self)
        }
    }

    /// Mutably borrows the safe wrapper as its raw representation
    pub unsafe fn as_raw_mut(&mut self) -> &mut raw::Termios {
        mem::transmute(self)
    }

    /// Puts `raw::Termios` into a safe wrapper without performing any check
    pub unsafe fn from_raw(termios: raw::Termios) -> Termios {
        mem::transmute(termios)
    }

    /// Converts the safe wrapper into its raw representation
    pub fn into_raw(self) -> raw::Termios {
        unsafe {
            mem::transmute(self)
        }
    }
}

// XXX (Debug) Formatting may change
impl fmt::Debug for Termios {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(writeln!(f, "iflag:\t{:?}", self.iflag));
        try!(writeln!(f, "oflag:\t{:?}", self.oflag));
        try!(writeln!(f, "cflag:\t{:?}", self.cflag));
        try!(writeln!(f, "lflag:\t{:?}", self.lflag));
        try!(writeln!(f, "cc:\t{:?}", self.cc));
        try!(writeln!(f, "ispeed:\t{:?}", self.ispeed()));
        try!(write!(f, "ospeed:\t{:?}", self.ospeed()));
        Ok(())
    }
}

/// Standard baud rates
#[allow(missing_docs)]
#[derive(Copy, Debug, PartialEq)]
pub enum BaudRate {
    B0,
    B50,
    B75,
    B110,
    B134,
    B150,
    B200,
    B300,
    B600,
    B1200,
    B1800,
    B2400,
    B4800,
    B9600,
    B19200,
    B38400,
    B57600,
    B115200,
    B230400,
}

impl BaudRate {
    fn from_raw(speed: raw::tcflag_t) -> BaudRate {
        use BaudRate::*;

        match speed {
            raw::B0 => B0,
            raw::B50 => B50,
            raw::B75 => B75,
            raw::B110 => B110,
            raw::B134 => B134,
            raw::B150 => B150,
            raw::B200 => B200,
            raw::B300 => B300,
            raw::B600 => B600,
            raw::B1200 => B1200,
            raw::B1800 => B1800,
            raw::B2400 => B2400,
            raw::B4800 => B4800,
            raw::B9600 => B9600,
            raw::B19200 => B19200,
            raw::B38400 => B38400,
            raw::B57600 => B57600,
            raw::B115200 => B115200,
            raw::B230400 => B230400,
            _ => panic!("Unknown baud rate flag: {}", speed),
        }
    }

    fn to_raw(&self) -> raw::speed_t {
        match *self {
            B0 => raw::B0,
            B50 => raw::B50,
            B75 => raw::B75,
            B110 => raw::B110,
            B134 => raw::B134,
            B150 => raw::B150,
            B200 => raw::B200,
            B300 => raw::B300,
            B600 => raw::B600,
            B1200 => raw::B1200,
            B1800 => raw::B1800,
            B2400 => raw::B2400,
            B4800 => raw::B4800,
            B9600 => raw::B9600,
            B19200 => raw::B19200,
            B38400 => raw::B38400,
            B57600 => raw::B57600,
            B115200 => raw::B115200,
            B230400 => raw::B230400,
        }
    }
}

/// When to update the underlying `raw::Termios` structure
pub enum When {
    /// Make change immediate
    Now,
    /// Drain output, then change
    AfterDrain,
    /// Drain output, flush input, then change
    AfterFlush,
}

impl When {
    fn to_raw(&self) -> c_int {
        match *self {
            Now => raw::TCSANOW,
            AfterDrain => raw::TCSADRAIN,
            AfterFlush => raw::TCSAFLUSH,
        }
    }
}

#[cfg(test)]
mod test {
    use libc;

    use Termios;

    #[test]
    fn stderr() {
        Termios::fetch(libc::STDERR_FILENO).unwrap();
    }

    #[test]
    fn stdin() {
        Termios::fetch(libc::STDIN_FILENO).unwrap();
    }

    #[test]
    fn stdout() {
        Termios::fetch(libc::STDOUT_FILENO).unwrap();
    }
}
<|endoftext|>


<commit_before>//! The `neon` crate provides the entire [Neon](https://www.neon-bindings.com/) API.

extern crate neon_runtime;
extern crate cslice;

pub mod mem;
pub mod vm;
pub mod scope;
pub mod js;
pub mod task;

#[doc(hidden)]
pub mod macro_internal;

/// Register the current crate as a Node module, providing startup
/// logic for initializing the module object at runtime.
///
/// Example:
///
/// ```rust,ignore
/// register_module!(m, {
///     m.export("foo", foo)?;
///     m.export("bar", bar)?;
///     m.export("baz", baz)?;
///     Ok(())
/// });
/// ```
#[macro_export]
macro_rules! register_module {
    ($module:ident, $init:block) => {
        // Mark this function as a global constructor (like C++).
        #[allow(improper_ctypes)]
        #[cfg_attr(target_os = "linux", link_section = ".ctors")]
        #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
        #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
        pub static __LOAD_NEON_MODULE: extern "C" fn() = {
            fn __init_neon_module(mut $module: $crate::vm::Module) -> $crate::vm::VmResult<()> $init

            extern "C" fn __load_neon_module() {
                // Put everything else in the ctor fn so the user fn can't see it.
                #[repr(C)]
                struct __NodeModule {
                    version: i32,
                    flags: u32,
                    dso_handle: *mut u8,
                    filename: *const u8,
                    register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8)>,
                    context_register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8, *mut u8)>,
                    modname: *const u8,
                    priv_data: *mut u8,
                    link: *mut __NodeModule
                }

                static mut __NODE_MODULE: __NodeModule = __NodeModule {
                    version: 0,
                    flags: 0,
                    dso_handle: 0 as *mut _,
                    filename: b"neon_source.rs\0" as *const u8,
                    register_func: Some(__register_neon_module),
                    context_register_func: None,
                    modname: b"neon_module\0" as *const u8,
                    priv_data: 0 as *mut _,
                    link: 0 as *mut _
                };

                extern "C" fn __register_neon_module(
                        m: $crate::mem::Handle<$crate::js::JsObject>, _: *mut u8, _: *mut u8) {
                    $crate::vm::Module::initialize(m, __init_neon_module);
                }

                extern "C" {
                    fn node_module_register(module: *mut __NodeModule);
                }

                // Suppress the default Rust panic hook, which prints diagnostics to stderr.
                ::std::panic::set_hook(::std::boxed::Box::new(|_| { }));

                unsafe {
                    // Set the ABI version based on the NODE_MODULE_VERSION constant provided by the current node headers.
                    __NODE_MODULE.version = $crate::macro_internal::runtime::module::get_version();
                    node_module_register(&mut __NODE_MODULE);
                }
            }

            __load_neon_module
        };
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! class_definition {
    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; init($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          {
                              fn _______allocator_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsUndefined>) -> $crate::vm::VmResult<$typ> {
                                  $body
                              }

                              $crate::macro_internal::AllocateKernel::new(_______allocator_rust_y_u_no_hygienic_items_______)
                          } ;
                          $call_ctor ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; ($($mname:tt)*) ; ($($mdef:tt)*) ; method $name:ident($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          $new_ctor ;
                          ($($mname)* $name) ;
                          ($($mdef)* {
                              fn _______method_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::MethodKernel::new(_______method_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; constructor($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          ({
                              fn _______constructor_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::VmResult<Option<$crate::mem::Handle<$crate::js::JsObject>>> {
                                  $body
                              }

                              $crate::macro_internal::ConstructKernel::new(_______constructor_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; call($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          ({
                              fn _______call_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsValue>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::ConstructorCallKernel::new(_______call_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:block ; ($($call_ctor:block)*) ; ($($new_ctor:block)*) ; ($($mname:ident)*) ; ($($mdef:block)*) ; $($rest:tt)* ) => {
        impl $crate::js::class::Class for $cls {
            type Internals = $typ;

            fn setup<'a, T: $crate::scope::Scope<'a>>(_: &mut T) -> $crate::vm::VmResult<$crate::js::class::ClassDescriptor<'a, Self>> {
                ::std::result::Result::Ok(Self::describe(stringify!($cname), $allocator)
                                             $(.construct($new_ctor))*
                                             $(.call($call_ctor))*
                                             $(.method(stringify!($mname), $mdef))*)
            }
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! impl_managed {
    ($cls:ident) => {
        impl $crate::mem::Managed for $cls {
            fn to_raw(self) -> $crate::macro_internal::runtime::raw::Local {
                let $cls(raw) = self;
                raw
            }

            fn from_raw(raw: $crate::macro_internal::runtime::raw::Local) -> Self {
                $cls(raw)
            }
        }
    }
}

/// Declare custom native JavaScript types with Rust implementations.
///
/// Example:
///
/// ```rust,ignore
/// pub struct Greeter {
///     greeting: String
/// }
///
/// declare_types! {
///
///     /// A class for generating greeting strings.
///     pub class JsGreeter for Greeter {
///         init(call) {
///             let scope = call.scope;
///             let greeting = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             Ok(Greeter {
///                 greeting: greeting
///             })
///         }
///
///         method hello(call) {
///             let scope = call.scope;
///             let name = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             let msg = vm::lock(call.arguments.this(scope), |greeter| {
///                 format!("{}, {}!", greeter.greeting, name)
///             });
///             Ok(JsString::new_or_throw(scope, &msg[..])?.upcast())
///         }
///     }
///
/// }
/// ```
#[macro_export]
macro_rules! declare_types {
    { $(#[$attr:meta])* pub class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* pub class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* pub class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        pub struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { } => { };
}

#[test]
fn cli_test() {
    use std::process::Command;
    let cli_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .output()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd cli; npm install; npm run transpile")
                .output()
                .expect("failed to execute process")
    };
    assert!(cli_output.status.success());

    let cli_test_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .output()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd test/cli; npm install; npm run transpile && npm test")
                .output()
                .expect("failed to execute process")
    };
    assert!(cli_test_output.status.success());
}

#[test]
fn static_test() {
    use std::process::Command;
    let static_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .output()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd test/static; cargo test")
                .output()
                .expect("failed to execute process")
    };
    assert!(static_output.status.success());
}

#[test]
fn dynamic_test() {
    use std::process::Command;
    let dynamic_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .output()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd test/dynamic; npm install; npm test")
                .output()
                .expect("failed to execute process")
    };
    assert!(dynamic_output.status.success());
}
<commit_msg>replace semi-colons with ANDs<commit_after>//! The `neon` crate provides the entire [Neon](https://www.neon-bindings.com/) API.

extern crate neon_runtime;
extern crate cslice;

pub mod mem;
pub mod vm;
pub mod scope;
pub mod js;
pub mod task;

#[doc(hidden)]
pub mod macro_internal;

/// Register the current crate as a Node module, providing startup
/// logic for initializing the module object at runtime.
///
/// Example:
///
/// ```rust,ignore
/// register_module!(m, {
///     m.export("foo", foo)?;
///     m.export("bar", bar)?;
///     m.export("baz", baz)?;
///     Ok(())
/// });
/// ```
#[macro_export]
macro_rules! register_module {
    ($module:ident, $init:block) => {
        // Mark this function as a global constructor (like C++).
        #[allow(improper_ctypes)]
        #[cfg_attr(target_os = "linux", link_section = ".ctors")]
        #[cfg_attr(target_os = "macos", link_section = "__DATA,__mod_init_func")]
        #[cfg_attr(target_os = "windows", link_section = ".CRT$XCU")]
        pub static __LOAD_NEON_MODULE: extern "C" fn() = {
            fn __init_neon_module(mut $module: $crate::vm::Module) -> $crate::vm::VmResult<()> $init

            extern "C" fn __load_neon_module() {
                // Put everything else in the ctor fn so the user fn can't see it.
                #[repr(C)]
                struct __NodeModule {
                    version: i32,
                    flags: u32,
                    dso_handle: *mut u8,
                    filename: *const u8,
                    register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8)>,
                    context_register_func: Option<extern "C" fn(
                        $crate::mem::Handle<$crate::js::JsObject>, *mut u8, *mut u8, *mut u8)>,
                    modname: *const u8,
                    priv_data: *mut u8,
                    link: *mut __NodeModule
                }

                static mut __NODE_MODULE: __NodeModule = __NodeModule {
                    version: 0,
                    flags: 0,
                    dso_handle: 0 as *mut _,
                    filename: b"neon_source.rs\0" as *const u8,
                    register_func: Some(__register_neon_module),
                    context_register_func: None,
                    modname: b"neon_module\0" as *const u8,
                    priv_data: 0 as *mut _,
                    link: 0 as *mut _
                };

                extern "C" fn __register_neon_module(
                        m: $crate::mem::Handle<$crate::js::JsObject>, _: *mut u8, _: *mut u8) {
                    $crate::vm::Module::initialize(m, __init_neon_module);
                }

                extern "C" {
                    fn node_module_register(module: *mut __NodeModule);
                }

                // Suppress the default Rust panic hook, which prints diagnostics to stderr.
                ::std::panic::set_hook(::std::boxed::Box::new(|_| { }));

                unsafe {
                    // Set the ABI version based on the NODE_MODULE_VERSION constant provided by the current node headers.
                    __NODE_MODULE.version = $crate::macro_internal::runtime::module::get_version();
                    node_module_register(&mut __NODE_MODULE);
                }
            }

            __load_neon_module
        };
    }
}

#[doc(hidden)]
#[macro_export]
macro_rules! class_definition {
    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; init($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          {
                              fn _______allocator_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsUndefined>) -> $crate::vm::VmResult<$typ> {
                                  $body
                              }

                              $crate::macro_internal::AllocateKernel::new(_______allocator_rust_y_u_no_hygienic_items_______)
                          } ;
                          $call_ctor ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; ($($mname:tt)*) ; ($($mdef:tt)*) ; method $name:ident($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          $new_ctor ;
                          ($($mname)* $name) ;
                          ($($mdef)* {
                              fn _______method_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::MethodKernel::new(_______method_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; constructor($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          $call_ctor ;
                          ({
                              fn _______constructor_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$cls>) -> $crate::vm::VmResult<Option<$crate::mem::Handle<$crate::js::JsObject>>> {
                                  $body
                              }

                              $crate::macro_internal::ConstructKernel::new(_______constructor_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:tt ; $call_ctor:tt ; $new_ctor:tt ; $mnames:tt ; $mdefs:tt ; call($call:pat) $body:block $($rest:tt)* ) => {
        class_definition!($cls ;
                          $cname ;
                          $typ ;
                          $allocator ;
                          ({
                              fn _______call_rust_y_u_no_hygienic_items_______($call: $crate::vm::FunctionCall<$crate::js::JsValue>) -> $crate::vm::JsResult<$crate::js::JsValue> {
                                  $body
                              }

                              $crate::macro_internal::ConstructorCallKernel::new(_______call_rust_y_u_no_hygienic_items_______)
                          }) ;
                          $new_ctor ;
                          $mnames ;
                          $mdefs ;
                          $($rest)*);
    };

    ( $cls:ident ; $cname:ident ; $typ:ty ; $allocator:block ; ($($call_ctor:block)*) ; ($($new_ctor:block)*) ; ($($mname:ident)*) ; ($($mdef:block)*) ; $($rest:tt)* ) => {
        impl $crate::js::class::Class for $cls {
            type Internals = $typ;

            fn setup<'a, T: $crate::scope::Scope<'a>>(_: &mut T) -> $crate::vm::VmResult<$crate::js::class::ClassDescriptor<'a, Self>> {
                ::std::result::Result::Ok(Self::describe(stringify!($cname), $allocator)
                                             $(.construct($new_ctor))*
                                             $(.call($call_ctor))*
                                             $(.method(stringify!($mname), $mdef))*)
            }
        }
    };
}

#[doc(hidden)]
#[macro_export]
macro_rules! impl_managed {
    ($cls:ident) => {
        impl $crate::mem::Managed for $cls {
            fn to_raw(self) -> $crate::macro_internal::runtime::raw::Local {
                let $cls(raw) = self;
                raw
            }

            fn from_raw(raw: $crate::macro_internal::runtime::raw::Local) -> Self {
                $cls(raw)
            }
        }
    }
}

/// Declare custom native JavaScript types with Rust implementations.
///
/// Example:
///
/// ```rust,ignore
/// pub struct Greeter {
///     greeting: String
/// }
///
/// declare_types! {
///
///     /// A class for generating greeting strings.
///     pub class JsGreeter for Greeter {
///         init(call) {
///             let scope = call.scope;
///             let greeting = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             Ok(Greeter {
///                 greeting: greeting
///             })
///         }
///
///         method hello(call) {
///             let scope = call.scope;
///             let name = call.arguments.require(scope, 0)?.to_string(scope)?.value();
///             let msg = vm::lock(call.arguments.this(scope), |greeter| {
///                 format!("{}, {}!", greeter.greeting, name)
///             });
///             Ok(JsString::new_or_throw(scope, &msg[..])?.upcast())
///         }
///     }
///
/// }
/// ```
#[macro_export]
macro_rules! declare_types {
    { $(#[$attr:meta])* pub class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* pub class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident for $typ:ident { $($body:tt)* } $($rest:tt)* } => {
        declare_types! { $(#[$attr])* class $cls as $typ for $typ { $($body)* } $($rest)* }
    };

    { $(#[$attr:meta])* pub class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        pub struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { $(#[$attr:meta])* class $cls:ident as $cname:ident for $typ:ty { $($body:tt)* } $($rest:tt)* } => {
        #[derive(Copy, Clone)]
        #[repr(C)]
        $(#[$attr])*
        struct $cls($crate::macro_internal::runtime::raw::Local);

        impl_managed!($cls);

        class_definition!($cls ; $cname ; $typ ; () ; () ; () ; () ; () ; $($body)*);

        declare_types! { $($rest)* }
    };

    { } => { };
}

#[test]
fn cli_test() {
    use std::process::Command;
    let cli_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .output()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd cli && npm install && npm run transpile")
                .output()
                .expect("failed to execute process")
    };
    assert!(cli_output.status.success());

    let cli_test_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .output()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd test/cli && npm install && npm run transpile && npm test")
                .output()
                .expect("failed to execute process")
    };
    assert!(cli_test_output.status.success());
}

#[test]
fn static_test() {
    use std::process::Command;
    let static_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .output()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd test/static && cargo test")
                .output()
                .expect("failed to execute process")
    };
    assert!(static_output.status.success());
}

#[test]
fn dynamic_test() {
    use std::process::Command;
    let dynamic_output = if cfg!(target_os = "windows") {
        Command::new("cmd")
                .args(&["/C", "Implement this later"])
                .output()
                .expect("failed to execute process")
    } else {
        Command::new("sh")
                .arg("-c")
                .arg("cd test/dynamic && npm install && npm test")
                .output()
                .expect("failed to execute process")
    };
    assert!(dynamic_output.status.success());
}
<|endoftext|>