<commit_before>use field::{self, CoreField};
use column_puyo_list::ColumnPuyoList;
use color::{PuyoColor, NUM_PUYO_COLORS};
use rensa_detector::PurposeForFindingRensa;

pub fn detect_by_drop<Callback>(original_field: &CoreField,
                                prohibits: &[bool],
                                purpose: PurposeForFindingRensa,
                                max_complement_puyos: usize,
                                max_puyo_height: usize,
                                mut callback: Callback)
                                where Callback: FnMut(CoreField, &ColumnPuyoList) {
    let mut visited = [[false; NUM_PUYO_COLORS]; field::MAP_WIDTH];

    let normal_color_bits = original_field.field().normal_color_bits();
    let empty_bits = original_field.field().bits(PuyoColor::EMPTY);
    let edge_bits = (normal_color_bits & empty_bits.expand_edge()).masked_field_12();

    edge_bits.iterate_bit_position(|x, y| {
        debug_assert!(original_field.is_normal_color(x, y));
        let c = original_field.color(x, y);

        for d in &[-1isize, 0isize, 1isize] {
            let xd = (x as isize + *d) as usize;
            if prohibits[xd] || visited[xd][c as usize] || xd <= 0 || field::WIDTH < xd {
                continue;
            }
            if *d == 0 {
                if !original_field.is_empty(x, y + 1) {
                    continue;
                }
                // If the first rensa is this, any rensa won't continue.
                // This is like erasing the following X.
                // ......
                // .YXY..
                // BZZZBB
                // CAAACC
                //
                // So, we should be able to skip this.
                if purpose == PurposeForFindingRensa::ForFire && !original_field.is_connected(x, y) {
                    continue;
                }
            } else {
                if !original_field.is_empty(xd, y) {
                    continue;
                }
            }

            visited[xd][c as usize] = true;
            let mut necessary_puyos = 0;

            let mut ok = true;
            let mut cf: CoreField = (*original_field).clone();
            loop {
                if !cf.drop_puyo_on_with_max_height(xd, c, max_puyo_height) {
                    ok = false;
                    break;
                }

                necessary_puyos += 1;
                if max_complement_puyos < necessary_puyos {
                    ok = false;
                    break;
                }
                if cf.count_connected_max4_with_color(xd, cf.height(xd), c) >= 4 {
                    break;
                }
            }

            if !ok {
                continue;
            }

            let mut cpl = ColumnPuyoList::new();
            if !cpl.add_multi(xd, c, necessary_puyos) {
                continue;
            }

            callback(cf, &cpl);
        }
    });
}

#[cfg(test)]
mod tests {
    use super::*;
    use column_puyo_list::ColumnPuyoList;
    use field::CoreField;
    use rensa_detector::PurposeForFindingRensa;

    #[test]
    fn test_detect_by_drop() {
        let original = CoreField::from_str(concat!(
            ".RGYG.",
            "RGYGB.",
            "RGYGB.",
            "RGYGB.",
        ));

        let expected = CoreField::from_str(concat!(
            ".RGYG.",
            "RGYGB.",
            "RGYGB.",
            "RGYGBB",
        ));

        let mut found = false;
        {
            let callback = |actual: CoreField, cpl: &ColumnPuyoList| {
                if actual != expected {
                    return;
                }

                assert!(!found);
                found = true;

                let mut cf = original.clone();
                assert!(cf.drop_column_puyo_list(cpl));
                assert_eq!(expected, cf);
            };

            let no_prohibits = &[false; 8];
            detect_by_drop(&original, no_prohibits, PurposeForFindingRensa::ForFire, 1, 12, callback);
        }
        assert!(found);
    }
}
<commit_msg>Add RensaDetector::detect<commit_after>use field::{self, CoreField};
use column_puyo_list::ColumnPuyoList;
use color::{PuyoColor, NUM_PUYO_COLORS};
use rensa_detector::PurposeForFindingRensa;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Mode {
    Drop,
    Float,
}

pub struct RensaDetector {
    mode: Mode,
    max_puyo_for_key: usize,
    max_puyo_for_fire: usize,
    max_height: usize,
}

impl RensaDetector {
    pub fn new(mode: Mode, max_puyo_for_key: usize, max_puyo_for_fire: usize, max_height: usize) -> RensaDetector {
        RensaDetector {
            mode: mode,
            max_puyo_for_key: max_puyo_for_key,
            max_puyo_for_fire: max_puyo_for_fire,
            max_height: max_height,
        }
    }

    pub fn default_drop_strategy() -> RensaDetector {
        RensaDetector::new(Mode::Drop, 3, 3, 12)
    }

    pub fn default_float_strategy() -> RensaDetector {
        RensaDetector::new(Mode::Float, 3, 3, 13)
    }

    pub fn detect<Callback>(&self,
                            original_field: &CoreField,
                            purpose: PurposeForFindingRensa,
                            prohibits: &[bool],
                            callback: Callback)
                            where Callback: FnMut(CoreField, &ColumnPuyoList) {
        let max_complement_puyo = {
            match purpose {
                PurposeForFindingRensa::ForKey => self.max_puyo_for_key,
                PurposeForFindingRensa::ForFire => self.max_puyo_for_fire,
            }
        };

        match self.mode {
            Mode::Drop => {
                detect_by_drop(original_field, prohibits, purpose,
                               max_complement_puyo, self.max_height, callback)
            },
            Mode::Float => {
                unimplemented!()
            }
        }
    }
}

/// Detects rensa by `drop` strategy.
pub fn detect_by_drop<Callback>(original_field: &CoreField,
                                prohibits: &[bool],
                                purpose: PurposeForFindingRensa,
                                max_complement_puyos: usize,
                                max_puyo_height: usize,
                                mut callback: Callback)
                                where Callback: FnMut(CoreField, &ColumnPuyoList) {
    let mut visited = [[false; NUM_PUYO_COLORS]; field::MAP_WIDTH];

    let normal_color_bits = original_field.field().normal_color_bits();
    let empty_bits = original_field.field().bits(PuyoColor::EMPTY);
    let edge_bits = (normal_color_bits & empty_bits.expand_edge()).masked_field_12();

    edge_bits.iterate_bit_position(|x, y| {
        debug_assert!(original_field.is_normal_color(x, y));
        let c = original_field.color(x, y);

        for d in &[-1isize, 0isize, 1isize] {
            let xd = (x as isize + *d) as usize;
            if prohibits[xd] || visited[xd][c as usize] || xd <= 0 || field::WIDTH < xd {
                continue;
            }
            if *d == 0 {
                if !original_field.is_empty(x, y + 1) {
                    continue;
                }
                // If the first rensa is this, any rensa won't continue.
                // This is like erasing the following X.
                // ......
                // .YXY..
                // BZZZBB
                // CAAACC
                //
                // So, we should be able to skip this.
                if purpose == PurposeForFindingRensa::ForFire && !original_field.is_connected(x, y) {
                    continue;
                }
            } else {
                if !original_field.is_empty(xd, y) {
                    continue;
                }
            }

            visited[xd][c as usize] = true;
            let mut necessary_puyos = 0;

            let mut ok = true;
            let mut cf: CoreField = (*original_field).clone();
            loop {
                if !cf.drop_puyo_on_with_max_height(xd, c, max_puyo_height) {
                    ok = false;
                    break;
                }

                necessary_puyos += 1;
                if max_complement_puyos < necessary_puyos {
                    ok = false;
                    break;
                }
                if cf.count_connected_max4_with_color(xd, cf.height(xd), c) >= 4 {
                    break;
                }
            }

            if !ok {
                continue;
            }

            let mut cpl = ColumnPuyoList::new();
            if !cpl.add_multi(xd, c, necessary_puyos) {
                continue;
            }

            callback(cf, &cpl);
        }
    });
}

#[cfg(test)]
mod tests {
    use super::*;
    use column_puyo_list::ColumnPuyoList;
    use field::CoreField;
    use rensa_detector::PurposeForFindingRensa;

    #[test]
    fn test_detect_by_drop() {
        let original = CoreField::from_str(concat!(
            ".RGYG.",
            "RGYGB.",
            "RGYGB.",
            "RGYGB.",
        ));

        let expected = CoreField::from_str(concat!(
            ".RGYG.",
            "RGYGB.",
            "RGYGB.",
            "RGYGBB",
        ));

        let mut found = false;
        {
            let callback = |actual: CoreField, cpl: &ColumnPuyoList| {
                if actual != expected {
                    return;
                }

                assert!(!found);
                found = true;

                let mut cf = original.clone();
                assert!(cf.drop_column_puyo_list(cpl));
                assert_eq!(expected, cf);
            };

            let no_prohibits = &[false; 8];
            detect_by_drop(&original, no_prohibits, PurposeForFindingRensa::ForFire, 1, 12, callback);
        }
        assert!(found);
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;

use super::super::config::Config;
use super::super::helpers::path::build_path;
use super::super::helpers::oauth2;
use super::super::helpers::providers;
use super::super::results::{BearerResult, BearerError};

fn read_stdin(message: &str) -> BearerResult<String> {
    print!("{}", message);
    io::stdout().flush().unwrap();

    let mut buffer = String::new();
    match io::stdin().read_line(&mut buffer) {
        Ok(_) => Ok(buffer.trim().to_string()),
        Err(err) => Err(BearerError::IOError(format!("{}", err))),
    }
}

pub fn command(config_dir: &str, client_name: &str) -> BearerResult<()> {

    debug!("Registering new client {} in directory {}",
           client_name,
           config_dir);
    let (_, exists) = build_path(config_dir, client_name)?;
    if exists {
        return Err(BearerError::ValueError(format!("Client {} already registered", client_name)));
    }
    println!("Before continue, register the a client with the following url to the OAuth2 \
              Provider:");
    println!("");
    println!("http://localhost:6750/callback");
    println!("");
    println!("Ensure your port is not already open by another service.");
    println!("If the provider require a https url, please run an https reverse proxy before \
              continue.");
    println!("");
    let mut provider_name = read_stdin("Enter the OAuth2.0 Provider Name: ")?;

    let (authorize_url, token_url) = match providers::get_provider(&provider_name) {
        Some(provider) => {
            provider_name = provider.name.to_string();
            (provider.authorize_url.to_string(), provider.token_url.to_string())
        }
        None => {
            let authorize_url = read_stdin("Enter the OAuth2.0 Authorize Url: ")?;
            let token_url = read_stdin("Enter the OAuth2.0 Token Url: ")?;
            (authorize_url, token_url)
        }
    };
    let client_id = read_stdin("Enter the Client Id: ")?;
    let secret = read_stdin("Enter the Client Secret: ")?;
    let scope = read_stdin("Enter the scope (optional): ")?;

    let mut config = Config::new(config_dir,
                                 client_name,
                                 provider_name.as_str(),
                                 authorize_url.as_str(),
                                 token_url.as_str(),
                                 client_id.as_str(),
                                 secret.as_str(),
                                 match scope.len() {
                                     0 => None,
                                     _ => Some(scope.as_str()),
                                 })?;

    println!("");
    println!("Visit to finish the configuration: http://localhost:6750/callback");

    debug!("Start server to retrieve tokens");
    let tokens = oauth2::get_tokens(&config, 6750)?;
    debug!("Token retrieved: {:?}", tokens);
    config.set_tokens(tokens);
    config.write()?;
    println!("Tokens retrieved succesfully");
    Ok(())
}
<commit_msg>Rename variable for concistancy<commit_after>use std::io;
use std::io::prelude::*;

use super::super::config::Config;
use super::super::helpers::path::build_path;
use super::super::helpers::oauth2;
use super::super::helpers::providers;
use super::super::results::{BearerResult, BearerError};

fn read_stdin(message: &str) -> BearerResult<String> {
    print!("{}", message);
    io::stdout().flush().unwrap();

    let mut buffer = String::new();
    match io::stdin().read_line(&mut buffer) {
        Ok(_) => Ok(buffer.trim().to_string()),
        Err(err) => Err(BearerError::IOError(format!("{}", err))),
    }
}

pub fn command(config_dir: &str, client_name: &str) -> BearerResult<()> {

    debug!("Registering new client {} in directory {}",
           client_name,
           config_dir);
    let (_, exists) = build_path(config_dir, client_name)?;
    if exists {
        return Err(BearerError::ValueError(format!("Client {} already registered", client_name)));
    }
    println!("Before continue, register the a client with the following url to the OAuth2 \
              Provider:");
    println!("");
    println!("http://localhost:6750/callback");
    println!("");
    println!("Ensure your port is not already open by another service.");
    println!("If the provider require a https url, please run an https reverse proxy before \
              continue.");
    println!("");
    let mut provider_name = read_stdin("Enter the OAuth2.0 Provider Name: ")?;

    let (authorize_url, token_url) = match providers::get_provider(&provider_name) {
        Some(provider) => {
            provider_name = provider.name.to_string();
            (provider.authorize_url.to_string(), provider.token_url.to_string())
        }
        None => {
            let authorize_url = read_stdin("Enter the OAuth2.0 Authorize Url: ")?;
            let token_url = read_stdin("Enter the OAuth2.0 Token Url: ")?;
            (authorize_url, token_url)
        }
    };
    let client_id = read_stdin("Enter the Client Id: ")?;
    let secret = read_stdin("Enter the Client Secret: ")?;
    let scope = read_stdin("Enter the scope (optional): ")?;

    let mut conf = Config::new(config_dir,
                               client_name,
                               provider_name.as_str(),
                               authorize_url.as_str(),
                               token_url.as_str(),
                               client_id.as_str(),
                               secret.as_str(),
                               match scope.len() {
                                   0 => None,
                                   _ => Some(scope.as_str()),
                               })?;

    println!("");
    println!("Visit to finish the configuration: http://localhost:6750/callback");

    debug!("Start server to retrieve tokens");
    let tokens = oauth2::get_tokens(&conf, 6750)?;
    debug!("Token retrieved: {:?}", tokens);
    conf.set_tokens(tokens);
    conf.write()?;
    println!("Tokens retrieved succesfully");
    Ok(())
}
<|endoftext|>


<commit_before>//! [Church booleans](https://en.wikipedia.org/wiki/Church_encoding#Church_Booleans)

use term::{Term, abs};
use term::Term::*;

/// A Church-encoded boolean `true`.
///
/// TRUE := λab.a = λ λ 2
pub fn tru() -> Term { abs(abs(Var(2))) }

/// A Church-encoded boolean `false`.
///
/// FALSE := λab.b = λ λ 1
pub fn fls() -> Term { abs(abs(Var(1))) }

/// Applied to two Church booleans it returns their Church-encoded conjunction.
///
/// AND := λpq.p q p = λ λ 2 1 2
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{and, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(and(), tru(), tru()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(and(), tru(), fls()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(and(), fls(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(and(), fls(), fls()), NOR, 0, false), fls());
/// # }
/// ```
pub fn and() -> Term {
    abs(abs(
        app!(Var(2), Var(1), Var(2))
    ))
}

/// Applied to two Church booleans it returns their Church-encoded disjunction.
///
/// OR := λpq.p p q = λ λ 2 2 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{or, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(or(), tru(), tru()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(or(), tru(), fls()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(or(), fls(), tru()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(or(), fls(), fls()), NOR, 0, false), fls());
/// # }
/// ```
pub fn or() -> Term {
    abs(abs(
        app!(Var(2), Var(2), Var(1))
    ))
}

/// Applied to a Church boolean it returns its Church-encoded negation.
///
/// NOT := λp.p FALSE TRUE = λ 1 FALSE TRUE
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{not, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(not(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(not(), fls()), NOR, 0, false), tru());
/// # }
/// ```
pub fn not() -> Term {
    abs(
        app!(Var(1), fls(), tru())
    )
}

/// Applied to two Church booleans it returns their Church-encoded exclusive disjunction.
///
/// XOR := λpq.p (NOT q) q = λ λ 2 (NOT 1) 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{xor, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(xor(), tru(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(xor(), tru(), fls()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(xor(), fls(), tru()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(xor(), fls(), fls()), NOR, 0, false), fls());
/// # }
/// ```
pub fn xor() -> Term {
    abs(abs(
        app!(
            Var(2),
            app!(
                Var(1),
                abs(abs(Var(1))),
                abs(abs(Var(2)))
            ),
            Var(1)
        )
    ))
}

/// Applied to two Church booleans it returns their Church-encoded joint denial.
///
/// NOR := λpq.NOT (OR p q) = λ λ NOT (OR 2 1)
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{nor, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(nor(), tru(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(nor(), tru(), fls()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(nor(), fls(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(nor(), fls(), fls()), NOR, 0, false), tru());
/// # }
/// ```
pub fn nor() -> Term {
    abs(abs(
        app!(
            Var(2),
            Var(2),
            Var(1),
            abs(abs(Var(1))),
            abs(abs(Var(2)))
        )
    ))
}

/// Applied to two Church booleans it returns their Church-encoded alternative denial.
///
/// NAND := λpq.NOT (AND p q) = λ λ NOT (AND 2 1)
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{nand, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(nand(), tru(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(nand(), tru(), fls()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(nand(), fls(), tru()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(nand(), fls(), fls()), NOR, 0, false), tru());
/// # }
/// ```
pub fn nand() -> Term {
    abs(abs(
        app!(
            Var(2),
            Var(1),
            Var(2),
            abs(abs(Var(1))),
            abs(abs(Var(2)))
        )
    ))
}

/// Applied to a Church-encoded predicate and two terms it returns the first one if the predicate
/// is true or the second one if the predicate is false.
///
/// IF_ELSE := λpab.p a b = λ λ λ 3 2 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{if_else, tru, fls};
/// use lambda_calculus::church::numerals::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(if_else(), tru(), one(), zero()), NOR, 0, false),  one());
/// assert_eq!(beta(app!(if_else(), fls(), one(), zero()), NOR, 0, false), zero());
/// # }
/// ```
pub fn if_else() -> Term {
    abs(abs(abs(
        app!(Var(3), Var(2), Var(1))
    )))
}

impl From<bool> for Term {
    fn from(b: bool) -> Self {
        if b { tru() } else { fls() }
    }
}
<commit_msg>use abs!() in booleans.rs<commit_after>//! [Church booleans](https://en.wikipedia.org/wiki/Church_encoding#Church_Booleans)

use term::{Term, abs};
use term::Term::*;

/// A Church-encoded boolean `true`.
///
/// TRUE := λab.a = λ λ 2
pub fn tru() -> Term { abs!(2, Var(2)) }

/// A Church-encoded boolean `false`.
///
/// FALSE := λab.b = λ λ 1
pub fn fls() -> Term { abs!(2, Var(1)) }

/// Applied to two Church booleans it returns their Church-encoded conjunction.
///
/// AND := λpq.p q p = λ λ 2 1 2
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{and, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(and(), tru(), tru()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(and(), tru(), fls()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(and(), fls(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(and(), fls(), fls()), NOR, 0, false), fls());
/// # }
/// ```
pub fn and() -> Term {
    abs!(2, app!(Var(2), Var(1), Var(2)))
}

/// Applied to two Church booleans it returns their Church-encoded disjunction.
///
/// OR := λpq.p p q = λ λ 2 2 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{or, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(or(), tru(), tru()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(or(), tru(), fls()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(or(), fls(), tru()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(or(), fls(), fls()), NOR, 0, false), fls());
/// # }
/// ```
pub fn or() -> Term {
    abs!(2, app!(Var(2), Var(2), Var(1)))
}

/// Applied to a Church boolean it returns its Church-encoded negation.
///
/// NOT := λp.p FALSE TRUE = λ 1 FALSE TRUE
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{not, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(not(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(not(), fls()), NOR, 0, false), tru());
/// # }
/// ```
pub fn not() -> Term {
    abs(app!(Var(1), fls(), tru()))
}

/// Applied to two Church booleans it returns their Church-encoded exclusive disjunction.
///
/// XOR := λpq.p (NOT q) q = λ λ 2 (NOT 1) 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{xor, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(xor(), tru(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(xor(), tru(), fls()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(xor(), fls(), tru()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(xor(), fls(), fls()), NOR, 0, false), fls());
/// # }
/// ```
pub fn xor() -> Term {
    abs!(2,
        app!(
            Var(2),
            app!(
                Var(1),
                abs!(2, Var(1)),
                abs!(2, Var(2))
            ),
            Var(1)
        )
    )
}

/// Applied to two Church booleans it returns their Church-encoded joint denial.
///
/// NOR := λpq.NOT (OR p q) = λ λ NOT (OR 2 1)
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{nor, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(nor(), tru(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(nor(), tru(), fls()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(nor(), fls(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(nor(), fls(), fls()), NOR, 0, false), tru());
/// # }
/// ```
pub fn nor() -> Term {
    abs!(2,
        app!(
            Var(2),
            Var(2),
            Var(1),
            abs!(2, Var(1)),
            abs!(2, Var(2))
        )
    )
}

/// Applied to two Church booleans it returns their Church-encoded alternative denial.
///
/// NAND := λpq.NOT (AND p q) = λ λ NOT (AND 2 1)
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{nand, tru, fls};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(nand(), tru(), tru()), NOR, 0, false), fls());
/// assert_eq!(beta(app!(nand(), tru(), fls()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(nand(), fls(), tru()), NOR, 0, false), tru());
/// assert_eq!(beta(app!(nand(), fls(), fls()), NOR, 0, false), tru());
/// # }
/// ```
pub fn nand() -> Term {
    abs!(2,
        app!(
            Var(2),
            Var(1),
            Var(2),
            abs!(2, Var(1)),
            abs!(2, Var(2))
        )
    )
}

/// Applied to a Church-encoded predicate and two terms it returns the first one if the predicate
/// is true or the second one if the predicate is false.
///
/// IF_ELSE := λpab.p a b = λ λ λ 3 2 1
///
/// # Examples
/// ```
/// # #[macro_use] extern crate lambda_calculus;
/// # fn main() {
/// use lambda_calculus::church::booleans::{if_else, tru, fls};
/// use lambda_calculus::church::numerals::{zero, one};
/// use lambda_calculus::reduction::beta;
/// use lambda_calculus::reduction::Order::*;
///
/// assert_eq!(beta(app!(if_else(), tru(), one(), zero()), NOR, 0, false),  one());
/// assert_eq!(beta(app!(if_else(), fls(), one(), zero()), NOR, 0, false), zero());
/// # }
/// ```
pub fn if_else() -> Term {
    abs!(3, app!(Var(3), Var(2), Var(1)))
}

impl From<bool> for Term {
    fn from(b: bool) -> Self {
        if b { tru() } else { fls() }
    }
}
<|endoftext|>


<commit_before>use ffi::h5g::{H5G_info_t, H5Gget_info, H5Gcreate2, H5Gopen2};
use ffi::h5l::{H5Lmove, H5L_SAME_LOC};
use ffi::h5i::hid_t;
use ffi::h5p::{H5Pcreate, H5Pset_create_intermediate_group, H5P_DEFAULT};
use globals::H5P_LINK_CREATE;

use error::Result;
use group::Group;
use location::Location;
use object::Object;
use plist::PropertyList;
use util::to_cstring;

use std::default::Default;

fn group_info(id: hid_t) -> Result<H5G_info_t> {
    let info: *mut H5G_info_t = &mut H5G_info_t::default();
    h5call!(H5Gget_info(id, info)).and(Ok(unsafe { *info }))
}

fn make_lcpl() -> Result<PropertyList> {
    h5lock_s!({
        let lcpl = PropertyList::from_id(h5try!(H5Pcreate(*H5P_LINK_CREATE)));
        h5call!(H5Pset_create_intermediate_group(lcpl.id(), 1)).and(Ok(lcpl))
    })
}

pub trait Container: Location {
    /// Returns the number of objects in the container (or 0 if the container is invalid).
    fn len(&self) -> u64 {
        group_info(self.id()).map(|info| info.nlinks).unwrap_or(0)
    }

    /// Returns true if the container has no linked objects (or if the container is invalid).
    fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Create a new group in a container which can be a file or another group.
    fn create_group<S: Into<String>>(&self, name: S) -> Result<Group> {
        h5lock_s!({
            let lcpl = try!(make_lcpl());
            Ok(Group::from_id(h5try!(H5Gcreate2(
                self.id(), to_cstring(name).as_ptr(), lcpl.id(), H5P_DEFAULT, H5P_DEFAULT))))
        })
    }

    /// Opens an existing group in a container which can be a file or another group.
    fn group<S: Into<String>>(&self, name: S) -> Result<Group> {
        Ok(Group::from_id(h5try!(H5Gopen2(
            self.id(), to_cstring(name).as_ptr(), H5P_DEFAULT))))
    }

    /// Relinks an object. Note: `from` and `to` are relative to the current object.
    fn relink<S1: Into<String>, S2: Into<String>>(&self, name: S1, path: S2) -> Result<()> {
        h5call!(H5Lmove(self.id(), to_cstring(name).as_ptr(), H5L_SAME_LOC,
                        to_cstring(path).as_ptr(), H5P_DEFAULT, H5P_DEFAULT)).and(Ok(()))
    }
}

#[cfg(test)]
mod tests {
    use error::silence_errors;
    use test::with_tmp_file;
    use super::Container;
    use location::Location;
    use object::Object;

    #[test]
    pub fn test_group() {
        silence_errors();
        with_tmp_file(|file| {
            assert_err!(file.group("a"), "unable to open group: object.+doesn't exist");
            file.create_group("a").unwrap();
            let a = file.group("a").unwrap();
            assert!(a.name() == "/a");
            assert!(a.file().id() == file.id());
            a.create_group("b").unwrap();
            let b = file.group("/a/b").unwrap();
            assert!(b.name() == "/a/b");
            assert!(b.file().id() == file.id());
            file.create_group("/foo/bar").unwrap();
            file.group("foo").unwrap().group("bar").unwrap();
            file.create_group("x/y/").unwrap();
            file.group("/x").unwrap().group("./y/").unwrap();
        })
    }

    #[test]
    pub fn test_len() {
        with_tmp_file(|file| {
            assert_eq!(file.len(), 0);
            assert!(file.is_empty());
            file.create_group("foo").unwrap();
            assert_eq!(file.len(), 1);
            assert!(!file.is_empty());
            assert_eq!(file.group("foo").unwrap().len(), 0);
            assert!(file.group("foo").unwrap().is_empty());
            file.create_group("bar").unwrap().create_group("baz").unwrap();
            assert_eq!(file.len(), 2);
            assert_eq!(file.group("bar").unwrap().len(), 1);
            assert_eq!(file.group("/bar/baz").unwrap().len(), 0);
        })
    }

    #[test]
    pub fn test_relink() {
        silence_errors();
        with_tmp_file(|file| {
            file.create_group("test").unwrap();
            file.group("test").unwrap();
            assert_err!(file.relink("test", "foo/test"),
                        "unable to move link: component not found");
            file.create_group("foo").unwrap();
            assert_err!(file.relink("bar", "/baz"),
                        "unable to move link: name doesn't exist");
            file.relink("test", "/foo/test").unwrap();
            file.group("/foo/test").unwrap();
            assert_err!(file.group("test"),
                        "unable to open group: object.+doesn't exist");
        })
    }
}
<commit_msg>Add Container::link_{hard,soft} methods + tests<commit_after>use ffi::h5g::{H5G_info_t, H5Gget_info, H5Gcreate2, H5Gopen2};
use ffi::h5i::hid_t;
use ffi::h5l::{H5Lmove, H5Lcreate_soft, H5Lcreate_hard, H5L_SAME_LOC};
use ffi::h5p::{H5Pcreate, H5Pset_create_intermediate_group, H5P_DEFAULT};
use globals::H5P_LINK_CREATE;

use error::Result;
use group::Group;
use location::Location;
use object::Object;
use plist::PropertyList;
use util::to_cstring;

use std::default::Default;

fn group_info(id: hid_t) -> Result<H5G_info_t> {
    let info: *mut H5G_info_t = &mut H5G_info_t::default();
    h5call!(H5Gget_info(id, info)).and(Ok(unsafe { *info }))
}

fn make_lcpl() -> Result<PropertyList> {
    h5lock_s!({
        let lcpl = PropertyList::from_id(h5try!(H5Pcreate(*H5P_LINK_CREATE)));
        h5call!(H5Pset_create_intermediate_group(lcpl.id(), 1)).and(Ok(lcpl))
    })
}

pub trait Container: Location {
    /// Returns the number of objects in the container (or 0 if the container is invalid).
    fn len(&self) -> u64 {
        group_info(self.id()).map(|info| info.nlinks).unwrap_or(0)
    }

    /// Returns true if the container has no linked objects (or if the container is invalid).
    fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Create a new group in a container which can be a file or another group.
    fn create_group<S: Into<String>>(&self, name: S) -> Result<Group> {
        h5lock_s!({
            let lcpl = try!(make_lcpl());
            Ok(Group::from_id(h5try!(H5Gcreate2(
                self.id(), to_cstring(name).as_ptr(), lcpl.id(), H5P_DEFAULT, H5P_DEFAULT))))
        })
    }

    /// Opens an existing group in a container which can be a file or another group.
    fn group<S: Into<String>>(&self, name: S) -> Result<Group> {
        Ok(Group::from_id(h5try!(H5Gopen2(
            self.id(), to_cstring(name).as_ptr(), H5P_DEFAULT))))
    }

    /// Creates a soft link. Note: `name` and `path` are relative to the current object.
    fn link_soft<S1: Into<String>, S2: Into<String>>(&self, name: S1, path: S2) -> Result<()> {
        // use std::ffi::CString;
        // let name = CString::new("./a").unwrap();
        // let path = CString::new("soft").unwrap();
        h5lock_s!({
            let lcpl = try!(make_lcpl());
            // h5call!(H5Lcreate_soft(name.as_ptr(), self.id(), path.as_ptr(),
            //                        lcpl.id(), H5P_DEFAULT)).and(Ok(()))
            h5call!(H5Lcreate_soft(to_cstring(name).as_ptr(), self.id(), to_cstring(path).as_ptr(),
                                   lcpl.id(), H5P_DEFAULT)).and(Ok(()))
        })
    }

    /// Creates a hard link. Note: `name` and `path` are relative to the current object.
    fn link_hard<S1: Into<String>, S2: Into<String>>(&self, name: S1, path: S2) -> Result<()> {
        h5call!(H5Lcreate_hard(self.id(), to_cstring(name).as_ptr(), H5L_SAME_LOC,
                               to_cstring(path).as_ptr(), H5P_DEFAULT, H5P_DEFAULT)).and(Ok(()))
    }

    /// Relinks an object. Note: `name` and `path` are relative to the current object.
    fn relink<S1: Into<String>, S2: Into<String>>(&self, name: S1, path: S2) -> Result<()> {
        h5call!(H5Lmove(self.id(), to_cstring(name).as_ptr(), H5L_SAME_LOC,
                        to_cstring(path).as_ptr(), H5P_DEFAULT, H5P_DEFAULT)).and(Ok(()))
    }
}

#[cfg(test)]
mod tests {
    use error::silence_errors;
    use test::with_tmp_file;
    use super::Container;
    use location::Location;
    use object::Object;

    #[test]
    pub fn test_group() {
        silence_errors();
        with_tmp_file(|file| {
            assert_err!(file.group("a"), "unable to open group: object.+doesn't exist");
            file.create_group("a").unwrap();
            let a = file.group("a").unwrap();
            assert!(a.name() == "/a");
            assert!(a.file().id() == file.id());
            a.create_group("b").unwrap();
            let b = file.group("/a/b").unwrap();
            assert!(b.name() == "/a/b");
            assert!(b.file().id() == file.id());
            file.create_group("/foo/bar").unwrap();
            file.group("foo").unwrap().group("bar").unwrap();
            file.create_group("x/y/").unwrap();
            file.group("/x").unwrap().group("./y/").unwrap();
        })
    }

    #[test]
    pub fn test_len() {
        with_tmp_file(|file| {
            assert_eq!(file.len(), 0);
            assert!(file.is_empty());
            file.create_group("foo").unwrap();
            assert_eq!(file.len(), 1);
            assert!(!file.is_empty());
            assert_eq!(file.group("foo").unwrap().len(), 0);
            assert!(file.group("foo").unwrap().is_empty());
            file.create_group("bar").unwrap().create_group("baz").unwrap();
            assert_eq!(file.len(), 2);
            assert_eq!(file.group("bar").unwrap().len(), 1);
            assert_eq!(file.group("/bar/baz").unwrap().len(), 0);
        })
    }

    #[test]
    pub fn test_link_hard() {
        silence_errors();
        with_tmp_file(|file| {
            file.create_group("foo/test/inner").unwrap();
            file.link_hard("/foo/test", "/foo/hard").unwrap();
            file.group("foo/test/inner").unwrap();
            file.group("/foo/hard/inner").unwrap();
            assert_err!(file.link_hard("foo/test", "/foo/test/inner"),
                        "unable to create link: name already exists");
            assert_err!(file.link_hard("foo/bar", "/foo/baz"),
                        "unable to create link: object.+doesn't exist");
            file.relink("/foo/hard", "/foo/hard2").unwrap();
            file.group("/foo/hard2/inner").unwrap();
            file.relink("/foo/test", "/foo/baz").unwrap();
            file.group("/foo/baz/inner").unwrap();
            file.group("/foo/hard2/inner").unwrap();
        })
    }

    #[test]
    pub fn test_link_soft() {
        silence_errors();
        with_tmp_file(|file| {
            file.create_group("a/b/c").unwrap();
            file.link_soft("/a/b", "a/soft").unwrap();
            file.group("/a/soft/c").unwrap();
            file.relink("/a/soft", "/a/soft2").unwrap();
            file.group("/a/soft2/c").unwrap();
            file.relink("a/b", "/a/d").unwrap();
            assert_err!(file.group("/a/soft2/c"), "unable to open group");
            file.link_soft("/a/bar", "/a/baz").unwrap();
            assert_err!(file.group("/a/baz"), "unable to open group");
            file.create_group("/a/bar").unwrap();
            file.group("/a/baz").unwrap();
        })
    }

    #[test]
    pub fn test_relink() {
        silence_errors();
        with_tmp_file(|file| {
            file.create_group("test").unwrap();
            file.group("test").unwrap();
            assert_err!(file.relink("test", "foo/test"),
                        "unable to move link: component not found");
            file.create_group("foo").unwrap();
            assert_err!(file.relink("bar", "/baz"),
                        "unable to move link: name doesn't exist");
            file.relink("test", "/foo/test").unwrap();
            file.group("/foo/test").unwrap();
            assert_err!(file.group("test"),
                        "unable to open group: object.+doesn't exist");
        })
    }
}
<|endoftext|>


<commit_before>
#[lang="panic_fmt"]
#[no_mangle]
pub extern "C" fn rust_begin_unwind(args: ::core::fmt::Arguments, file: &str, line: usize) -> !
{
    // 'args' will print to the formatted string passed to panic!
    use core::fmt::Write;
    let _ = write!(&mut ::PrintWriter::new(), "file='{}', line={} :: {}", file, line, args);
    loop {}
}

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Clone,Copy)]
pub enum _Unwind_Reason_Code
{
	_URC_NO_REASON = 0,
	_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
	_URC_FATAL_PHASE2_ERROR = 2,
	_URC_FATAL_PHASE1_ERROR = 3,
	_URC_NORMAL_STOP = 4,
	_URC_END_OF_STACK = 5,
	_URC_HANDLER_FOUND = 6,
	_URC_INSTALL_CONTEXT = 7,
	_URC_CONTINUE_UNWIND = 8,
}

#[allow(non_camel_case_types)]
#[derive(Clone,Copy)]
pub struct _Unwind_Context;

#[allow(non_camel_case_types)]
pub type _Unwind_Action = u32;
static _UA_SEARCH_PHASE: _Unwind_Action = 1;

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Clone,Copy)]
pub struct _Unwind_Exception
{
	exception_class: u64,
	exception_cleanup: fn(_Unwind_Reason_Code,*const _Unwind_Exception),
	private: [u64; 2],
}

#[lang="eh_personality"]
#[no_mangle]
pub fn rust_eh_personality(
	_version: isize, _actions: _Unwind_Action, _exception_class: u64,
	_exception_object: &_Unwind_Exception, _context: &_Unwind_Context
	) -> _Unwind_Reason_Code
{
	loop{}
}

#[no_mangle]
#[allow(non_snake_case)]
pub fn _Unwind_Resume()
{
	loop{}
}
<commit_msg>Use system print for unwind<commit_after>
#[lang="panic_fmt"]
#[no_mangle]
pub extern "C" fn rust_begin_unwind(args: ::core::fmt::Arguments, file: &str, line: usize) -> !
{
    // 'args' will print to the formatted string passed to panic!
    use core::fmt::Write;
    system_print!("file='{}', line={} :: {}", file, line, args);
    loop {}
}

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Clone,Copy)]
pub enum _Unwind_Reason_Code
{
	_URC_NO_REASON = 0,
	_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
	_URC_FATAL_PHASE2_ERROR = 2,
	_URC_FATAL_PHASE1_ERROR = 3,
	_URC_NORMAL_STOP = 4,
	_URC_END_OF_STACK = 5,
	_URC_HANDLER_FOUND = 6,
	_URC_INSTALL_CONTEXT = 7,
	_URC_CONTINUE_UNWIND = 8,
}

#[allow(non_camel_case_types)]
#[derive(Clone,Copy)]
pub struct _Unwind_Context;

#[allow(non_camel_case_types)]
pub type _Unwind_Action = u32;
static _UA_SEARCH_PHASE: _Unwind_Action = 1;

#[allow(non_camel_case_types)]
#[repr(C)]
#[derive(Clone,Copy)]
pub struct _Unwind_Exception
{
	exception_class: u64,
	exception_cleanup: fn(_Unwind_Reason_Code,*const _Unwind_Exception),
	private: [u64; 2],
}

#[lang="eh_personality"]
#[no_mangle]
pub fn rust_eh_personality(
	_version: isize, _actions: _Unwind_Action, _exception_class: u64,
	_exception_object: &_Unwind_Exception, _context: &_Unwind_Context
	) -> _Unwind_Reason_Code
{
	loop{}
}

#[no_mangle]
#[allow(non_snake_case)]
pub fn _Unwind_Resume()
{
	loop{}
}
<|endoftext|>


<commit_before>use core::arch::asm;

use crate::{
    context,
    cpu_id,
    interrupt::stack_trace,
    syscall,
    syscall::flag::*,

    with_exception_stack,
    exception_stack,
};

exception_stack!(synchronous_exception_at_el1_with_sp0, |stack| {
    println!("Synchronous exception at EL1 with SP0");
    stack.dump();
    stack_trace();
    loop {}
});

exception_stack!(synchronous_exception_at_el1_with_spx, |stack| {
    println!("Synchronous exception at EL1 with SPx");
    stack.dump();
    stack_trace();
    loop {}
});

exception_stack!(synchronous_exception_at_el0, |stack| {
    with_exception_stack!(|stack| {
        let exception_code = (stack.iret.esr_el1 & (0x3f << 26)) >> 26;
        if exception_code != 0b010101 {
            println!("FATAL: Not an SVC induced synchronous exception");
            stack.dump();
            stack_trace();

            println!("CPU {}, PID {:?}", cpu_id(), context::context_id());

            // This could deadlock, but at this point we are going to halt anyways
            {
                let contexts = context::contexts();
                if let Some(context_lock) = contexts.current() {
                    let context = context_lock.read();
                    println!("NAME: {}", *context.name.read());
                }
            }

            // Halt
            loop {}
        }

        let scratch = &stack.scratch;
        syscall::syscall(scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, stack)
    });
});

exception_stack!(unhandled_exception, |stack| {
    println!("Unhandled exception");
    stack.dump();
    stack_trace();
    loop {}
});
<commit_msg>Send SIGSEGV on aarch64 exception<commit_after>use core::arch::asm;

use crate::{
    context,
    cpu_id,
    interrupt::stack_trace,
    syscall,
    syscall::flag::*,

    with_exception_stack,
    exception_stack,
};

exception_stack!(synchronous_exception_at_el1_with_sp0, |stack| {
    println!("Synchronous exception at EL1 with SP0");
    stack.dump();
    stack_trace();
    loop {}
});

exception_stack!(synchronous_exception_at_el1_with_spx, |stack| {
    println!("Synchronous exception at EL1 with SPx");
    stack.dump();
    stack_trace();
    loop {}
});

exception_stack!(synchronous_exception_at_el0, |stack| {
    with_exception_stack!(|stack| {
        let exception_code = (stack.iret.esr_el1 & (0x3f << 26)) >> 26;
        if exception_code != 0b010101 {
            println!("FATAL: Not an SVC induced synchronous exception");
            stack.dump();
            stack_trace();
            crate::ksignal(SIGSEGV);
            stack.scratch.x0
        } else {
            let scratch = &stack.scratch;
            syscall::syscall(scratch.x8, scratch.x0, scratch.x1, scratch.x2, scratch.x3, scratch.x4, stack)
        }
    });
});

exception_stack!(unhandled_exception, |stack| {
    println!("Unhandled exception");
    stack.dump();
    stack_trace();
    loop {}
});
<|endoftext|>


<commit_before>#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]

#[miri_run(expected = "Int(1)")]
fn ret() -> i32 {
    1
}

#[miri_run(expected = "Int(-1)")]
fn neg() -> i32 {
    -1
}

#[miri_run(expected = "Int(3)")]
fn add() -> i32 {
    1 + 2
}

#[miri_run(expected = "Int(3)")]
fn indirect_add() -> i32 {
    let x = 1;
    let y = 2;
    x + y
}

#[miri_run(expected = "Int(25)")]
fn arith() -> i32 {
    3*3 + 4*4
}

#[miri_run(expected = "Int(0)")]
fn if_false() -> i32 {
    if false { 1 } else { 0 }
}

#[miri_run(expected = "Int(1)")]
fn if_true() -> i32 {
    if true { 1 } else { 0 }
}

#[miri_run(expected = "Int(2)")]
fn call() -> i32 {
    fn increment(x: i32) -> i32 {
        x + 1
    }

    increment(1)
}

// #[miri_run(expected = "Int(3628800)")]
// fn factorial_loop() -> i32 {
//     let mut product = 1;
//     let mut i = 1;

//     while i <= 10 {
//         product *= i;
//         i += 1;
//     }

//     product
// }

#[miri_run(expected = "Int(3628800)")]
fn factorial_recursive() -> i32 {
    fn fact(n: i32) -> i32 {
        if n == 0 {
            1
        } else {
            n * fact(n - 1)
        }
    }

    fact(10)
}

#[miri_run(expected = "Int(1)")]
fn match_bool() -> i32 {
    let b = true;
    match b {
        true => 1,
        false => 0,
    }
}

#[miri_run(expected = "Int(20)")]
fn match_int() -> i32 {
    let n = 2;
    match n {
        0 => 0,
        1 => 10,
        2 => 20,
        3 => 30,
        _ => 100,
    }
}

#[miri_run(expected = "Int(1)")]
fn one_line_ref() -> i32 {
    *&1
}

#[miri_run(expected = "Int(1)")]
fn basic_ref() -> i32 {
    let x = &1;
    *x
}

#[miri_run(expected = "Int(3)")]
fn basic_ref_mut() -> i32 {
    let x = &mut 1;
    *x += 2;
    *x
}

// #[miri_run(expected = "Int(3)")]
// fn basic_ref_mut_var() -> i32 {
//     let mut a = 1;
//     {
//         let x = &mut a;
//         *x += 2;
//     }
//     a
// }

#[miri_run(expected = "Int(4)")]
fn match_int_range() -> i32 {
    let n = 42;
    match n {
        0...9 => 0,
        10...19 => 1,
        20...29 => 2,
        30...39 => 3,
        40...49 => 4,
        _ => 5,
    }
}

enum MyOption<T> {
    Some { data: T },
    None,
}

#[miri_run(expected = "Int(13)")]
fn match_my_opt_some() -> i32 {
    let x = MyOption::Some { data: 13 };
    match x {
        MyOption::Some { data } => data,
        MyOption::None => 42,
    }
}

#[miri_run(expected = "Int(42)")]
fn match_my_opt_none() -> i32 {
    let x = MyOption::None;
    match x {
        MyOption::Some { data } => data,
        MyOption::None => 42,
    }
}

// #[miri_run(expected = "Int(13)")]
// fn match_opt_some() -> i32 {
//     let x = Some(13);
//     match x {
//         Some(data)  => data,
//         None => 42,
//     }
// }

/// Test calling a very simple function from the standard library.
#[miri_run(expected = "Int(1)")]
fn cross_crate_fn_call() -> i32 {
    if 1i32.is_positive() { 1 } else { 0 }
}

fn main() {}
<commit_msg>Enable a test that works now with rustc master.<commit_after>#![feature(custom_attribute)]
#![allow(dead_code, unused_attributes)]

#[miri_run(expected = "Int(1)")]
fn ret() -> i32 {
    1
}

#[miri_run(expected = "Int(-1)")]
fn neg() -> i32 {
    -1
}

#[miri_run(expected = "Int(3)")]
fn add() -> i32 {
    1 + 2
}

#[miri_run(expected = "Int(3)")]
fn indirect_add() -> i32 {
    let x = 1;
    let y = 2;
    x + y
}

#[miri_run(expected = "Int(25)")]
fn arith() -> i32 {
    3*3 + 4*4
}

#[miri_run(expected = "Int(0)")]
fn if_false() -> i32 {
    if false { 1 } else { 0 }
}

#[miri_run(expected = "Int(1)")]
fn if_true() -> i32 {
    if true { 1 } else { 0 }
}

#[miri_run(expected = "Int(2)")]
fn call() -> i32 {
    fn increment(x: i32) -> i32 {
        x + 1
    }

    increment(1)
}

// #[miri_run(expected = "Int(3628800)")]
// fn factorial_loop() -> i32 {
//     let mut product = 1;
//     let mut i = 1;

//     while i <= 10 {
//         product *= i;
//         i += 1;
//     }

//     product
// }

#[miri_run(expected = "Int(3628800)")]
fn factorial_recursive() -> i32 {
    fn fact(n: i32) -> i32 {
        if n == 0 {
            1
        } else {
            n * fact(n - 1)
        }
    }

    fact(10)
}

#[miri_run(expected = "Int(1)")]
fn match_bool() -> i32 {
    let b = true;
    match b {
        true => 1,
        false => 0,
    }
}

#[miri_run(expected = "Int(20)")]
fn match_int() -> i32 {
    let n = 2;
    match n {
        0 => 0,
        1 => 10,
        2 => 20,
        3 => 30,
        _ => 100,
    }
}

#[miri_run(expected = "Int(1)")]
fn one_line_ref() -> i32 {
    *&1
}

#[miri_run(expected = "Int(1)")]
fn basic_ref() -> i32 {
    let x = &1;
    *x
}

#[miri_run(expected = "Int(3)")]
fn basic_ref_mut() -> i32 {
    let x = &mut 1;
    *x += 2;
    *x
}

// #[miri_run(expected = "Int(3)")]
// fn basic_ref_mut_var() -> i32 {
//     let mut a = 1;
//     {
//         let x = &mut a;
//         *x += 2;
//     }
//     a
// }

#[miri_run(expected = "Int(4)")]
fn match_int_range() -> i32 {
    let n = 42;
    match n {
        0...9 => 0,
        10...19 => 1,
        20...29 => 2,
        30...39 => 3,
        40...49 => 4,
        _ => 5,
    }
}

enum MyOption<T> {
    Some { data: T },
    None,
}

#[miri_run(expected = "Int(13)")]
fn match_my_opt_some() -> i32 {
    let x = MyOption::Some { data: 13 };
    match x {
        MyOption::Some { data } => data,
        MyOption::None => 42,
    }
}

#[miri_run(expected = "Int(42)")]
fn match_my_opt_none() -> i32 {
    let x = MyOption::None;
    match x {
        MyOption::Some { data } => data,
        MyOption::None => 42,
    }
}

#[miri_run(expected = "Int(13)")]
fn match_opt_some() -> i32 {
    let x = Some(13);
    match x {
        Some(data)  => data,
        None => 42,
    }
}

/// Test calling a very simple function from the standard library.
#[miri_run(expected = "Int(1)")]
fn cross_crate_fn_call() -> i32 {
    if 1i32.is_positive() { 1 } else { 0 }
}

fn main() {}
<|endoftext|>


<commit_before>use clap;

use std::ffi::OsString;

use super::{Context, ArgumentType};
use super::internal::{Feedback, CollectedCommand};

pub struct ClapBackend;

impl ClapBackend {
    //TODO: remove code duplication
    #[doc(hiden)]
    pub fn execute_cmd_string<I, T>(commands: &[CollectedCommand], line: I) -> Feedback
    where I: IntoIterator<Item=T>, T: Into<OsString> + Clone
    {
        let app =
        clap::App::new("Exonum application based on fabric configuration.")
                .version(crate_version!())
                .author("Vladimir M. <vladimir.motylenko@xdev.re>")
                .about("It contain basic set of command, to deploy network on exonum.");

        let subcommands: Vec<_> = commands.iter().map(|command|
            ClapBackend::command_into_subcommand(command)
        ).collect();

        let matches = app.subcommands(subcommands.into_iter())
                         .get_matches_from_safe(line).unwrap();

        let subcommand = matches.subcommand();
        for command in commands {
            if command.name() == subcommand.0 {
                return command.execute(
                            Context::new_from_args(
                                command.args(),
                                subcommand.1.expect("Arguments not found.")
                            ))
            }
        }

        panic!("Subcommand not found");
    }
    pub fn execute(commands: &[CollectedCommand]) -> Feedback {
        let app =
        clap::App::new("Exonum application based on fabric configuration.")
                .version(crate_version!())
                .author(crate_authors!("\n"))
                .about("Exonum application based on fabric configuration.");

        let subcommands: Vec<_> = commands.iter().map(|command|
            ClapBackend::command_into_subcommand(command)
        ).collect();

        let matches = app.subcommands(subcommands.into_iter()).get_matches();

        let subcommand = matches.subcommand();
        for command in commands {
            if command.name() == subcommand.0 {
                return command.execute(
                            Context::new_from_args(
                                command.args(),
                                subcommand.1.expect("Arguments not found.")
                            ))
            }
        }

        panic!("Subcommand not found");
    }

    fn command_into_subcommand(command: & CollectedCommand) -> clap::App {
        let mut index = 1;
        let command_args: Vec<_> =
            command.args()
                .iter()
                .map(|arg|{
                    let clap_arg = clap::Arg::with_name(arg.name);
                    let clap_arg = match arg.argument_type {
                        ArgumentType::Positional => {
                            let arg = clap_arg.index(index);
                            index += 1;
                            arg
                        }
                        ArgumentType::Named(detail) => {
                            let mut clap_arg = clap_arg.long(detail.long_name);
                            if let Some(short) = detail.short_name {
                                clap_arg = clap_arg.short(short);
                            }
                            clap_arg.multiple(detail.multiple)
                                    .takes_value(true)
                        }
                    };
                    clap_arg.help(arg.help)
                            .required(arg.required)

                    }).collect();

        let mut subcommand = clap::SubCommand::with_name(command.name())
            .about(command.about());

        subcommand = subcommand.args(&command_args);

        subcommand
    }
}
<commit_msg>fix authors<commit_after>use clap;

use std::ffi::OsString;

use super::{Context, ArgumentType};
use super::internal::{Feedback, CollectedCommand};

pub struct ClapBackend;

impl ClapBackend {
    //TODO: remove code duplication
    #[doc(hiden)]
    pub fn execute_cmd_string<I, T>(commands: &[CollectedCommand], line: I) -> Feedback
    where I: IntoIterator<Item=T>, T: Into<OsString> + Clone
    {
        let app =
        clap::App::new("Exonum application based on fabric configuration.")
                .version(crate_version!())
                .author(crate_authors!("\n"))
                .about("It contain basic set of command, to deploy network on exonum.");

        let subcommands: Vec<_> = commands.iter().map(|command|
            ClapBackend::command_into_subcommand(command)
        ).collect();

        let matches = app.subcommands(subcommands.into_iter())
                         .get_matches_from_safe(line).unwrap();

        let subcommand = matches.subcommand();
        for command in commands {
            if command.name() == subcommand.0 {
                return command.execute(
                            Context::new_from_args(
                                command.args(),
                                subcommand.1.expect("Arguments not found.")
                            ))
            }
        }

        panic!("Subcommand not found");
    }
    pub fn execute(commands: &[CollectedCommand]) -> Feedback {
        let app =
        clap::App::new("Exonum application based on fabric configuration.")
                .version(crate_version!())
                .author(crate_authors!("\n"))
                .about("Exonum application based on fabric configuration.");

        let subcommands: Vec<_> = commands.iter().map(|command|
            ClapBackend::command_into_subcommand(command)
        ).collect();

        let matches = app.subcommands(subcommands.into_iter()).get_matches();

        let subcommand = matches.subcommand();
        for command in commands {
            if command.name() == subcommand.0 {
                return command.execute(
                            Context::new_from_args(
                                command.args(),
                                subcommand.1.expect("Arguments not found.")
                            ))
            }
        }

        panic!("Subcommand not found");
    }

    fn command_into_subcommand(command: & CollectedCommand) -> clap::App {
        let mut index = 1;
        let command_args: Vec<_> =
            command.args()
                .iter()
                .map(|arg|{
                    let clap_arg = clap::Arg::with_name(arg.name);
                    let clap_arg = match arg.argument_type {
                        ArgumentType::Positional => {
                            let arg = clap_arg.index(index);
                            index += 1;
                            arg
                        }
                        ArgumentType::Named(detail) => {
                            let mut clap_arg = clap_arg.long(detail.long_name);
                            if let Some(short) = detail.short_name {
                                clap_arg = clap_arg.short(short);
                            }
                            clap_arg.multiple(detail.multiple)
                                    .takes_value(true)
                        }
                    };
                    clap_arg.help(arg.help)
                            .required(arg.required)

                    }).collect();

        let mut subcommand = clap::SubCommand::with_name(command.name())
            .about(command.about());

        subcommand = subcommand.args(&command_args);

        subcommand
    }
}
<|endoftext|>


<commit_before>//!
//! ```rust
//! use can_dbc::DBC;
//! use codegen::Scope;
//!
//! use std::fs::File;
//! use std::io;
//! use std::io::prelude::*;
//!
//! fn main() -> io::Result<()> {
//!     let mut f = File::open("./examples/sample.dbc")?;
//!     let mut buffer = Vec::new();
//!     f.read_to_end(&mut buffer)?;
//!
//!     let dbc = can_dbc::DBC::from_slice(&buffer).expect("Failed to parse dbc file");
//!
//!     let mut scope = Scope::new();
//!     for message in dbc.messages() {
//!         for signal in message.signals() {
//!
//!             let mut scope = Scope::new();
//!             let message_struct = scope.new_struct(message.message_name());
//!             for signal in message.signals() {
//!                 message_struct.field(signal.name().to_lowercase().as_str(), "f64");
//!             }
//!         }
//!     }
//!
//!     println!("{}", scope.to_string());
//!     Ok(())
//! }
//! ```

use derive_getters::Getters;
use nom::*;
use nom::types::CompleteByteSlice;

pub mod parser;

#[cfg(test)]
mod tests {

    use super::*;
    use std::str;

    #[test]
    fn dbc_definition_test() {
        let sample_dbc =
        b"
VERSION \"0.1\"
NS_ :
    NS_DESC_
    CM_
    BA_DEF_
    BA_
    VAL_
    CAT_DEF_
    CAT_
    FILTER
    BA_DEF_DEF_
    EV_DATA_
    ENVVAR_DATA_
    SGTYPE_
    SGTYPE_VAL_
    BA_DEF_SGTYPE_
    BA_SGTYPE_
    SIG_TYPE_REF_
    VAL_TABLE_
    SIG_GROUP_
    SIG_VALTYPE_
    SIGTYPE_VALTYPE_
    BO_TX_BU_
    BA_DEF_REL_
    BA_REL_
    BA_DEF_DEF_REL_
    BU_SG_REL_
    BU_EV_REL_
    BU_BO_REL_
    SG_MUL_VAL_
BS_:
BU_: PC
BO_ 2000 WebData_2000: 4 Vector__XXX
    SG_ Signal_8 : 24|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_7 : 16|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_6 : 8|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_5 : 0|8@1+ (1,0) [0|255] \"\" Vector__XXX
BO_ 1840 WebData_1840: 4 PC
    SG_ Signal_4 : 24|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_3 : 16|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_2 : 8|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_1 : 0|8@1+ (1,0) [0|0] \"\" Vector__XXX

EV_ Environment1: 0 [0|220] \"\" 0 6 DUMMY_NODE_VECTOR0 DUMMY_NODE_VECTOR2;
EV_ Environment2: 0 [0|177] \"\" 0 7 DUMMY_NODE_VECTOR1 DUMMY_NODE_VECTOR2;
ENVVAR_DATA_ SomeEnvVarData: 399;

CM_ SG_ 4 TestSigLittleUnsigned1 \"asaklfjlsdfjlsdfgls
HH?=(%)/&KKDKFSDKFKDFKSDFKSDFNKCnvsdcvsvxkcv\";
CM_ SG_ 5 TestSigLittleUnsigned1 \"asaklfjlsdfjlsdfgls
=0943503450KFSDKFKDFKSDFKSDFNKCnvsdcvsvxkcv\";

BA_DEF_DEF_ \"BusType\" \"AS\";

BA_ \"Attr\" BO_ 4358435 283;
BA_ \"Attr\" BO_ 56949545 344;
";
        match DBC::from_slice(sample_dbc) {
            Ok(dbc_content) => println!("DBC Content{:#?}", dbc_content),
            Err(e) => {
                match e {
                    Error::NomError(nom::Err::Incomplete(needed)) => eprintln!("Error incomplete input, needed: {:?}", needed),
                    Error::NomError(nom::Err::Error(ctx)) => {
                        match ctx {
                            verbose_errors::Context::Code(i, kind) => eprintln!("Error Kind: {:?}, Code: {:?}", kind, str::from_utf8(i.as_bytes())),
                            verbose_errors::Context::List(l)=> eprintln!("Error List: {:?}", l),
                        }
                    }
                    Error::NomError(nom::Err::Failure(ctx)) => eprintln!("Failure {:?}", ctx),
                    Error::Incomplete(dbc, remaining) => eprintln!("Not all data in buffer was read {:#?}, remaining unparsed: {}", dbc, String::from_utf8(remaining).unwrap())
                }
                panic!("Failed to read DBC");
            }
        }
    }
}

#[derive(Debug)]
pub enum Error<'a> {
    // Remaining String
    Incomplete(DBC, Vec<u8>),
    NomError(nom::Err<nom::types::CompleteByteSlice<'a>, u32>)
}

#[derive(Clone, Debug, PartialEq)]
pub struct Label(String);

/// Baudrate in kbit/s
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Baudrate(u64);

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct Signal {
    name: String,
    multiplexer_indicator: MultiplexIndicator,
    pub start_bit: u64,
    pub signal_size: u64,
    byte_order: ByteOrder,
    value_type: ValueType,
    pub factor: f64,
    pub offset: f64,
    pub min: f64,
    pub max: f64,
    unit: String,
    receivers: Vec<String>,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub struct MessageId(u64);

#[derive(Clone, Debug, PartialEq)]
pub enum Transmitter {
    /// node transmitting the message
    NodeName(String),
    /// message has no sender
    VectorXXX
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct MessageTransmitter {
    message_id: MessageId,
    transmitter: Transmitter,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Version(String);

#[derive(Clone, Debug, PartialEq)]
pub struct Symbol(String);

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum MultiplexIndicator {
    /// Multiplexor switch
    Multiplexor,
    /// Signal us being multiplexed by the multiplexer switch.
    MultiplexedSignal(u64),
    /// Normal signal
    Plain,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ByteOrder {
    LittleEndian,
    BigEndian,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ValueType {
    Signed,
    Unsigned,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum EnvType {
    EnvTypeFloat,
    EnvTypeu64,
    EnvTypeData,
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct SignalType {
    signal_type_name: String,
    signal_size: u64,
    byte_order: ByteOrder,
    value_type: ValueType,
    factor: f64,
    offset: f64,
    min: f64,
    max: f64,
    unit: String,
    default_value: f64,
    value_table: String,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum AccessType {
    DummyNodeVector0,
    DummyNodeVector1,
    DummyNodeVector2,
    DummyNodeVector3,
}

#[derive(Clone, Debug, PartialEq)]
pub enum AccessNode {
    AccessNodeVectorXXX,
    AccessNodeName(String),
}

#[derive(Clone, Debug, PartialEq)]
pub enum SignalAttributeValue {
    Text(String),
    Int(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum AttributeValuedForObjectType {
    RawAttributeValue(AttributeValue),
    NetworkNodeAttributeValue(String, AttributeValue),
    MessageDefinitionAttributeValue(MessageId, Option<AttributeValue>),
    SignalAttributeValue(MessageId, String, AttributeValue),
    EnvVariableAttributeValue(String, AttributeValue),
}

#[derive(Clone, Debug, PartialEq)]
pub enum AttributeValueType {
    AttributeValueTypeInt(i64, i64),
    AttributeValueTypeHex(i64, i64),
    AttributeValueTypeFloat(f64, f64),
    AttributeValueTypeString,
    AttributeValueTypeEnum(Vec<String>),
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct ValDescription {
    a: f64,
    b: String,
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct AttrDefault {
    name: String,
    value: AttributeValue,
}

#[derive(Clone, Debug, PartialEq)]
pub enum AttributeValue {
    AttributeValueU64(u64),
    AttributeValueI64(i64),
    AttributeValueF64(f64),
    AttributeValueCharString(String),
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct ValueTable {
    value_table_name: String,
    value_descriptions: Vec<ValDescription>
}

#[derive(Clone, Debug, PartialEq)]
pub enum Comment {
    Node { node_name: String, comment: String },
    Message { message_id: MessageId, comment: String },
    Signal { message_id: MessageId, signal_name: String, comment: String },
    EnvVar { env_var_name: String, comment: String },
    Plain { comment: String },
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct Message {
    message_id: MessageId,
    message_name: String,
    message_size: u64,
    transmitter: Transmitter,
    signals: Vec<Signal>
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct EnvironmentVariable {
    env_var_name: String,
    env_var_type: EnvType,
    min: i64,
    max: i64,
    unit: String,
    initial_value: f64,
    ev_id: i64,
    access_type: AccessType,
    access_nodes: Vec<AccessNode>,
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct EnvironmentVariableData {
    env_var_name: String,
    data_size: u64,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Node(Vec<String>);

#[derive(Clone,Debug, PartialEq, Getters)]
pub struct AttributeDefault {
    attribute_name: String,
    attribute_value: AttributeValue,
}

#[derive(Clone,Debug, PartialEq, Getters)]
pub struct AttributeValueForObject {
    attribute_name: String,
    attribute_value: AttributeValuedForObjectType,
}

#[derive(Clone, Debug, PartialEq)]
pub enum AttributeDefinition {
    // TODO add properties
    Message(String),
    // TODO add properties
    Node(String),
    // TODO add properties
    Signal(String),
    EnvironmentVariable(String),
    // TODO figure out name
    Plain(String),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueDescription {
    Signal {
        message_id: MessageId,
        signal_name: String,
        value_descriptions: Vec<ValDescription>
    },
    EnvironmentVariable {
        env_var_name: String,
        value_descriptions: Vec<ValDescription>
    },
}

#[derive(Clone, Debug, PartialEq)]
pub struct SignalTypeRef {
    message_id: MessageId,
    signal_name: String,
    signal_type_name: String,
}

#[derive(Clone, Debug, PartialEq)]
pub struct SignalGroups {
    message_id: MessageId,
    signal_group_name: String,
    repetitions: u64,
    signal_names: Vec<String>,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SignalExtendedValueType {
    SignedOrUnsignedInteger,
    IEEEfloat32Bit,
    IEEEdouble64bit,
}

#[derive(Clone, Debug, PartialEq,Getters)]
pub struct SignalExtendedValueTypeList {
    message_id: MessageId,
    signal_name: String,
    signal_extended_value_type: SignalExtendedValueType
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct DBC {
    version: Version,
    new_symbols: Vec<Symbol>,
    bit_timing: Option<Vec<Baudrate>>,
    nodes: Vec<Node>,
    value_tables: Vec<ValueTable>,
    messages: Vec<Message>,
    message_transmitters: Vec<MessageTransmitter>,
    environment_variables: Vec<EnvironmentVariable>,
    environment_variable_data: Vec<EnvironmentVariableData>,
    signal_types: Vec<SignalType>,
    ///
    /// Object comments.
    ///
    comments: Vec<Comment>,
    attribute_definitions: Vec<AttributeDefinition>,
    // undefined
    // sigtype_attr_list: SigtypeAttrList,
    attribute_defaults: Vec<AttributeDefault>,
    attribute_values: Vec<AttributeValueForObject>,
    ///
    /// Encoding for signal raw values.
    ///
    value_descriptions: Vec<ValueDescription>,
    // obsolete + undefined
    // category_definitions: Vec<CategoryDefinition>,
    // obsolete + undefined
    //categories: Vec<Category>,
    // obsolete + undefined
    //filter: Vec<Filter>,
    signal_type_refs: Vec<SignalTypeRef>,
    ///
    /// signal groups define a group of signals within a message
    ///
    signal_groups: Option<SignalGroups>,
    signal_extended_value_type_list: Option<SignalExtendedValueTypeList>,
}

impl DBC {
    pub fn from_slice(buffer: &[u8]) -> Result<DBC, Error> {
        match parser::dbc(CompleteByteSlice(buffer)) {
            Ok((remaining, dbc)) => {
                if !remaining.is_empty() {
                    return Err(Error::Incomplete(dbc, remaining.as_bytes().to_vec()));
                }
                Ok(dbc)
            },
            Err(e) => Err(Error::NomError(e))
        }
    }
}<commit_msg>Add documentation<commit_after>//!
//! ```rust
//! use can_dbc::DBC;
//! use codegen::Scope;
//!
//! use std::fs::File;
//! use std::io;
//! use std::io::prelude::*;
//!
//! fn main() -> io::Result<()> {
//!     let mut f = File::open("./examples/sample.dbc")?;
//!     let mut buffer = Vec::new();
//!     f.read_to_end(&mut buffer)?;
//!
//!     let dbc = can_dbc::DBC::from_slice(&buffer).expect("Failed to parse dbc file");
//!
//!     let mut scope = Scope::new();
//!     for message in dbc.messages() {
//!         for signal in message.signals() {
//!
//!             let mut scope = Scope::new();
//!             let message_struct = scope.new_struct(message.message_name());
//!             for signal in message.signals() {
//!                 message_struct.field(signal.name().to_lowercase().as_str(), "f64");
//!             }
//!         }
//!     }
//!
//!     println!("{}", scope.to_string());
//!     Ok(())
//! }
//! ```

use derive_getters::Getters;
use nom::*;
use nom::types::CompleteByteSlice;

pub mod parser;

#[cfg(test)]
mod tests {

    use super::*;
    use std::str;

    #[test]
    fn dbc_definition_test() {
        let sample_dbc =
        b"
VERSION \"0.1\"
NS_ :
    NS_DESC_
    CM_
    BA_DEF_
    BA_
    VAL_
    CAT_DEF_
    CAT_
    FILTER
    BA_DEF_DEF_
    EV_DATA_
    ENVVAR_DATA_
    SGTYPE_
    SGTYPE_VAL_
    BA_DEF_SGTYPE_
    BA_SGTYPE_
    SIG_TYPE_REF_
    VAL_TABLE_
    SIG_GROUP_
    SIG_VALTYPE_
    SIGTYPE_VALTYPE_
    BO_TX_BU_
    BA_DEF_REL_
    BA_REL_
    BA_DEF_DEF_REL_
    BU_SG_REL_
    BU_EV_REL_
    BU_BO_REL_
    SG_MUL_VAL_
BS_:
BU_: PC
BO_ 2000 WebData_2000: 4 Vector__XXX
    SG_ Signal_8 : 24|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_7 : 16|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_6 : 8|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_5 : 0|8@1+ (1,0) [0|255] \"\" Vector__XXX
BO_ 1840 WebData_1840: 4 PC
    SG_ Signal_4 : 24|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_3 : 16|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_2 : 8|8@1+ (1,0) [0|255] \"\" Vector__XXX
    SG_ Signal_1 : 0|8@1+ (1,0) [0|0] \"\" Vector__XXX

EV_ Environment1: 0 [0|220] \"\" 0 6 DUMMY_NODE_VECTOR0 DUMMY_NODE_VECTOR2;
EV_ Environment2: 0 [0|177] \"\" 0 7 DUMMY_NODE_VECTOR1 DUMMY_NODE_VECTOR2;
ENVVAR_DATA_ SomeEnvVarData: 399;

CM_ SG_ 4 TestSigLittleUnsigned1 \"asaklfjlsdfjlsdfgls
HH?=(%)/&KKDKFSDKFKDFKSDFKSDFNKCnvsdcvsvxkcv\";
CM_ SG_ 5 TestSigLittleUnsigned1 \"asaklfjlsdfjlsdfgls
=0943503450KFSDKFKDFKSDFKSDFNKCnvsdcvsvxkcv\";

BA_DEF_DEF_ \"BusType\" \"AS\";

BA_ \"Attr\" BO_ 4358435 283;
BA_ \"Attr\" BO_ 56949545 344;
";
        match DBC::from_slice(sample_dbc) {
            Ok(dbc_content) => println!("DBC Content{:#?}", dbc_content),
            Err(e) => {
                match e {
                    Error::NomError(nom::Err::Incomplete(needed)) => eprintln!("Error incomplete input, needed: {:?}", needed),
                    Error::NomError(nom::Err::Error(ctx)) => {
                        match ctx {
                            verbose_errors::Context::Code(i, kind) => eprintln!("Error Kind: {:?}, Code: {:?}", kind, str::from_utf8(i.as_bytes())),
                            verbose_errors::Context::List(l)=> eprintln!("Error List: {:?}", l),
                        }
                    }
                    Error::NomError(nom::Err::Failure(ctx)) => eprintln!("Failure {:?}", ctx),
                    Error::Incomplete(dbc, remaining) => eprintln!("Not all data in buffer was read {:#?}, remaining unparsed: {}", dbc, String::from_utf8(remaining).unwrap())
                }
                panic!("Failed to read DBC");
            }
        }
    }
}

/// Possible error cases for `can-dbc`
#[derive(Debug)]
pub enum Error<'a> {
    // Remaining String
    Incomplete(DBC, Vec<u8>),
    NomError(nom::Err<nom::types::CompleteByteSlice<'a>, u32>)
}

/// Baudrate of network in kbit/s
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Baudrate(u64);

/// One or multiple signals are the payload of a CAN frame.
/// To determine the actual value of a signal the following fn applies:
/// `let fnvalue = |can_signal_value| -> can_signal_value * factor + offset;`
#[derive(Clone, Debug, PartialEq, Getters)]
pub struct Signal {
    name: String,
    multiplexer_indicator: MultiplexIndicator,
    pub start_bit: u64,
    pub signal_size: u64,
    byte_order: ByteOrder,
    value_type: ValueType,
    pub factor: f64,
    pub offset: f64,
    pub min: f64,
    pub max: f64,
    unit: String,
    receivers: Vec<String>,
}

/// CAN id in header of CAN frame.
/// Must be unique in DBC file.
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct MessageId(u64);

#[derive(Clone, Debug, PartialEq)]
pub enum Transmitter {
    /// node transmitting the message
    NodeName(String),
    /// message has no sender
    VectorXXX
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct MessageTransmitter {
    message_id: MessageId,
    transmitter: Transmitter,
}

/// Version generated by DB editor
#[derive(Clone, Debug, PartialEq)]
pub struct Version(String);

#[derive(Clone, Debug, PartialEq)]
pub struct Symbol(String);

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum MultiplexIndicator {
    /// Multiplexor switch
    Multiplexor,
    /// Signal us being multiplexed by the multiplexer switch.
    MultiplexedSignal(u64),
    /// Normal signal
    Plain,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ByteOrder {
    LittleEndian,
    BigEndian,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ValueType {
    Signed,
    Unsigned,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum EnvType {
    EnvTypeFloat,
    EnvTypeu64,
    EnvTypeData,
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct SignalType {
    signal_type_name: String,
    signal_size: u64,
    byte_order: ByteOrder,
    value_type: ValueType,
    factor: f64,
    offset: f64,
    min: f64,
    max: f64,
    unit: String,
    default_value: f64,
    value_table: String,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum AccessType {
    DummyNodeVector0,
    DummyNodeVector1,
    DummyNodeVector2,
    DummyNodeVector3,
}

#[derive(Clone, Debug, PartialEq)]
pub enum AccessNode {
    AccessNodeVectorXXX,
    AccessNodeName(String),
}

#[derive(Clone, Debug, PartialEq)]
pub enum SignalAttributeValue {
    Text(String),
    Int(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum AttributeValuedForObjectType {
    RawAttributeValue(AttributeValue),
    NetworkNodeAttributeValue(String, AttributeValue),
    MessageDefinitionAttributeValue(MessageId, Option<AttributeValue>),
    SignalAttributeValue(MessageId, String, AttributeValue),
    EnvVariableAttributeValue(String, AttributeValue),
}

#[derive(Clone, Debug, PartialEq)]
pub enum AttributeValueType {
    AttributeValueTypeInt(i64, i64),
    AttributeValueTypeHex(i64, i64),
    AttributeValueTypeFloat(f64, f64),
    AttributeValueTypeString,
    AttributeValueTypeEnum(Vec<String>),
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct ValDescription {
    a: f64,
    b: String,
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct AttrDefault {
    name: String,
    value: AttributeValue,
}

#[derive(Clone, Debug, PartialEq)]
pub enum AttributeValue {
    AttributeValueU64(u64),
    AttributeValueI64(i64),
    AttributeValueF64(f64),
    AttributeValueCharString(String),
}

/// Global value table
#[derive(Clone, Debug, PartialEq, Getters)]
pub struct ValueTable {
    value_table_name: String,
    value_descriptions: Vec<ValDescription>
}

/// Object comments
#[derive(Clone, Debug, PartialEq)]
pub enum Comment {
    Node { node_name: String, comment: String },
    Message { message_id: MessageId, comment: String },
    Signal { message_id: MessageId, signal_name: String, comment: String },
    EnvVar { env_var_name: String, comment: String },
    Plain { comment: String },
}

/// CAN message (frame) details including signal details
#[derive(Clone, Debug, PartialEq, Getters)]
pub struct Message {
    /// CAN id in header of CAN frame.
    /// Must be unique in DBC file.
    message_id: MessageId,
    message_name: String,
    message_size: u64,
    transmitter: Transmitter,
    signals: Vec<Signal>
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct EnvironmentVariable {
    env_var_name: String,
    env_var_type: EnvType,
    min: i64,
    max: i64,
    unit: String,
    initial_value: f64,
    ev_id: i64,
    access_type: AccessType,
    access_nodes: Vec<AccessNode>,
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct EnvironmentVariableData {
    env_var_name: String,
    data_size: u64,
}

/// CAN network nodes, names must be unique
#[derive(Clone, Debug, PartialEq)]
pub struct Node(Vec<String>);

#[derive(Clone,Debug, PartialEq, Getters)]
pub struct AttributeDefault {
    attribute_name: String,
    attribute_value: AttributeValue,
}

#[derive(Clone,Debug, PartialEq, Getters)]
pub struct AttributeValueForObject {
    attribute_name: String,
    attribute_value: AttributeValuedForObjectType,
}

#[derive(Clone, Debug, PartialEq)]
pub enum AttributeDefinition {
    // TODO add properties
    Message(String),
    // TODO add properties
    Node(String),
    // TODO add properties
    Signal(String),
    EnvironmentVariable(String),
    // TODO figure out name
    Plain(String),
}

/// Encoding for signal raw values.
#[derive(Clone, Debug, PartialEq)]
pub enum ValueDescription {
    Signal {
        message_id: MessageId,
        signal_name: String,
        value_descriptions: Vec<ValDescription>
    },
    EnvironmentVariable {
        env_var_name: String,
        value_descriptions: Vec<ValDescription>
    },
}

#[derive(Clone, Debug, PartialEq)]
pub struct SignalTypeRef {
    message_id: MessageId,
    signal_name: String,
    signal_type_name: String,
}

/// Signal groups define a group of signals within a message
#[derive(Clone, Debug, PartialEq)]
pub struct SignalGroups {
    message_id: MessageId,
    signal_group_name: String,
    repetitions: u64,
    signal_names: Vec<String>,
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum SignalExtendedValueType {
    SignedOrUnsignedInteger,
    IEEEfloat32Bit,
    IEEEdouble64bit,
}

#[derive(Clone, Debug, PartialEq,Getters)]
pub struct SignalExtendedValueTypeList {
    message_id: MessageId,
    signal_name: String,
    signal_extended_value_type: SignalExtendedValueType
}

#[derive(Clone, Debug, PartialEq, Getters)]
pub struct DBC {
    /// Version generated by DB editor
    version: Version,
    new_symbols: Vec<Symbol>,
    /// Baud rate of network
    bit_timing: Option<Vec<Baudrate>>,
    /// CAN network nodes
    nodes: Vec<Node>,
    /// Global value table
    value_tables: Vec<ValueTable>,
    /// CAN message (frame) details including signal details
    messages: Vec<Message>,
    message_transmitters: Vec<MessageTransmitter>,
    environment_variables: Vec<EnvironmentVariable>,
    environment_variable_data: Vec<EnvironmentVariableData>,
    signal_types: Vec<SignalType>,
    /// Object comments
    comments: Vec<Comment>,
    attribute_definitions: Vec<AttributeDefinition>,
    // undefined
    // sigtype_attr_list: SigtypeAttrList,
    attribute_defaults: Vec<AttributeDefault>,
    attribute_values: Vec<AttributeValueForObject>,
    /// Encoding for signal raw values
    value_descriptions: Vec<ValueDescription>,
    // obsolete + undefined
    // category_definitions: Vec<CategoryDefinition>,
    // obsolete + undefined
    //categories: Vec<Category>,
    // obsolete + undefined
    //filter: Vec<Filter>,
    signal_type_refs: Vec<SignalTypeRef>,
    /// Signal groups define a group of signals within a message
    signal_groups: Option<SignalGroups>,
    signal_extended_value_type_list: Option<SignalExtendedValueTypeList>,
}

impl DBC {
    pub fn from_slice(buffer: &[u8]) -> Result<DBC, Error> {
        match parser::dbc(CompleteByteSlice(buffer)) {
            Ok((remaining, dbc)) => {
                if !remaining.is_empty() {
                    return Err(Error::Incomplete(dbc, remaining.as_bytes().to_vec()));
                }
                Ok(dbc)
            },
            Err(e) => Err(Error::NomError(e))
        }
    }
}<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use common::*;
use message;

pub type SegmentId = u32;

pub struct SegmentReader<'self> {
    messageReader : &'self message::MessageReader<'self>,
    segment : &'self [u8]
}

pub struct SegmentBuilder {
    messageBuilder : @mut message::MessageBuilder,
    segment : ~[u8],
    id : SegmentId,
    pos : WordCount
}

impl SegmentBuilder {

    pub fn new(messageBuilder : @mut message::MessageBuilder,
               size : ByteCount) -> SegmentBuilder {
        SegmentBuilder {
            messageBuilder : messageBuilder,
            segment : std::vec::from_elem(size, 0u8),
            id : messageBuilder.segments.len() as SegmentId,
            pos : 0
        }
    }

    pub fn allocate(&mut self, amount : WordCount) -> Option<WordCount> {
        if (amount > self.segment.len() - self.pos) {
            return None;
        } else {
            let result = self.pos;
            self.pos += amount;
            return Some(result);
        }
    }

    pub fn available(&self) -> WordCount {
        self.segment.len() * BYTES_PER_WORD - self.pos
    }

    #[inline(always)]
    pub fn memset(&mut self, ptr: uint, c: u8, count: uint) {
        unsafe {
            let p = self.segment.unsafe_mut_ref(ptr);
            std::ptr::set_memory(p, c, count)
        }
    }
}

pub struct BuilderArena {
    message : @mut message::MessageBuilder
}
<commit_msg>remove an (always)<commit_after>/*
 * Copyright (c) 2013, David Renshaw (dwrenshaw@gmail.com)
 *
 * See the LICENSE file in the capnproto-rust root directory.
 */

use std;
use common::*;
use message;

pub type SegmentId = u32;

pub struct SegmentReader<'self> {
    messageReader : &'self message::MessageReader<'self>,
    segment : &'self [u8]
}

pub struct SegmentBuilder {
    messageBuilder : @mut message::MessageBuilder,
    segment : ~[u8],
    id : SegmentId,
    pos : WordCount
}

impl SegmentBuilder {

    pub fn new(messageBuilder : @mut message::MessageBuilder,
               size : ByteCount) -> SegmentBuilder {
        SegmentBuilder {
            messageBuilder : messageBuilder,
            segment : std::vec::from_elem(size, 0u8),
            id : messageBuilder.segments.len() as SegmentId,
            pos : 0
        }
    }

    pub fn allocate(&mut self, amount : WordCount) -> Option<WordCount> {
        if (amount > self.segment.len() - self.pos) {
            return None;
        } else {
            let result = self.pos;
            self.pos += amount;
            return Some(result);
        }
    }

    pub fn available(&self) -> WordCount {
        self.segment.len() * BYTES_PER_WORD - self.pos
    }

    #[inline]
    pub fn memset(&mut self, ptr: uint, c: u8, count: uint) {
        unsafe {
            let p = self.segment.unsafe_mut_ref(ptr);
            std::ptr::set_memory(p, c, count)
        }
    }
}

pub struct BuilderArena {
    message : @mut message::MessageBuilder
}
<|endoftext|>


<commit_before>use std::io::{self, Write};
use termion::event::Key;

use KeyMap;
use Editor;

pub struct Emacs<'a, W: Write> {
    ed: Editor<'a, W>,
}

impl<'a, W: Write> Emacs<'a, W> {
    pub fn new(ed: Editor<'a, W>) -> Self {
        Emacs { ed: ed }
    }

    fn handle_ctrl_key(&mut self, c: char) -> io::Result<()> {
        match c {
            'l' => self.ed.clear(),
            'a' => self.ed.move_cursor_to_start_of_line(),
            'e' => self.ed.move_cursor_to_end_of_line(),
            'b' => self.ed.move_cursor_left(1),
            'f' => self.ed.move_cursor_right(1),
            'd' => self.ed.delete_after_cursor(),
            'p' => self.ed.move_up(),
            'n' => self.ed.move_down(),
            'u' => self.ed.delete_all_before_cursor(),
            'k' => self.ed.delete_all_after_cursor(),
            'w' => self.ed.delete_word_before_cursor(true),
            'x' => {
                try!(self.ed.undo());
                Ok(())
            }
            _ => Ok(()),
        }
    }

    fn handle_alt_key(&mut self, c: char) -> io::Result<()> {
        match c {
            '<' => self.ed.move_to_start_of_history(),
            '>' => self.ed.move_to_end_of_history(),
            '\x7F' => self.ed.delete_word_before_cursor(true),
            'r' => {
                try!(self.ed.revert());
                Ok(())
            }
            _ => Ok(()),
        }
    }
}

impl<'a, W: Write> KeyMap<'a, W, Emacs<'a, W>> for Emacs<'a, W> {
    fn handle_key_core(&mut self, key: Key) -> io::Result<()> {
        match key {
            Key::Char(c) => self.ed.insert_after_cursor(c),
            Key::Alt(c) => self.handle_alt_key(c),
            Key::Ctrl(c) => self.handle_ctrl_key(c),
            Key::Left => self.ed.move_cursor_left(1),
            Key::Right => self.ed.move_cursor_right(1),
            Key::Up => self.ed.move_up(),
            Key::Down => self.ed.move_down(),
            Key::Home => self.ed.move_cursor_to_start_of_line(),
            Key::End => self.ed.move_cursor_to_end_of_line(),
            Key::Backspace => self.ed.delete_before_cursor(),
            Key::Delete => self.ed.delete_after_cursor(),
            Key::Null => Ok(()),
            _ => Ok(()),
        }
    }

    fn editor_mut(&mut self) ->  &mut Editor<'a, W> {
        &mut self.ed
    }

    fn editor(&self) ->  &Editor<'a, W> {
        &self.ed
    }
}

impl<'a, W: Write> From<Emacs<'a, W>> for String {
    fn from(emacs: Emacs<'a, W>) -> String {
        emacs.ed.into()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use termion::event::Key;
    use Context;
    use Editor;
    use KeyMap;
    use std::io::Write;

    macro_rules! simulate_keys {
        ($keymap:ident, $keys:expr) => {{
            simulate_keys(&mut $keymap, $keys.into_iter())
        }}
    }

    fn simulate_keys<'a, 'b, W: Write, T, M: KeyMap<'a, W, T>, I>(keymap: &mut M, keys: I) -> bool
        where I: Iterator<Item = &'b Key>
    {
        for k in keys {
            if keymap.handle_key(*k, &mut |_| {}).unwrap() {
                return true;
            }
        }

        false
    }

    #[test]
    fn enter_is_done() {
        let mut context = Context::new();
        let out = Vec::new();
        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
        let mut map = Emacs::new(ed);
        map.ed.insert_str_after_cursor("done").unwrap();
        assert_eq!(map.ed.cursor(), 4);

        assert!(simulate_keys!(map, [Key::Char('\n')]));

        assert_eq!(map.ed.cursor(), 4);
        assert_eq!(String::from(map), "done");
    }

    #[test]
    fn move_cursor_left() {
        let mut context = Context::new();
        let out = Vec::new();
        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
        let mut map = Emacs::new(ed);
        map.editor_mut().insert_str_after_cursor("let").unwrap();
        assert_eq!(map.ed.cursor(), 3);

        simulate_keys!(map, [Key::Left, Key::Char('f')]);

        assert_eq!(map.ed.cursor(), 3);
        assert_eq!(String::from(map), "left");
    }

    #[test]
    fn cursor_movement() {
        let mut context = Context::new();
        let out = Vec::new();
        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
        let mut map = Emacs::new(ed);
        map.ed.insert_str_after_cursor("right").unwrap();
        assert_eq!(map.ed.cursor(), 5);

        simulate_keys!(map, [Key::Left, Key::Left, Key::Right]);

        assert_eq!(map.ed.cursor(), 4);
    }
}
<commit_msg>Add Alt-f/Alt-b emacs keybindings to move one word forwards/backwards<commit_after>use std::io::{self, Write};
use termion::event::Key;

use KeyMap;
use Editor;

pub struct Emacs<'a, W: Write> {
    ed: Editor<'a, W>,
}

impl<'a, W: Write> Emacs<'a, W> {
    pub fn new(ed: Editor<'a, W>) -> Self {
        Emacs { ed: ed }
    }

    fn handle_ctrl_key(&mut self, c: char) -> io::Result<()> {
        match c {
            'l' => self.ed.clear(),
            'a' => self.ed.move_cursor_to_start_of_line(),
            'e' => self.ed.move_cursor_to_end_of_line(),
            'b' => self.ed.move_cursor_left(1),
            'f' => self.ed.move_cursor_right(1),
            'd' => self.ed.delete_after_cursor(),
            'p' => self.ed.move_up(),
            'n' => self.ed.move_down(),
            'u' => self.ed.delete_all_before_cursor(),
            'k' => self.ed.delete_all_after_cursor(),
            'w' => self.ed.delete_word_before_cursor(true),
            'x' => {
                try!(self.ed.undo());
                Ok(())
            }
            _ => Ok(()),
        }
    }

    fn handle_alt_key(&mut self, c: char) -> io::Result<()> {
        match c {
            '<' => self.ed.move_to_start_of_history(),
            '>' => self.ed.move_to_end_of_history(),
            '\x7F' => self.ed.delete_word_before_cursor(true),
            'f' => emacs_move_word(&mut self.ed, EmacsMoveDir::Right),
            'b' => emacs_move_word(&mut self.ed, EmacsMoveDir::Left),
            'r' => {
                try!(self.ed.revert());
                Ok(())
            }
            _ => Ok(()),
        }
    }
}

impl<'a, W: Write> KeyMap<'a, W, Emacs<'a, W>> for Emacs<'a, W> {
    fn handle_key_core(&mut self, key: Key) -> io::Result<()> {
        match key {
            Key::Char(c) => self.ed.insert_after_cursor(c),
            Key::Alt(c) => self.handle_alt_key(c),
            Key::Ctrl(c) => self.handle_ctrl_key(c),
            Key::Left => self.ed.move_cursor_left(1),
            Key::Right => self.ed.move_cursor_right(1),
            Key::Up => self.ed.move_up(),
            Key::Down => self.ed.move_down(),
            Key::Home => self.ed.move_cursor_to_start_of_line(),
            Key::End => self.ed.move_cursor_to_end_of_line(),
            Key::Backspace => self.ed.delete_before_cursor(),
            Key::Delete => self.ed.delete_after_cursor(),
            Key::Null => Ok(()),
            _ => Ok(()),
        }
    }

    fn editor_mut(&mut self) ->  &mut Editor<'a, W> {
        &mut self.ed
    }

    fn editor(&self) ->  &Editor<'a, W> {
        &self.ed
    }
}

impl<'a, W: Write> From<Emacs<'a, W>> for String {
    fn from(emacs: Emacs<'a, W>) -> String {
        emacs.ed.into()
    }
}

#[derive(PartialEq, Clone, Copy)]
enum EmacsMoveDir {
    Left,
    Right,
}

impl EmacsMoveDir {
    fn advance(&self, cursor: &mut usize, max: usize) -> bool {
        if *self == EmacsMoveDir::Right && *cursor == max {
            return false;
        }

        if *self == EmacsMoveDir::Left && *cursor == 0 {
            return false;
        }

        match *self {
            EmacsMoveDir::Right => *cursor += 1,
            EmacsMoveDir::Left => *cursor -= 1,
        }

        true
    }
}

fn emacs_move_word<W: Write>(ed: &mut Editor<W>, direction: EmacsMoveDir) -> io::Result<()> {
    enum State {
        Word,
        NonWord,
    }

    let mut cursor = ed.cursor();

    {
        let buf = ed.current_buffer();

        let next_char = |cursor| {
            match direction {
                EmacsMoveDir::Right => buf.char_after(cursor),
                EmacsMoveDir::Left => buf.char_before(cursor),
            }
        };

        let mut state = match next_char(cursor) {
            None => return Ok(()),
            Some(c) => {
                match c {
                    c if is_emacs_word(c) => State::Word,
                    _ => State::NonWord,
                }
            },
        };

        // Skip non-words until a word is found, then stop at the character after the word
        while direction.advance(&mut cursor, buf.num_chars()) {
            let c = match next_char(cursor) {
                Some(c) => c,
                _ => break,
            };

            match state {
                State::NonWord => match c {
                    c if is_emacs_word(c) => state = State::Word,
                    _ => {},
                },
                State::Word => match c {
                    c if !is_emacs_word(c) => break,
                    _ => {},
                },
            }
        }
    }

    ed.move_cursor_to(cursor)
}

fn is_emacs_word(c: char) -> bool {
    c.is_alphanumeric()
}

#[cfg(test)]
mod tests {
    use super::*;
    use termion::event::Key;
    use Context;
    use Editor;
    use KeyMap;
    use std::io::Write;

    macro_rules! simulate_keys {
        ($keymap:ident, $keys:expr) => {{
            simulate_keys(&mut $keymap, $keys.into_iter())
        }}
    }

    fn simulate_keys<'a, 'b, W: Write, T, M: KeyMap<'a, W, T>, I>(keymap: &mut M, keys: I) -> bool
        where I: Iterator<Item = &'b Key>
    {
        for k in keys {
            if keymap.handle_key(*k, &mut |_| {}).unwrap() {
                return true;
            }
        }

        false
    }

    #[test]
    fn enter_is_done() {
        let mut context = Context::new();
        let out = Vec::new();
        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
        let mut map = Emacs::new(ed);
        map.ed.insert_str_after_cursor("done").unwrap();
        assert_eq!(map.ed.cursor(), 4);

        assert!(simulate_keys!(map, [Key::Char('\n')]));

        assert_eq!(map.ed.cursor(), 4);
        assert_eq!(String::from(map), "done");
    }

    #[test]
    fn move_cursor_left() {
        let mut context = Context::new();
        let out = Vec::new();
        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
        let mut map = Emacs::new(ed);
        map.editor_mut().insert_str_after_cursor("let").unwrap();
        assert_eq!(map.ed.cursor(), 3);

        simulate_keys!(map, [Key::Left, Key::Char('f')]);

        assert_eq!(map.ed.cursor(), 3);
        assert_eq!(String::from(map), "left");
    }

    #[test]
    fn move_word() {
        let mut context = Context::new();
        let out = Vec::new();
        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
        let mut map = Emacs::new(ed);
        map.editor_mut().insert_str_after_cursor("abc def ghi").unwrap();
        assert_eq!(map.ed.cursor(), 11);

        simulate_keys!(map, [Key::Alt('b')]);

        // Move to `g`
        assert_eq!(map.ed.cursor(), 8);

        simulate_keys!(map, [Key::Alt('b'), Key::Alt('f')]);

        // Move to the char after `f`
        assert_eq!(map.ed.cursor(), 7);
    }

    #[test]
    fn cursor_movement() {
        let mut context = Context::new();
        let out = Vec::new();
        let ed = Editor::new(out, "prompt".to_owned(), &mut context).unwrap();
        let mut map = Emacs::new(ed);
        map.ed.insert_str_after_cursor("right").unwrap();
        assert_eq!(map.ed.cursor(), 5);

        simulate_keys!(map, [Key::Left, Key::Left, Key::Right]);

        assert_eq!(map.ed.cursor(), 4);
    }
}
<|endoftext|>


<commit_before>pub type Value = i32;
pub type ForthResult = Result<(), Error>;

pub struct Forth;

#[derive(Debug, PartialEq)]
pub enum Error {
    DivisionByZero,
    StackUnderflow,
    UnknownWord,
    InvalidWord,
}

impl Forth {
    pub fn new() -> Forth {
        unimplemented!()
    }

    pub fn stack(&self) -> Vec<Value> {
        unimplemented!()
    }

    pub fn eval(&mut self, input: &str) -> ForthResult {
        unimplemented!()
    }
}
<commit_msg>forth: eliminate stub warnings<commit_after>pub type Value = i32;
pub type ForthResult = Result<(), Error>;

pub struct Forth;

#[derive(Debug, PartialEq)]
pub enum Error {
    DivisionByZero,
    StackUnderflow,
    UnknownWord,
    InvalidWord,
}

impl Forth {
    pub fn new() -> Forth {
        unimplemented!()
    }

    pub fn stack(&self) -> Vec<Value> {
        unimplemented!()
    }

    pub fn eval(&mut self, input: &str) -> ForthResult {
        unimplemented!("result of evaluating '{}'", input)
    }
}
<|endoftext|>