<commit_before>extern crate regex;
extern crate clap;
extern crate walkdir;
extern crate ansi_term;

use std::io::Write;

macro_rules! println_stderr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

use clap::{Arg, App, AppSettings};
use regex::Regex;
use walkdir::WalkDir;
use ansi_term::Colour::Blue;

use std::env;
use std::path::PathBuf;

fn find(rgx: Regex, dirs: Vec<PathBuf>, paint: bool) {
    let painter;
    let replacement = if paint {
        painter = Blue.paint("$search");
        format!("{}", painter)
    } else {
        "$search".to_string()
    };

    for d in dirs.iter() {
        let wkd = WalkDir::new(d);

        for f in wkd.into_iter() {
            let entry;
            match f {
                Ok(e) => entry = e,
                Err(err) => {
                    println_stderr!("{}", err);
                    continue;
                }
            }

            // paths are ascii so should always be valid unicode
            // the edge case is super rare so just ignore it
            let s = &entry.path().to_string_lossy();

            if rgx.is_match(s) {
                let display = rgx.replace_all(s, replacement.as_str());
                println!("{}", display);
            }
        }
    }
}

fn main() {
    let matches = App::new("fnd, a simpler way to find files")
        .version("0.2.0")
        .author("Mathew Robinson <mrobinson@praelatus.io>")
        .about("Finds files")
        .setting(AppSettings::TrailingVarArg)
        .arg(Arg::with_name("color")
             .long("no_color")
             .short("nc")
             .help("When specified will not highlight matches with ansi \
                    term color codes this is useful when piping output"))
        .arg(Arg::with_name("REGEX")
             .required(true)
             .index(1)
             .help("The REGEX to search for, defaults to fuzzy finding"))
        .arg(Arg::with_name("DIRS")
            .multiple(true)
            .help("Where to search for SEARCH")
            .default_value("."))
        .get_matches();

    let search = matches.value_of("REGEX").unwrap();
    let dirs: Vec<&str> = matches.values_of("DIRS").unwrap().collect();

    let mut d: Vec<PathBuf> = dirs.iter()
        .map(|x| {
            if *x == "." {
                return env::current_dir().unwrap().to_path_buf();
            }

            PathBuf::from(x)
        })
        .collect();

    d = d.iter()
        .map(|x| std::fs::canonicalize(x).unwrap())
        .collect();

    let mut re = "(?P<search>".to_string();
    re.push_str(search);
    re.push_str(")");

    let rgx = Regex::new(&re).unwrap();

    find(rgx, d, !matches.is_present("color"));
}
<commit_msg>remove dead code<commit_after>extern crate regex;
extern crate clap;
extern crate walkdir;
extern crate ansi_term;

use std::io::Write;

macro_rules! println_stderr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

use clap::{Arg, App, AppSettings};
use regex::Regex;
use walkdir::WalkDir;
use ansi_term::Colour::Blue;

use std::env;
use std::path::PathBuf;

fn find(rgx: Regex, dirs: Vec<PathBuf>, paint: bool) {
    let painter;
    let replacement = if paint {
        painter = Blue.paint("$search");
        format!("{}", painter)
    } else {
        "$search".to_string()
    };

    for d in dirs.iter() {
        let wkd = WalkDir::new(d);

        for f in wkd.into_iter() {
            let entry;
            match f {
                Ok(e) => entry = e,
                Err(err) => {
                    println_stderr!("{}", err);
                    continue;
                }
            }

            // paths are ascii so should always be valid unicode
            // the edge case is super rare so just ignore it
            let s = &entry.path().to_string_lossy();

            if rgx.is_match(s) {
                let display = rgx.replace_all(s, replacement.as_str());
                println!("{}", display);
            }
        }
    }
}

fn main() {
    let matches = App::new("fnd, a simpler way to find files")
        .version("0.2.0")
        .author("Mathew Robinson <mrobinson@praelatus.io>")
        .about("Finds files")
        .setting(AppSettings::TrailingVarArg)
        .arg(Arg::with_name("color")
             .long("no_color")
             .short("nc")
             .help("When specified will not highlight matches with ansi \
                    term color codes this is useful when piping output"))
        .arg(Arg::with_name("REGEX")
             .required(true)
             .index(1)
             .help("The REGEX to search for, defaults to fuzzy finding"))
        .arg(Arg::with_name("DIRS")
            .multiple(true)
            .help("Where to search for SEARCH")
            .default_value("."))
        .get_matches();

    let search = matches.value_of("REGEX").unwrap();
    let dirs: Vec<&str> = matches.values_of("DIRS").unwrap().collect();

    let d: Vec<PathBuf> = dirs.iter()
        .map(|x| {
            if *x == "." {
                return env::current_dir().unwrap().to_path_buf();
            }

            PathBuf::from(x)
        })
        .collect();

    let re = format!("(?P<search>{})", search);
    let rgx = Regex::new(&re).unwrap();

    find(rgx, d, !matches.is_present("color"));
}
<|endoftext|>


<commit_before>extern crate hyper;
extern crate serde;
extern crate serde_json;
extern crate term;
extern crate rand;

use hyper::Client;
use hyper::client::Response;
use std::io::{BufReader, BufRead};
use std::sync::mpsc::*;
use std::thread;

include!(concat!(env!("OUT_DIR"), "/main.rs"));

#[derive(Debug)]
struct Record {
    namespace: String,
    pod: String,
    container: String,
    color: term::color::Color,
    text: String,
}

fn main() {
    let colors = vec![term::color::CYAN,
                      term::color::MAGENTA,
                      term::color::GREEN,
                      term::color::YELLOW,
                      term::color::BRIGHT_BLUE];
    let client = Client::new();
    let response = client.get("http://127.0.0.1:8001/api/v1/pods")
        .send()
        .unwrap();
    let pods = serde_json::from_reader::<Response, PodList>(response).unwrap();
    let (tx, rx) = channel();
    let mut t = term::stdout().unwrap();
    thread::spawn(move || {
        loop {
            if let Ok(Record { namespace, pod, container, color, text }) = rx.recv() {
                t.reset().unwrap();
                t.fg(color).unwrap();
                write!(t, "{}/{}/{}: ", namespace, pod, container).unwrap();
                t.fg(term::color::RED).unwrap();
                t.reset().unwrap();
                writeln!(t, ": {}", text);
                t.reset().unwrap();
            }
        }
    });
    let mut rng = rand::thread_rng();
    for pod in pods.items {
        let containers = pod.spec.containers.iter().map(|c| c.name.clone()).collect::<Vec<_>>();
        let reader = BufReader::new(client.get(&format!("http://127.0.0.1:\
                           8001/api/v1/namespaces/{}/pods/{}/log?container={}&follow=true",
                          pod.metadata.namespace,
                          pod.metadata.name,
                          containers[0]))
            .send()
            .unwrap());
        let px = tx.clone();
        let color = rand::sample(&mut rng, colors.clone(), 1)[0];
        thread::spawn(move || {
            for l in reader.lines() {
                if let Ok(text) = l {
                    px.send(Record {
                            namespace: pod.metadata.namespace.clone(),
                            pod: pod.metadata.name.clone(),
                            container: containers[0].clone(),
                            color: color,
                            text: text,
                        })
                        .unwrap()
                }
            }
        });
    }
}
<commit_msg>remove extra color<commit_after>extern crate hyper;
extern crate serde;
extern crate serde_json;
extern crate term;
extern crate rand;

use hyper::Client;
use hyper::client::Response;
use std::io::{BufReader, BufRead};
use std::sync::mpsc::*;
use std::thread;

include!(concat!(env!("OUT_DIR"), "/main.rs"));

#[derive(Debug)]
struct Record {
    namespace: String,
    pod: String,
    container: String,
    color: term::color::Color,
    text: String,
}

fn main() {
    let colors = vec![term::color::CYAN,
                      term::color::MAGENTA,
                      term::color::GREEN,
                      term::color::YELLOW,
                      term::color::BRIGHT_BLUE];
    let client = Client::new();
    let response = client.get("http://127.0.0.1:8001/api/v1/pods")
        .send()
        .unwrap();
    let pods = serde_json::from_reader::<Response, PodList>(response).unwrap();
    let (tx, rx) = channel();
    let mut t = term::stdout().unwrap();
    thread::spawn(move || {
        loop {
            if let Ok(Record { namespace, pod, container, color, text }) = rx.recv() {
                t.reset().unwrap();
                t.fg(color).unwrap();
                write!(t, "{}/{}/{}: ", namespace, pod, container).unwrap();
                t.reset().unwrap();
                writeln!(t, ": {}", text);
            }
        }
    });
    let mut rng = rand::thread_rng();
    for pod in pods.items {
        let containers = pod.spec.containers.iter().map(|c| c.name.clone()).collect::<Vec<_>>();
        let reader = BufReader::new(client.get(&format!("http://127.0.0.1:\
                           8001/api/v1/namespaces/{}/pods/{}/log?container={}&follow=true",
                          pod.metadata.namespace,
                          pod.metadata.name,
                          containers[0]))
            .send()
            .unwrap());
        let px = tx.clone();
        let color = rand::sample(&mut rng, colors.clone(), 1)[0];
        thread::spawn(move || {
            for l in reader.lines() {
                if let Ok(text) = l {
                    px.send(Record {
                            namespace: pod.metadata.namespace.clone(),
                            pod: pod.metadata.name.clone(),
                            container: containers[0].clone(),
                            color: color,
                            text: text,
                        })
                        .unwrap()
                }
            }
        });
    }
}
<|endoftext|>


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

// Import crates with necessary types into a new project.

extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

// Import necessary types from crates.

use exonum::blockchain::{Blockchain, Service, GenesisConfig, ValidatorKeys, Transaction,
                         ApiContext};
use exonum::node::{Node, NodeConfig, NodeApiConfig, TransactionSend, ApiSender};
use exonum::messages::{RawTransaction, FromRaw, Message};
use exonum::storage::{Fork, MemoryDB, MapIndex};
use exonum::crypto::{PublicKey, Hash, HexValue};
use exonum::encoding;
use exonum::api::{Api, ApiError};
use iron::prelude::*;
use iron::Handler;
use router::Router;

// // // // // // // // // // CONSTANTS // // // // // // // // // //

// Define service ID for the service trait.

const SERVICE_ID: u16 = 1;

// Define constants for transaction types within the service.

const TX_CREATE_WALLET_ID: u16 = 1;

const TX_TRANSFER_ID: u16 = 2;

// Define initial balance of a newly created wallet.

const INIT_BALANCE: u64 = 100;

// // // // // // // // // // PERSISTENT DATA // // // // // // // // // //

// Declare the data to be stored in the blockchain. In the present case,
// declare a type for storing information about the wallet and its balance.

/// Declare a [serializable][1]
/// [1]: https://github.com/exonum/exonum-doc/blob/master/src/architecture/serialization.md
/// struct and determine bounds of its fields with `encoding_struct!` macro.
encoding_struct! {
    struct Wallet {
        const SIZE = 48;

        field pub_key:            &PublicKey  [00 => 32]
        field name:               &str        [32 => 40]
        field balance:            u64         [40 => 48]
    }
}

/// Add methods to the `Wallet` type for changing balance.
impl Wallet {
    pub fn increase(self, amount: u64) -> Self {
        let balance = self.balance() + amount;
        Self::new(self.pub_key(), self.name(), balance)
    }

    pub fn decrease(self, amount: u64) -> Self {
        let balance = self.balance() - amount;
        Self::new(self.pub_key(), self.name(), balance)
    }
}

// // // // // // // // // // DATA LAYOUT // // // // // // // // // //

/// Create schema of the key-value storage implemented by `MemoryDB`. In the
/// present case a `Fork` of the database is used.
pub struct CurrencySchema<'a> {
    view: &'a mut Fork,
}

/// Declare layout of the data. Use an instance of [`MapIndex`][2]
/// [2]: https://github.com/exonum/exonum-doc/blob/master/src/architecture/storage.md#mapindex
/// to keep wallets in storage. Index values are serialized `Wallet` structs.
///
/// Isolate the wallets map into a separate entity by adding a unique prefix,
/// i.e. the first argument to the `MapIndex::new` call.
impl<'a> CurrencySchema<'a> {
    pub fn wallets(&mut self) -> MapIndex<&mut Fork, PublicKey, Wallet> {
        MapIndex::new("cryptocurrency.wallets", self.view)
    }

    /// Get a separate wallet from the storage.
    pub fn wallet(&mut self, pub_key: &PublicKey) -> Option<Wallet> {
        self.wallets().get(pub_key)
    }
}

// // // // // // // // // // TRANSACTIONS // // // // // // // // // //

/// Create a new wallet.
message! {
    struct TxCreateWallet {
        const TYPE = SERVICE_ID;
        const ID = TX_CREATE_WALLET_ID;
        const SIZE = 40;

        field pub_key:     &PublicKey  [00 => 32]
        field name:        &str        [32 => 40]
    }
}

/// Transfer coins between the wallets.
message! {
    struct TxTransfer {
        const TYPE = SERVICE_ID;
        const ID = TX_TRANSFER_ID;
        const SIZE = 80;

        field from:        &PublicKey  [00 => 32]
        field to:          &PublicKey  [32 => 64]
        field amount:      u64         [64 => 72]
        field seed:        u64         [72 => 80]
    }
}

// // // // // // // // // // CONTRACTS // // // // // // // // // //

/// Execute a transaction.
impl Transaction for TxCreateWallet {
    /// Verify integrity of the transaction by checking the transaction
    /// signature.
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    /// Apply logic to the storage when executing the transaction.
    fn execute(&self, view: &mut Fork) {
        let mut schema = CurrencySchema { view };
        if schema.wallet(self.pub_key()).is_none() {
            let wallet = Wallet::new(self.pub_key(), self.name(), INIT_BALANCE);
            println!("Create the wallet: {:?}", wallet);
            schema.wallets().put(self.pub_key(), wallet)
        }
    }

    /// Provide information about the transaction to be used in the blockchain explorer.
    fn info(&self) -> serde_json::Value {
        serde_json::to_value(&self).expect("Cannot serialize transaction to JSON")
    }
}

impl Transaction for TxTransfer {
    /// Check if the sender is not the receiver. Check correctness of the
    /// sender's signature.
    fn verify(&self) -> bool {
        (*self.from() != *self.to()) && self.verify_signature(self.from())
    }

    /// Retrieve two wallets to apply the transfer. Check the sender's
    /// balance and apply changes to the balances of the wallets.
    fn execute(&self, view: &mut Fork) {
        let mut schema = CurrencySchema { view };
        let sender = schema.wallet(self.from());
        let receiver = schema.wallet(self.to());
        if let (Some(sender), Some(receiver)) = (sender, receiver) {
            let amount = self.amount();
            if sender.balance() >= amount {
                let sender = sender.decrease(amount);
                let receiver = receiver.increase(amount);
                println!("Transfer between wallets: {:?} => {:?}", sender, receiver);
                let mut wallets = schema.wallets();
                wallets.put(self.from(), sender);
                wallets.put(self.to(), receiver);
            }
        }
    }

    /// Provide information about the transaction to be used in the blockchain explorer.
    fn info(&self) -> serde_json::Value {
        serde_json::to_value(&self).expect("Cannot serialize transaction to JSON")
    }
}

// // // // // // // // // // REST API // // // // // // // // // //

/// Implement the node API.
#[derive(Clone)]
struct CryptocurrencyApi {
    channel: ApiSender,
    blockchain: Blockchain,
}

/// Shortcut to get data on wallets.
impl CryptocurrencyApi {
    fn get_wallet(&self, pub_key: &PublicKey) -> Option<Wallet> {
        let mut view = self.blockchain.fork();
        let mut schema = CurrencySchema { view: &mut view };
        schema.wallet(pub_key)
    }

    fn get_wallets(&self) -> Option<Vec<Wallet>> {
        let mut view = self.blockchain.fork();
        let mut schema = CurrencySchema { view: &mut view };
        let idx = schema.wallets();
        let wallets: Vec<Wallet> = idx.values().collect();
        if wallets.is_empty() {
            None
        } else {
            Some(wallets)
        }
    }
}

/// Add an enum which joins transactions of both types to simplify request
/// processing.
#[serde(untagged)]
#[derive(Clone, Serialize, Deserialize)]
enum TransactionRequest {
    CreateWallet(TxCreateWallet),
    Transfer(TxTransfer),
}

/// Implement a trait for the enum for deserialized `TransactionRequest`s
/// to fit into the node channel.
impl Into<Box<Transaction>> for TransactionRequest {
    fn into(self) -> Box<Transaction> {
        match self {
            TransactionRequest::CreateWallet(trans) => Box::new(trans),
            TransactionRequest::Transfer(trans) => Box::new(trans),
        }
    }
}

/// The structure returned by the REST API.
#[derive(Serialize, Deserialize)]
struct TransactionResponse {
    tx_hash: Hash,
}

/// Implement the `Api` trait.
/// `Api` facilitates conversion between transactions/read requests and REST
/// endpoints; for example, it parses `POSTed` JSON into the binary transaction
/// representation used in Exonum internally.
impl Api for CryptocurrencyApi {
    fn wire(&self, router: &mut Router) {
        let self_ = self.clone();
        let transaction = move |req: &mut Request| -> IronResult<Response> {
            match req.get::<bodyparser::Struct<TransactionRequest>>() {
                Ok(Some(transaction)) => {
                    let transaction: Box<Transaction> = transaction.into();
                    let tx_hash = transaction.hash();
                    self_.channel.send(transaction).map_err(ApiError::from)?;
                    let json = TransactionResponse { tx_hash };
                    self_.ok_response(&serde_json::to_value(&json).unwrap())
                }
                Ok(None) => Err(ApiError::IncorrectRequest("Empty request body".into()))?,
                Err(e) => Err(ApiError::IncorrectRequest(Box::new(e)))?,
            }
        };

        // Gets status of all wallets.
        let self_ = self.clone();
        let wallets_info = move |_: &mut Request| -> IronResult<Response> {
            if let Some(wallets) = self_.get_wallets() {
                self_.ok_response(&serde_json::to_value(wallets).unwrap())
            } else {
                self_.not_found_response(
                    &serde_json::to_value("Wallets database is empty")
                        .unwrap(),
                )
            }
        };

        // Gets status of the wallet corresponding to the public key.
        let self_ = self.clone();
        let wallet_info = move |req: &mut Request| -> IronResult<Response> {
            let path = req.url.path();
            let wallet_key = path.last().unwrap();
            let public_key = PublicKey::from_hex(wallet_key).map_err(ApiError::FromHex)?;
            if let Some(wallet) = self_.get_wallet(&public_key) {
                self_.ok_response(&serde_json::to_value(wallet).unwrap())
            } else {
                self_.not_found_response(&serde_json::to_value("Wallet not found").unwrap())
            }
        };

        // Bind the transaction handler to a specific route.
        router.post("/v1/wallets/transaction", transaction, "transaction");
        router.get("/v1/wallets", wallets_info, "wallets_info");
        router.get("/v1/wallet/:pub_key", wallet_info, "wallet_info");
    }
}

// // // // // // // // // // SERVICE DECLARATION // // // // // // // // // //

/// Define the service.
struct CurrencyService;

/// Implement a `Service` trait for the service.
impl Service for CurrencyService {
    fn service_name(&self) -> &'static str {
        "cryptocurrency"
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    /// Implement a method to deserialize transactions coming to the node.
    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        let trans: Box<Transaction> = match raw.message_type() {
            TX_TRANSFER_ID => Box::new(TxTransfer::from_raw(raw)?),
            TX_CREATE_WALLET_ID => Box::new(TxCreateWallet::from_raw(raw)?),
            _ => {
                return Err(encoding::Error::IncorrectMessageType {
                    message_type: raw.message_type(),
                });
            }
        };
        Ok(trans)
    }

    /// Create a REST `Handler` to process web requests to the node.
    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = CryptocurrencyApi {
            channel: ctx.node_channel().clone(),
            blockchain: ctx.blockchain().clone(),
        };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

// // // // // // // // // // ENTRY POINT // // // // // // // // // //

fn main() {
    exonum::helpers::init_logger().unwrap();

    println!("Creating in-memory database...");
    let db = MemoryDB::new();
    let services: Vec<Box<Service>> = vec![Box::new(CurrencyService)];
    let blockchain = Blockchain::new(Box::new(db), services);

    let (consensus_public_key, consensus_secret_key) = exonum::crypto::gen_keypair();
    let (service_public_key, service_secret_key) = exonum::crypto::gen_keypair();

    let validator_keys = ValidatorKeys {
        consensus_key: consensus_public_key,
        service_key: service_public_key,
    };
    let genesis = GenesisConfig::new(vec![validator_keys].into_iter());

    let api_address = "0.0.0.0:8000".parse().unwrap();
    let api_cfg = NodeApiConfig {
        public_api_address: Some(api_address),
        ..Default::default()
    };

    let peer_address = "0.0.0.0:2000".parse().unwrap();

    let node_cfg = NodeConfig {
        listen_address: peer_address,
        peers: vec![],
        service_public_key,
        service_secret_key,
        consensus_public_key,
        consensus_secret_key,
        genesis,
        external_address: None,
        network: Default::default(),
        whitelist: Default::default(),
        api: api_cfg,
        mempool: Default::default(),
        services_configs: Default::default(),
    };

    println!("Starting a single node...");
    let node = Node::new(blockchain, node_cfg);

    println!("Blockchain is ready for transactions!");
    node.run().unwrap();
}
<commit_msg>Fix links in doc comments<commit_after>// Copyright 2017 The Exonum Team
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Import crates with necessary types into a new project.

extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

// Import necessary types from crates.

use exonum::blockchain::{Blockchain, Service, GenesisConfig, ValidatorKeys, Transaction,
                         ApiContext};
use exonum::node::{Node, NodeConfig, NodeApiConfig, TransactionSend, ApiSender};
use exonum::messages::{RawTransaction, FromRaw, Message};
use exonum::storage::{Fork, MemoryDB, MapIndex};
use exonum::crypto::{PublicKey, Hash, HexValue};
use exonum::encoding;
use exonum::api::{Api, ApiError};
use iron::prelude::*;
use iron::Handler;
use router::Router;

// // // // // // // // // // CONSTANTS // // // // // // // // // //

// Define service ID for the service trait.

const SERVICE_ID: u16 = 1;

// Define constants for transaction types within the service.

const TX_CREATE_WALLET_ID: u16 = 1;

const TX_TRANSFER_ID: u16 = 2;

// Define initial balance of a newly created wallet.

const INIT_BALANCE: u64 = 100;

// // // // // // // // // // PERSISTENT DATA // // // // // // // // // //

// Declare the data to be stored in the blockchain. In the present case,
// declare a type for storing information about the wallet and its balance.

/// Declare a [serializable][1] struct and determine bounds of its fields
/// with `encoding_struct!` macro.
///
/// [1]: https://exonum.com/doc/architecture/serialization
encoding_struct! {
    struct Wallet {
        const SIZE = 48;

        field pub_key:            &PublicKey  [00 => 32]
        field name:               &str        [32 => 40]
        field balance:            u64         [40 => 48]
    }
}

/// Add methods to the `Wallet` type for changing balance.
impl Wallet {
    pub fn increase(self, amount: u64) -> Self {
        let balance = self.balance() + amount;
        Self::new(self.pub_key(), self.name(), balance)
    }

    pub fn decrease(self, amount: u64) -> Self {
        let balance = self.balance() - amount;
        Self::new(self.pub_key(), self.name(), balance)
    }
}

// // // // // // // // // // DATA LAYOUT // // // // // // // // // //

/// Create schema of the key-value storage implemented by `MemoryDB`. In the
/// present case a `Fork` of the database is used.
pub struct CurrencySchema<'a> {
    view: &'a mut Fork,
}

/// Declare layout of the data. Use an instance of [`MapIndex`]
/// to keep wallets in storage. Index values are serialized `Wallet` structs.
///
/// Isolate the wallets map into a separate entity by adding a unique prefix,
/// i.e. the first argument to the `MapIndex::new` call.
///
/// [`MapIndex`]: https://exonum.com/doc/architecture/storage#mapindex
impl<'a> CurrencySchema<'a> {
    pub fn wallets(&mut self) -> MapIndex<&mut Fork, PublicKey, Wallet> {
        MapIndex::new("cryptocurrency.wallets", self.view)
    }

    /// Get a separate wallet from the storage.
    pub fn wallet(&mut self, pub_key: &PublicKey) -> Option<Wallet> {
        self.wallets().get(pub_key)
    }
}

// // // // // // // // // // TRANSACTIONS // // // // // // // // // //

/// Create a new wallet.
message! {
    struct TxCreateWallet {
        const TYPE = SERVICE_ID;
        const ID = TX_CREATE_WALLET_ID;
        const SIZE = 40;

        field pub_key:     &PublicKey  [00 => 32]
        field name:        &str        [32 => 40]
    }
}

/// Transfer coins between the wallets.
message! {
    struct TxTransfer {
        const TYPE = SERVICE_ID;
        const ID = TX_TRANSFER_ID;
        const SIZE = 80;

        field from:        &PublicKey  [00 => 32]
        field to:          &PublicKey  [32 => 64]
        field amount:      u64         [64 => 72]
        field seed:        u64         [72 => 80]
    }
}

// // // // // // // // // // CONTRACTS // // // // // // // // // //

/// Execute a transaction.
impl Transaction for TxCreateWallet {
    /// Verify integrity of the transaction by checking the transaction
    /// signature.
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    /// Apply logic to the storage when executing the transaction.
    fn execute(&self, view: &mut Fork) {
        let mut schema = CurrencySchema { view };
        if schema.wallet(self.pub_key()).is_none() {
            let wallet = Wallet::new(self.pub_key(), self.name(), INIT_BALANCE);
            println!("Create the wallet: {:?}", wallet);
            schema.wallets().put(self.pub_key(), wallet)
        }
    }

    /// Provide information about the transaction to be used in the blockchain explorer.
    fn info(&self) -> serde_json::Value {
        serde_json::to_value(&self).expect("Cannot serialize transaction to JSON")
    }
}

impl Transaction for TxTransfer {
    /// Check if the sender is not the receiver. Check correctness of the
    /// sender's signature.
    fn verify(&self) -> bool {
        (*self.from() != *self.to()) && self.verify_signature(self.from())
    }

    /// Retrieve two wallets to apply the transfer. Check the sender's
    /// balance and apply changes to the balances of the wallets.
    fn execute(&self, view: &mut Fork) {
        let mut schema = CurrencySchema { view };
        let sender = schema.wallet(self.from());
        let receiver = schema.wallet(self.to());
        if let (Some(sender), Some(receiver)) = (sender, receiver) {
            let amount = self.amount();
            if sender.balance() >= amount {
                let sender = sender.decrease(amount);
                let receiver = receiver.increase(amount);
                println!("Transfer between wallets: {:?} => {:?}", sender, receiver);
                let mut wallets = schema.wallets();
                wallets.put(self.from(), sender);
                wallets.put(self.to(), receiver);
            }
        }
    }

    /// Provide information about the transaction to be used in the blockchain explorer.
    fn info(&self) -> serde_json::Value {
        serde_json::to_value(&self).expect("Cannot serialize transaction to JSON")
    }
}

// // // // // // // // // // REST API // // // // // // // // // //

/// Implement the node API.
#[derive(Clone)]
struct CryptocurrencyApi {
    channel: ApiSender,
    blockchain: Blockchain,
}

/// Shortcut to get data on wallets.
impl CryptocurrencyApi {
    fn get_wallet(&self, pub_key: &PublicKey) -> Option<Wallet> {
        let mut view = self.blockchain.fork();
        let mut schema = CurrencySchema { view: &mut view };
        schema.wallet(pub_key)
    }

    fn get_wallets(&self) -> Option<Vec<Wallet>> {
        let mut view = self.blockchain.fork();
        let mut schema = CurrencySchema { view: &mut view };
        let idx = schema.wallets();
        let wallets: Vec<Wallet> = idx.values().collect();
        if wallets.is_empty() {
            None
        } else {
            Some(wallets)
        }
    }
}

/// Add an enum which joins transactions of both types to simplify request
/// processing.
#[serde(untagged)]
#[derive(Clone, Serialize, Deserialize)]
enum TransactionRequest {
    CreateWallet(TxCreateWallet),
    Transfer(TxTransfer),
}

/// Implement a trait for the enum for deserialized `TransactionRequest`s
/// to fit into the node channel.
impl Into<Box<Transaction>> for TransactionRequest {
    fn into(self) -> Box<Transaction> {
        match self {
            TransactionRequest::CreateWallet(trans) => Box::new(trans),
            TransactionRequest::Transfer(trans) => Box::new(trans),
        }
    }
}

/// The structure returned by the REST API.
#[derive(Serialize, Deserialize)]
struct TransactionResponse {
    tx_hash: Hash,
}

/// Implement the `Api` trait.
/// `Api` facilitates conversion between transactions/read requests and REST
/// endpoints; for example, it parses `POSTed` JSON into the binary transaction
/// representation used in Exonum internally.
impl Api for CryptocurrencyApi {
    fn wire(&self, router: &mut Router) {
        let self_ = self.clone();
        let transaction = move |req: &mut Request| -> IronResult<Response> {
            match req.get::<bodyparser::Struct<TransactionRequest>>() {
                Ok(Some(transaction)) => {
                    let transaction: Box<Transaction> = transaction.into();
                    let tx_hash = transaction.hash();
                    self_.channel.send(transaction).map_err(ApiError::from)?;
                    let json = TransactionResponse { tx_hash };
                    self_.ok_response(&serde_json::to_value(&json).unwrap())
                }
                Ok(None) => Err(ApiError::IncorrectRequest("Empty request body".into()))?,
                Err(e) => Err(ApiError::IncorrectRequest(Box::new(e)))?,
            }
        };

        // Gets status of all wallets.
        let self_ = self.clone();
        let wallets_info = move |_: &mut Request| -> IronResult<Response> {
            if let Some(wallets) = self_.get_wallets() {
                self_.ok_response(&serde_json::to_value(wallets).unwrap())
            } else {
                self_.not_found_response(
                    &serde_json::to_value("Wallets database is empty")
                        .unwrap(),
                )
            }
        };

        // Gets status of the wallet corresponding to the public key.
        let self_ = self.clone();
        let wallet_info = move |req: &mut Request| -> IronResult<Response> {
            let path = req.url.path();
            let wallet_key = path.last().unwrap();
            let public_key = PublicKey::from_hex(wallet_key).map_err(ApiError::FromHex)?;
            if let Some(wallet) = self_.get_wallet(&public_key) {
                self_.ok_response(&serde_json::to_value(wallet).unwrap())
            } else {
                self_.not_found_response(&serde_json::to_value("Wallet not found").unwrap())
            }
        };

        // Bind the transaction handler to a specific route.
        router.post("/v1/wallets/transaction", transaction, "transaction");
        router.get("/v1/wallets", wallets_info, "wallets_info");
        router.get("/v1/wallet/:pub_key", wallet_info, "wallet_info");
    }
}

// // // // // // // // // // SERVICE DECLARATION // // // // // // // // // //

/// Define the service.
struct CurrencyService;

/// Implement a `Service` trait for the service.
impl Service for CurrencyService {
    fn service_name(&self) -> &'static str {
        "cryptocurrency"
    }

    fn service_id(&self) -> u16 {
        SERVICE_ID
    }

    /// Implement a method to deserialize transactions coming to the node.
    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        let trans: Box<Transaction> = match raw.message_type() {
            TX_TRANSFER_ID => Box::new(TxTransfer::from_raw(raw)?),
            TX_CREATE_WALLET_ID => Box::new(TxCreateWallet::from_raw(raw)?),
            _ => {
                return Err(encoding::Error::IncorrectMessageType {
                    message_type: raw.message_type(),
                });
            }
        };
        Ok(trans)
    }

    /// Create a REST `Handler` to process web requests to the node.
    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = CryptocurrencyApi {
            channel: ctx.node_channel().clone(),
            blockchain: ctx.blockchain().clone(),
        };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

// // // // // // // // // // ENTRY POINT // // // // // // // // // //

fn main() {
    exonum::helpers::init_logger().unwrap();

    println!("Creating in-memory database...");
    let db = MemoryDB::new();
    let services: Vec<Box<Service>> = vec![Box::new(CurrencyService)];
    let blockchain = Blockchain::new(Box::new(db), services);

    let (consensus_public_key, consensus_secret_key) = exonum::crypto::gen_keypair();
    let (service_public_key, service_secret_key) = exonum::crypto::gen_keypair();

    let validator_keys = ValidatorKeys {
        consensus_key: consensus_public_key,
        service_key: service_public_key,
    };
    let genesis = GenesisConfig::new(vec![validator_keys].into_iter());

    let api_address = "0.0.0.0:8000".parse().unwrap();
    let api_cfg = NodeApiConfig {
        public_api_address: Some(api_address),
        ..Default::default()
    };

    let peer_address = "0.0.0.0:2000".parse().unwrap();

    let node_cfg = NodeConfig {
        listen_address: peer_address,
        peers: vec![],
        service_public_key,
        service_secret_key,
        consensus_public_key,
        consensus_secret_key,
        genesis,
        external_address: None,
        network: Default::default(),
        whitelist: Default::default(),
        api: api_cfg,
        mempool: Default::default(),
        services_configs: Default::default(),
    };

    println!("Starting a single node...");
    let node = Node::new(blockchain, node_cfg);

    println!("Blockchain is ready for transactions!");
    node.run().unwrap();
}
<|endoftext|>


<commit_before>#![feature(io)]

extern crate hyper;
extern crate regex;

// TODO
fn main() {
    let token = authentication::get_oauth_token_or_panic();
    println!("{}", token);
}

mod authentication {
    // Authentication
    use std::old_io::net::ip::Ipv4Addr;
    use hyper::server::{Server, Request, Response};
    use hyper::uri::RequestUri::AbsolutePath;
    use std::old_io::Command;
    // use hyper::status;
    use regex::Regex;
    use std::sync::mpsc::channel;
    use std::sync::Mutex;

    type AuthCode = String;

    pub fn get_oauth_token_or_panic() -> AuthCode {
        Command::new("xdg-open").arg("https://slack.com/oauth/authorize?client_id=2334733471.3592055147").output().unwrap();
        let server = Server::http(Ipv4Addr(127, 0, 0, 1), 9999);

        let (tx, rx) = channel();
        let mtx = Mutex::new(tx);

        let mut _guard = server.listen(move |req: Request, res: Response| {
            match req.uri {
                AbsolutePath(path) => {
                    let authcode = extract_auth_code(&path).unwrap();
                    mtx.lock().unwrap().send(authcode).unwrap();
                },
                _ => ()
            }

            let mut res = res.start().unwrap();
            res.write_all(b"Thanks! Please return to Lax").unwrap();
            res.end().unwrap();
        }).unwrap();

        let authcode = rx.recv().unwrap();
        _guard.close().unwrap();
        authcode
    }

    fn extract_auth_code(path: &str) -> Result<AuthCode, &'static str> {
        let re = try!(Regex::new(r"code=(.+?)(&|$)"));
        // Alternative example with map:
        // re.captures(path).map_or(Err("Expected authentication code"),
        //     |captures| try!(captures.at(1)).to_string())
        //
        //  or:
        //
        // re.captures(path).and_then(
        //   |captures| try!(captures.at(1)).to_string())
        // .or(Err("Expected authentication code")
        match re.captures(path) {
            Some(captures) => Ok(try!(captures.at(1)).to_string()),
            None => Err("Expected authentication code.")
        }
    }

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

        #[test]
        fn test_extract_auth_code() {
            let path = "www.timonv.nl?code=blablabla";
            assert_eq!(extract_auth_code(path).unwrap(), "blablabla".to_string())
        }
    }
}
<commit_msg>Reintroduce unwraps<commit_after>#![feature(io)]

extern crate hyper;
extern crate regex;

// TODO
fn main() {
    let token = authentication::get_oauth_token_or_panic();
    println!("{}", token);
}

// Temp
mod authentication {
    // Authentication
    use std::old_io::net::ip::Ipv4Addr;
    use hyper::server::{Server, Request, Response};
    use hyper::uri::RequestUri::AbsolutePath;
    use std::old_io::Command;
    // use hyper::status;
    use regex::Regex;
    use std::sync::mpsc::channel;
    use std::sync::Mutex;

    type AuthCode = String;

    pub fn get_oauth_token_or_panic() -> AuthCode {
        Command::new("xdg-open").arg("https://slack.com/oauth/authorize?client_id=2334733471.3592055147").output().unwrap();
        let server = Server::http(Ipv4Addr(127, 0, 0, 1), 9999);

        let (tx, rx) = channel();
        let mtx = Mutex::new(tx);

        let mut _guard = server.listen(move |req: Request, res: Response| {
            match req.uri {
                AbsolutePath(path) => {
                    let authcode = extract_auth_code(&path).unwrap();
                    mtx.lock().unwrap().send(authcode).unwrap();
                },
                _ => ()
            }

            let mut res = res.start().unwrap();
            res.write_all(b"Thanks! Please return to Lax").unwrap();
            res.end().unwrap();
        }).unwrap();

        let authcode = rx.recv().unwrap();
        _guard.close().unwrap();
        authcode
    }

    fn extract_auth_code(path: &str) -> Result<AuthCode, &'static str> {
        let re = Regex::new(r"code=(.+?)(&|$)").unwrap();
        // Alternative example with map:
        // re.captures(path).map_or(Err("Expected authentication code"),
        //     |captures| try!(captures.at(1)).to_string())
        //
        //  or:
        //
        // re.captures(path).and_then(
        //   |captures| try!(captures.at(1)).to_string())
        // .or(Err("Expected authentication code")
        //
        match re.captures(path) {
            Some(captures) => Ok(captures.at(1).unwrap().to_string()),
            None => Err("Expected authentication code.")
        }
    }

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

        #[test]
        fn test_extract_auth_code() {
            let path = "www.timonv.nl?code=blablabla";
            assert_eq!(extract_auth_code(path).unwrap(), "blablabla".to_string())
        }
    }
}
<|endoftext|>


<commit_before>#![crate_id="TicTacToe#0.1"]

extern crate sdl2;

use sdl2::video::Window;
use sdl2::video::PosCentered;
use sdl2::video::OpenGL;

use sdl2::render::Renderer;
use sdl2::render::DriverAuto;
use sdl2::render::Accelerated;

use sdl2::rect::Point;
use sdl2::pixels::RGB;

use sdl2::mouse::Mouse;

type SdlResult = Result<(), ~str>;

/// Draws a player X mark at a given location.
fn draw_x(r: &Renderer, x: i32, y: i32, w: i32, h: i32) -> SdlResult {
  try!(r.draw_line(Point::new(x, y), Point::new(x + w, y + h)));
  try!(r.draw_line(Point::new(x + w, y), Point::new(x, y + h)));
  Ok(())
}

/// Draws a player O mark at a given location.
fn draw_o(r: &Renderer, x: i32, y: i32, w: i32, h: i32) -> SdlResult {
  use std::f32::consts::PI;

  let segs = 16;
  let segr: f32 = 2f32 * PI / segs as f32;

  let cx: f32 = x as f32 + w as f32 / 2f32;
  let cy: f32 = y as f32 + h as f32 / 2f32;
  // technically we have to support oval shapes because the field is dynamically sized
  let rx: f32 = w as f32 / 2f32;
  let ry: f32 = h as f32 / 2f32;

  for i in range(0, segs) {
    let a = i as f32;
    let b = a + 1f32;
    let pt1 = Point::new(
      (cx + (a * segr).cos() * rx) as i32,
      (cy + (a * segr).sin() * ry) as i32);
    let pt2 = Point::new(
      (cx + (b * segr).cos() * rx) as i32,
      (cy + (b * segr).sin() * ry) as i32);
    try!(r.draw_line(pt1, pt2));
  }
  Ok(())
}

/// Specifies a set of methods that all game states should implement.
trait GameState {
  fn render(&self, r: &Renderer) -> SdlResult {
    Ok(())
  }

  fn on_mouse_down(&mut self, mouse: Mouse, x: int, y: int) {
  }
}

/// Represents the players in a Tic-tac-toe game.
#[deriving(Clone, Show)]
enum Mark {
  X, O
}

impl Mark {
  /// Returns the opposite mark.
  fn opposite(self) -> Mark {
    match self {
      X => O,
      O => X
    }
  }
}

/// Represents the winner in a game of Tic-tac-toe.
enum WinState {
  Win(Mark),
  Draw,
  Neither
}

/// Stores the board data associated with a game of Tic-tac-toe.
struct PlayField {
  cells: [Option<Mark>, ..9]
}

/// Represents a line of the Tic-tac-toe board. A line consists of three cells.
struct PlayLine {
  cells: [Option<Mark>, ..3]
}

impl PlayLine {
  /// Determines if this line counts as a win. Returns the winner wrapped in an
  /// Option, with None meaning that this line is not a winning one.
  fn is_win(&self) -> Option<Mark> {
    let (xs, os) = self.cells.iter().fold((0, 0), |(xs, os), &place| {
      match place {
        Some(X) => (xs + 1, os),
        Some(O) => (xs, os + 1),
        None    => (xs, os)
      }
    });
    if xs == 3 {
      Some(X)
    } else if os == 3 {
      Some(O)
    } else {
      None
    }
  }
}

enum LineIteratorState {
  Row(uint),
  Column(uint),
  LtrDiagonal,
  RtlDiagonal,
  Finished
}

struct LineIterator<'a> {
  field: &'a PlayField,
  state: LineIteratorState
}

impl<'a> LineIterator<'a> {
  fn from_field<'a>(f: &'a PlayField) -> LineIterator<'a> {
    LineIterator {
      field: f,
      state: Row(0)
    }
  }
}

impl<'a> Iterator<PlayLine> for LineIterator<'a> {
  fn next(&mut self) -> Option<PlayLine> {
    match self.state {
      Row(place) => {
        self.state = if place + 1 < 3 {
          Row(place + 1)
        } else {
          Column(0)
        };
        self.field.horizontal_line(place)
      },
      Column(place) => {
        self.state = if place + 1 < 3 {
          Column(place + 1)
        } else {
          LtrDiagonal
        };
        self.field.vertical_line(place)
      },
      LtrDiagonal => {
        self.state = RtlDiagonal;
        Some(self.field.ltr_diagonal_line())
      },
      RtlDiagonal => {
        self.state = Finished;
        Some(self.field.rtl_diagonal_line())
      },
      Finished => None
    }
  }
}

impl PlayField {
  fn new() -> PlayField {
    PlayField {
      cells: [None, ..9]
    }
  }

  /// Returns the number of occupied cells.
  fn occupied_count(&self) -> int {
    self.cells.iter().fold(0, |s, mark| if mark.is_some() { s + 1 } else { s })
  }

  /// Returns an iterator over the `PlayLine`s in this field.
  fn lines<'a>(&'a self) -> LineIterator<'a> {
    LineIterator::from_field(self)
  }

  fn horizontal_line(&self, row: uint) -> Option<PlayLine> {
    PlayField::map_xy(0, row).map(|ix| PlayLine {
      // there's probably a trick to do this with a slice
      cells: [self.cells[ix], self.cells[ix + 1], self.cells[ix + 2]]
    })
  }

  fn vertical_line(&self, col: uint) -> Option<PlayLine> {
    PlayField::map_xy(col, 0).map(|ix| PlayLine {
      cells: [self.cells[ix], self.cells[ix + 3], self.cells[ix + 6]]
    })
  }

  fn ltr_diagonal_line(&self) -> PlayLine {
    PlayLine {
      cells: [self.cells[0], self.cells[4], self.cells[8]]
    }
  }

  fn rtl_diagonal_line(&self) -> PlayLine {
    PlayLine {
      cells: [self.cells[2], self.cells[4], self.cells[6]]
    }
  }

  fn map_xy(x: uint, y: uint) -> Option<uint> {
    if y < 3 && y < 3 {
      Some(y * 3 + x)
    } else {
      None
    }
  }

  fn get_cell_xy(&self, x: uint, y: uint) -> Option< Option<Mark> > {
    PlayField::map_xy(x, y).map(|ix| self.cells[ix])
  }

  fn get_mut_cell_xy<'a>(&'a mut self, x: uint, y: uint) -> Option< &'a mut Option<Mark> > {
    match PlayField::map_xy(x, y) {
      Some(ix) => Some(&mut self.cells[ix]),
      None     => None
    }
  }
}

/// Represents an on-screen area where a Tic-tac-toe board can be interacted
/// with.
struct FieldArea {
  x: int, y: int,
  w: int, h: int
}

impl FieldArea {
  /// Returns the width of an individual cell.
  fn cell_width(&self) -> int {
    self.w / 3
  }

  /// Returns the height of an individual cell.
  fn cell_height(&self) -> int {
    self.h / 3
  }

  /// Computes the row at a given on-screen Y-coordinate.
  fn unproject_row(&self, y: int) -> Option<int> {
    if y >= self.y {
      match (y - self.y) / self.cell_height() {
        ix if ix > 2 => None,
        ix           => Some(ix)
      }
    } else {
      None
    }
  }

  /// Computes the column at a given on-screen X-coordinate.
  fn unproject_col(&self, x: int) -> Option<int> {
    if x >= self.x {
      match (x - self.x) / self.cell_width() {
        ix if ix > 2 => None,
        ix           => Some(ix)
      }
    } else {
      None
    }
  }

  /// Computes the given row and column given on-screen X and Y coordinates.
  fn unproject(&self, x: int, y: int) -> Option<(int, int)> {
    let row = match self.unproject_row(y) {
      Some(row) => row,
      None      => return None
    };
    let col = match self.unproject_col(x) {
      Some(col) => col,
      None      => return None
    };
    Some((row, col))
  }

  /// Computes the on-screen X and Y coordinates for a given row and column.
  fn project(&self, row: int, col: int) -> Point {
    let x = (self.x + col * self.cell_width()) as i32;
    let y = (self.y + row * self.cell_height()) as i32;
    Point::new(x, y)
  }
}

struct PlayState {
  field: PlayField,
  area: FieldArea,
  turn: Mark,
  winner: WinState
}
impl PlayState {
  fn new() -> ~PlayState {
    ~PlayState {
      field: PlayField::new(),
      area: FieldArea {
        x: 100, y: 0, w: 600, h: 600
      },
      turn: X,
      winner: Neither
    }
  }
}
impl GameState for PlayState {
  fn render(&self, renderer: &Renderer) -> SdlResult {
    try!(renderer.set_draw_color(RGB(0, 0, 0)));
    try!(renderer.clear());

    try!(renderer.set_draw_color(RGB(255, 0, 0)));

    for i in range(1, 3) {
      let x1 = self.area.x as i32;
      let y1 = (self.area.y + self.area.cell_height() * i) as i32;
      let x2 = (self.area.x + self.area.w) as i32;
      let y2 = (self.area.y + self.area.cell_height() * i) as i32;
      try!(renderer.draw_line(Point::new(x1, y1), Point::new(x2, y2)));
    }
    for i in range(1, 3) {
      let x1 = (self.area.x + self.area.cell_width() * i) as i32;
      let y1 = self.area.y as i32;
      let x2 = (self.area.x + self.area.cell_width() * i) as i32;
      let y2 = (self.area.y + self.area.h) as i32;
      try!(renderer.draw_line(Point::new(x1, y1), Point::new(x2, y2)));
    }

    try!(renderer.set_draw_color(RGB(0, 255, 0)));

    for row in range(0, 3) {
      for col in range(0, 3) {
        let pt = self.area.project(row, col);

        self.field.get_cell_xy(col as uint, row as uint).map(|mark| {
          // TODO: Try to remove a layer of indirection here
          match mark {
            Some(X) => draw_x(renderer, pt.x, pt.y, self.area.cell_width() as i32, self.area.cell_height() as i32),
            Some(O) => draw_o(renderer, pt.x, pt.y, self.area.cell_width() as i32, self.area.cell_height() as i32),
            _ => Ok(())
          }
        }).unwrap().unwrap();
      }
    }
    Ok(())
  }

  fn on_mouse_down(&mut self, button: Mouse, x: int, y: int) {
    match self.winner {
      Neither => {},
      _ => {
        self.field = PlayField::new();
        self.winner = Neither;
      }
    }

    match self.area.unproject(x, y) {
      Some((row,col)) => {
        match self.field.get_mut_cell_xy(col as uint, row as uint) {
          Some(r) => match *r {
            None => {
              *r = Some(self.turn);
              self.turn = self.turn.opposite();
            },
            _ => println!("space already occupied")
          },
          None => fail!("invalid coords! this should never happen!")
        }
      },
      None => println!("clicked out of bounds")
    }

    self.winner = self.check_winner();
    match self.winner {
      Win(mark) => {
        println!("{} wins!", mark);
      },
      Draw => {
        println!("draw")
      },
      Neither => {}
    }
  }
}

impl PlayState {
  fn check_winner(&self) -> WinState {
    for line in self.field.lines() {
      match line.is_win() {
        Some(mark) => {
          return Win(mark)
        },
        None => {}
      };
    };

    if self.field.occupied_count() == 9 {
      return Draw
    };

    return Neither
  }
}

fn main() {
  sdl2::init(sdl2::InitVideo);

  // TODO: since we're going to fail! anyways these could be converted to .unwrap()
  let window = match Window::new("Tic Tac Toe: The Rustening", PosCentered, PosCentered, 800, 600, OpenGL) {
    Ok(window) => window,
    Err(err)   => fail!("failed to create window: {}", err)
  };

  let renderer = match Renderer::from_window(window, DriverAuto, Accelerated) {
    Ok(renderer) => renderer,
    Err(err)     => fail!("failed to create renderer: {}", err)
  };

  // TODO: state machine
  let mut state = PlayState::new();

  loop {
    use sdl2::event::poll_event;
    use sdl2::event::{QuitEvent, MouseButtonDownEvent};

    match poll_event() {
      QuitEvent(..) => break,
      MouseButtonDownEvent(_, _, _, button, x, y) => state.on_mouse_down(button, x, y),
      _ => {}
    }

    state.render(renderer).unwrap();
    renderer.present();
  }

  sdl2::quit();
}
<commit_msg>Allow unused_variable on default GameState functions<commit_after>#![crate_id="TicTacToe#0.1"]

extern crate sdl2;

use sdl2::video::Window;
use sdl2::video::PosCentered;
use sdl2::video::OpenGL;

use sdl2::render::Renderer;
use sdl2::render::DriverAuto;
use sdl2::render::Accelerated;

use sdl2::rect::Point;
use sdl2::pixels::RGB;

use sdl2::mouse::Mouse;

type SdlResult = Result<(), ~str>;

/// Draws a player X mark at a given location.
fn draw_x(r: &Renderer, x: i32, y: i32, w: i32, h: i32) -> SdlResult {
  try!(r.draw_line(Point::new(x, y), Point::new(x + w, y + h)));
  try!(r.draw_line(Point::new(x + w, y), Point::new(x, y + h)));
  Ok(())
}

/// Draws a player O mark at a given location.
fn draw_o(r: &Renderer, x: i32, y: i32, w: i32, h: i32) -> SdlResult {
  use std::f32::consts::PI;

  let segs = 16;
  let segr: f32 = 2f32 * PI / segs as f32;

  let cx: f32 = x as f32 + w as f32 / 2f32;
  let cy: f32 = y as f32 + h as f32 / 2f32;
  // technically we have to support oval shapes because the field is dynamically sized
  let rx: f32 = w as f32 / 2f32;
  let ry: f32 = h as f32 / 2f32;

  for i in range(0, segs) {
    let a = i as f32;
    let b = a + 1f32;
    let pt1 = Point::new(
      (cx + (a * segr).cos() * rx) as i32,
      (cy + (a * segr).sin() * ry) as i32);
    let pt2 = Point::new(
      (cx + (b * segr).cos() * rx) as i32,
      (cy + (b * segr).sin() * ry) as i32);
    try!(r.draw_line(pt1, pt2));
  }
  Ok(())
}

/// Specifies a set of methods that all game states should implement.
trait GameState {
  #[allow(unused_variable)]
  fn render(&self, r: &Renderer) -> SdlResult {
    Ok(())
  }

  #[allow(unused_variable)]
  fn on_mouse_down(&mut self, mouse: Mouse, x: int, y: int) {
  }
}

/// Represents the players in a Tic-tac-toe game.
#[deriving(Clone, Show)]
enum Mark {
  X, O
}

impl Mark {
  /// Returns the opposite mark.
  fn opposite(self) -> Mark {
    match self {
      X => O,
      O => X
    }
  }
}

/// Represents the winner in a game of Tic-tac-toe.
enum WinState {
  Win(Mark),
  Draw,
  Neither
}

/// Stores the board data associated with a game of Tic-tac-toe.
struct PlayField {
  cells: [Option<Mark>, ..9]
}

/// Represents a line of the Tic-tac-toe board. A line consists of three cells.
struct PlayLine {
  cells: [Option<Mark>, ..3]
}

impl PlayLine {
  /// Determines if this line counts as a win. Returns the winner wrapped in an
  /// Option, with None meaning that this line is not a winning one.
  fn is_win(&self) -> Option<Mark> {
    let (xs, os) = self.cells.iter().fold((0, 0), |(xs, os), &place| {
      match place {
        Some(X) => (xs + 1, os),
        Some(O) => (xs, os + 1),
        None    => (xs, os)
      }
    });
    if xs == 3 {
      Some(X)
    } else if os == 3 {
      Some(O)
    } else {
      None
    }
  }
}

enum LineIteratorState {
  Row(uint),
  Column(uint),
  LtrDiagonal,
  RtlDiagonal,
  Finished
}

struct LineIterator<'a> {
  field: &'a PlayField,
  state: LineIteratorState
}

impl<'a> LineIterator<'a> {
  fn from_field<'a>(f: &'a PlayField) -> LineIterator<'a> {
    LineIterator {
      field: f,
      state: Row(0)
    }
  }
}

impl<'a> Iterator<PlayLine> for LineIterator<'a> {
  fn next(&mut self) -> Option<PlayLine> {
    match self.state {
      Row(place) => {
        self.state = if place + 1 < 3 {
          Row(place + 1)
        } else {
          Column(0)
        };
        self.field.horizontal_line(place)
      },
      Column(place) => {
        self.state = if place + 1 < 3 {
          Column(place + 1)
        } else {
          LtrDiagonal
        };
        self.field.vertical_line(place)
      },
      LtrDiagonal => {
        self.state = RtlDiagonal;
        Some(self.field.ltr_diagonal_line())
      },
      RtlDiagonal => {
        self.state = Finished;
        Some(self.field.rtl_diagonal_line())
      },
      Finished => None
    }
  }
}

impl PlayField {
  fn new() -> PlayField {
    PlayField {
      cells: [None, ..9]
    }
  }

  /// Returns the number of occupied cells.
  fn occupied_count(&self) -> int {
    self.cells.iter().fold(0, |s, mark| if mark.is_some() { s + 1 } else { s })
  }

  /// Returns an iterator over the `PlayLine`s in this field.
  fn lines<'a>(&'a self) -> LineIterator<'a> {
    LineIterator::from_field(self)
  }

  fn horizontal_line(&self, row: uint) -> Option<PlayLine> {
    PlayField::map_xy(0, row).map(|ix| PlayLine {
      // there's probably a trick to do this with a slice
      cells: [self.cells[ix], self.cells[ix + 1], self.cells[ix + 2]]
    })
  }

  fn vertical_line(&self, col: uint) -> Option<PlayLine> {
    PlayField::map_xy(col, 0).map(|ix| PlayLine {
      cells: [self.cells[ix], self.cells[ix + 3], self.cells[ix + 6]]
    })
  }

  fn ltr_diagonal_line(&self) -> PlayLine {
    PlayLine {
      cells: [self.cells[0], self.cells[4], self.cells[8]]
    }
  }

  fn rtl_diagonal_line(&self) -> PlayLine {
    PlayLine {
      cells: [self.cells[2], self.cells[4], self.cells[6]]
    }
  }

  fn map_xy(x: uint, y: uint) -> Option<uint> {
    if y < 3 && y < 3 {
      Some(y * 3 + x)
    } else {
      None
    }
  }

  fn get_cell_xy(&self, x: uint, y: uint) -> Option< Option<Mark> > {
    PlayField::map_xy(x, y).map(|ix| self.cells[ix])
  }

  fn get_mut_cell_xy<'a>(&'a mut self, x: uint, y: uint) -> Option< &'a mut Option<Mark> > {
    match PlayField::map_xy(x, y) {
      Some(ix) => Some(&mut self.cells[ix]),
      None     => None
    }
  }
}

/// Represents an on-screen area where a Tic-tac-toe board can be interacted
/// with.
struct FieldArea {
  x: int, y: int,
  w: int, h: int
}

impl FieldArea {
  /// Returns the width of an individual cell.
  fn cell_width(&self) -> int {
    self.w / 3
  }

  /// Returns the height of an individual cell.
  fn cell_height(&self) -> int {
    self.h / 3
  }

  /// Computes the row at a given on-screen Y-coordinate.
  fn unproject_row(&self, y: int) -> Option<int> {
    if y >= self.y {
      match (y - self.y) / self.cell_height() {
        ix if ix > 2 => None,
        ix           => Some(ix)
      }
    } else {
      None
    }
  }

  /// Computes the column at a given on-screen X-coordinate.
  fn unproject_col(&self, x: int) -> Option<int> {
    if x >= self.x {
      match (x - self.x) / self.cell_width() {
        ix if ix > 2 => None,
        ix           => Some(ix)
      }
    } else {
      None
    }
  }

  /// Computes the given row and column given on-screen X and Y coordinates.
  fn unproject(&self, x: int, y: int) -> Option<(int, int)> {
    let row = match self.unproject_row(y) {
      Some(row) => row,
      None      => return None
    };
    let col = match self.unproject_col(x) {
      Some(col) => col,
      None      => return None
    };
    Some((row, col))
  }

  /// Computes the on-screen X and Y coordinates for a given row and column.
  fn project(&self, row: int, col: int) -> Point {
    let x = (self.x + col * self.cell_width()) as i32;
    let y = (self.y + row * self.cell_height()) as i32;
    Point::new(x, y)
  }
}

struct PlayState {
  field: PlayField,
  area: FieldArea,
  turn: Mark,
  winner: WinState
}
impl PlayState {
  fn new() -> ~PlayState {
    ~PlayState {
      field: PlayField::new(),
      area: FieldArea {
        x: 100, y: 0, w: 600, h: 600
      },
      turn: X,
      winner: Neither
    }
  }
}
impl GameState for PlayState {
  fn render(&self, renderer: &Renderer) -> SdlResult {
    try!(renderer.set_draw_color(RGB(0, 0, 0)));
    try!(renderer.clear());

    try!(renderer.set_draw_color(RGB(255, 0, 0)));

    for i in range(1, 3) {
      let x1 = self.area.x as i32;
      let y1 = (self.area.y + self.area.cell_height() * i) as i32;
      let x2 = (self.area.x + self.area.w) as i32;
      let y2 = (self.area.y + self.area.cell_height() * i) as i32;
      try!(renderer.draw_line(Point::new(x1, y1), Point::new(x2, y2)));
    }
    for i in range(1, 3) {
      let x1 = (self.area.x + self.area.cell_width() * i) as i32;
      let y1 = self.area.y as i32;
      let x2 = (self.area.x + self.area.cell_width() * i) as i32;
      let y2 = (self.area.y + self.area.h) as i32;
      try!(renderer.draw_line(Point::new(x1, y1), Point::new(x2, y2)));
    }

    try!(renderer.set_draw_color(RGB(0, 255, 0)));

    for row in range(0, 3) {
      for col in range(0, 3) {
        let pt = self.area.project(row, col);

        self.field.get_cell_xy(col as uint, row as uint).map(|mark| {
          // TODO: Try to remove a layer of indirection here
          match mark {
            Some(X) => draw_x(renderer, pt.x, pt.y, self.area.cell_width() as i32, self.area.cell_height() as i32),
            Some(O) => draw_o(renderer, pt.x, pt.y, self.area.cell_width() as i32, self.area.cell_height() as i32),
            _ => Ok(())
          }
        }).unwrap().unwrap();
      }
    }
    Ok(())
  }

  fn on_mouse_down(&mut self, button: Mouse, x: int, y: int) {
    match self.winner {
      Neither => {},
      _ => {
        self.field = PlayField::new();
        self.winner = Neither;
      }
    }

    match self.area.unproject(x, y) {
      Some((row,col)) => {
        match self.field.get_mut_cell_xy(col as uint, row as uint) {
          Some(r) => match *r {
            None => {
              *r = Some(self.turn);
              self.turn = self.turn.opposite();
            },
            _ => println!("space already occupied")
          },
          None => fail!("invalid coords! this should never happen!")
        }
      },
      None => println!("clicked out of bounds")
    }

    self.winner = self.check_winner();
    match self.winner {
      Win(mark) => {
        println!("{} wins!", mark);
      },
      Draw => {
        println!("draw")
      },
      Neither => {}
    }
  }
}

impl PlayState {
  fn check_winner(&self) -> WinState {
    for line in self.field.lines() {
      match line.is_win() {
        Some(mark) => {
          return Win(mark)
        },
        None => {}
      };
    };

    if self.field.occupied_count() == 9 {
      return Draw
    };

    return Neither
  }
}

fn main() {
  sdl2::init(sdl2::InitVideo);

  // TODO: since we're going to fail! anyways these could be converted to .unwrap()
  let window = match Window::new("Tic Tac Toe: The Rustening", PosCentered, PosCentered, 800, 600, OpenGL) {
    Ok(window) => window,
    Err(err)   => fail!("failed to create window: {}", err)
  };

  let renderer = match Renderer::from_window(window, DriverAuto, Accelerated) {
    Ok(renderer) => renderer,
    Err(err)     => fail!("failed to create renderer: {}", err)
  };

  // TODO: state machine
  let mut state = PlayState::new();

  loop {
    use sdl2::event::poll_event;
    use sdl2::event::{QuitEvent, MouseButtonDownEvent};

    match poll_event() {
      QuitEvent(..) => break,
      MouseButtonDownEvent(_, _, _, button, x, y) => state.on_mouse_down(button, x, y),
      _ => {}
    }

    state.render(renderer).unwrap();
    renderer.present();
  }

  sdl2::quit();
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate toml;
extern crate clap;
extern crate hyper;
extern crate hyper_native_tls;

mod gitignore;
mod cli;

use std::fs::{File, OpenOptions, create_dir, read_dir};
use std::io::{BufReader, Result, Error, ErrorKind};
use std::io::prelude::*;
use std::path::Path;
use std::process::{exit, Command};
use std::env;

#[derive(Deserialize)]
struct Config {
    mkdir: Option<Vec<String>>,
    touch: Option<Vec<String>>,
    exec: Option<Vec<String>>,
    gitignore: Option<Vec<String>>,
    include: Option<Vec<String>>,
    order: Option<Vec<String>>,
}

fn main() {
    let matches = cli::build_cli().get_matches();
    let lang = matches.value_of("lang").unwrap();

    if let Some(matches) = matches.subcommand_matches("new") {
        println!("doing new {}", matches.value_of("NAME").unwrap());
    }

    let config_path = match get_config_path(&lang.to_string()) {
        Some(p) => p,
        None => {
            println!("Could not find home directory");
            exit(1);
        }
    };

    let config: Config = match parse_config(config_path) {
        Ok(c) => c,
        Err(err) => {
            println!("Error while parsing config! {:?}", err);
            exit(1);
        }
    };

    if let Some(subcmd) = matches.subcommand_matches("new") {
        let name = subcmd.value_of("NAME").unwrap();
        if file_exists(&name.to_string()) {
            println!("A file or directory with that name already exists");
            exit(1);
        } else {
            match create_dir(name.clone()) {
                Ok(_) => println!("Created directory '{}'", name),
                Err(e) => {
                    println!("Could not create directory '{}'. {:?}", name, e);
                    exit(1);
                }
            }
            if let Err(_) = env::set_current_dir(Path::new(&*name)) {
                println!("Could not change directory!");
                exit(1);
            }
        }
    }

    if !dir_is_empty(&".".to_string()) {
        println!("Directory is not empty!");
        exit(1);
    }

    if let Some(ref includes) = config.include {
        for incl in includes {
            let path = match get_config_path(&incl) {
                Some(p) => p,
                None => {
                    println!("Could not resolve home directory");
                    exit(1);
                }
            };

            let conf: Config = match parse_config(path) {
                Ok(c) => c,
                Err(e) => {
                    println!("Could not read include '{}'. {}", incl, e);
                    exit(1);
                }
            };
            process_config(conf);
        }
    }

    process_config(config);

}

fn mkdir(dirs: &Option<Vec<String>>) {
    if let Some(ref dirs) = *dirs {
        for dir in dirs {
            if !file_exists(&dir) {
                match create_dir(dir.clone()) {
                    Ok(_) => println!("Created directory '{}'", dir),
                    Err(e) => println!("Could not create directory '{}'. {:?}", dir, e),
                }
            } else {
                println!("Directory '{}' already exists", dir);
            }
        }
    }
}

fn gitignore(gi: &Option<Vec<String>>) {
    if let Some(ref gi) = *gi {
        let ign = gitignore::get_gitignore(&gi).unwrap();
        let file = OpenOptions::new()
            .create_new(true)
            .append(true)
            .open(".gitignore");
        if let Ok(mut file) = file {
            match writeln!(file, "{}", ign) {
                Ok(_) => {}
                Err(e) => println!("Could not write .gitignore. {:?}", e),
            }
        } else {
            println!("Could not write .gitignore");
        }
    }
}

fn touch(files: &Option<Vec<String>>) {
    if let Some(ref fnames) = *files {
        for file in fnames {
            if !create_file(&file) {
                println!("Could not create file '{}'", file);
            }
        }
    }
}

fn exec_list(cmd_list: &Option<Vec<String>>) {
    if let Some(ref cmds) = *cmd_list {
        for cmd in cmds {
            println!("Executing '{}'", cmd);
            match exec(&cmd) {
                Ok((out, err)) => {
                    println!("stdout: {}", out);
                    println!("stderr: {}", err);
                }
                Err(e) => println!("Failed to execute: {:?}", e),
            }
        }
    }
}

fn process_config(config: Config) {
    let order: Vec<String> = match config.order {
        Some(order) => order,
        None => {
            vec!["mkdir".to_string(),
                 "gitignore".to_string(),
                 "touch".to_string(),
                 "exec".to_string()]
        }
    };

    for ord in order {
        match &*ord {
            "mkdir" => mkdir(&config.mkdir),
            "gitignore" => gitignore(&config.gitignore),
            "touch" => touch(&config.touch),
            "exec" => exec_list(&config.exec),
            x => println!("Unknown operation \"{}\"", x),
        }
    }
}

/// Returns the config path for a `lang` parameter.
///
/// This method concatenates $HOME with "/.skeleton/{lang}.toml"
///
/// # Examples
///
/// ```
/// let path = get_config_path(&"rust".to_string())
/// ```
fn get_config_path(lang: &String) -> Option<String> {
    let home = match env::home_dir() {
        Some(p) => p,
        None => return None,
    };
    let config_path_cow = home.to_string_lossy();
    let mut config_path = config_path_cow.into_owned();
    // let mut config_path = env!("HOME").to_string();

    config_path.push_str("/.skeleton/");
    config_path.push_str(lang);
    config_path.push_str(".toml");
    Some(config_path)
}

/// Checks if a directory is empty
///
/// # Examples
///
/// ```
/// let dir_is_empty(&".".to_string());
/// ```
fn dir_is_empty(dir: &String) -> bool {
    let paths = match read_dir(dir) {
        Ok(paths) => paths,
        Err(_) => return false,
    };

    for _ in paths {
        return false;
    }
    true
}

/// Checks if a file exists
fn file_exists(name: &String) -> bool {
    Path::new(&name).exists()
}

/// Executes a command using `sh` or `cmd.exe` depending on the used operating system.
///
/// Returns either a `Error` or a tuple `(stdout, stderr)`
fn exec(cmd: &String) -> Result<(String, String)> {
    #[cfg(unix)]
    let shell = "sh";
    #[cfg(unix)]
    let arg1 = "-c";
    #[cfg(windows)]
    let shell = "cmd.exe";
    #[cfg(windows)]
    let arg1 = "/C";

    let out = Command::new(shell).arg(arg1).arg(cmd).output()?;

    Ok((String::from_utf8(out.stdout).unwrap_or("Could not parse stdout".to_string()),
        String::from_utf8(out.stderr).unwrap_or("Could not parse stderr".to_string())))

}

/// Creates a file if it doesn't exist.
fn create_file(file_name: &String) -> bool {
    !file_exists(&file_name) &&
    OpenOptions::new()
        .append(true)
        .create(true)
        .open(file_name)
        .is_ok()
}

/// Parses a configuration file and returns the `Config` struct.
fn parse_config(file_name: String) -> Result<Config> {
    let file = File::open(file_name)?;
    let mut reader = BufReader::new(file);
    let mut contents = String::new();

    reader.read_to_string(&mut contents)?;

    toml::from_str(&contents).map_err(|err| Error::new(ErrorKind::InvalidInput, err))
}

#[test]
fn test_file_exists() {
    assert!(file_exists(&"test/foo.toml".to_string()));
    assert!(!file_exists(&"test/none".to_string()));
}

#[test]
fn test_parse_config() {
    let conf = parse_config("test/foo.toml".to_string()).unwrap();
    let gi = conf.gitignore.unwrap();
    assert_eq!(gi, vec!["rust".to_string(), "vim".to_string()]);

    let mkd = conf.mkdir.unwrap();
    assert_eq!(mkd, vec!["b".to_string()]);

    let touch = conf.touch.unwrap();
    assert_eq!(touch, vec!["a".to_string()]);

    let exec = conf.exec.unwrap();
    assert_eq!(exec, vec!["touch asdf".to_string()]);
}

#[test]
fn test_exec() {
    let (stdout, stderr) = exec(&"echo -n test".to_string()).unwrap();
    assert_eq!(stdout, "test".to_string());
    assert_eq!(stderr, "".to_string());
    let (stdout, stderr) = exec(&"echo -n test 1>&2".to_string()).unwrap();
    assert_eq!(stdout, "".to_string());
    assert_eq!(stderr, "test".to_string());
}

#[test]
fn test_dir_is_empty() {
    let is_empty = dir_is_empty(&"./test".to_string());
    assert!(!is_empty);
    let non_existent = dir_is_empty(&"./non_existent_dir".to_string());
    assert!(!non_existent);
}

#[test]
fn test_get_config_path() {
    let expected = get_config_path(&"foo".to_string()).unwrap();
    let mut actual = env::home_dir().unwrap().to_str().unwrap().to_string();
    actual.push_str("/.skeleton/foo.toml");
    assert_eq!(actual, expected);
}
<commit_msg>Fix tests to work for both Windows and Linux<commit_after>#[macro_use]
extern crate serde_derive;
extern crate toml;
extern crate clap;
extern crate hyper;
extern crate hyper_native_tls;

mod gitignore;
mod cli;

use std::fs::{File, OpenOptions, create_dir, read_dir};
use std::io::{BufReader, Result, Error, ErrorKind};
use std::io::prelude::*;
use std::path::Path;
use std::process::{exit, Command};
use std::env;

#[derive(Deserialize)]
struct Config {
    mkdir: Option<Vec<String>>,
    touch: Option<Vec<String>>,
    exec: Option<Vec<String>>,
    gitignore: Option<Vec<String>>,
    include: Option<Vec<String>>,
    order: Option<Vec<String>>,
}

fn main() {
    let matches = cli::build_cli().get_matches();
    let lang = matches.value_of("lang").unwrap();

    if let Some(matches) = matches.subcommand_matches("new") {
        println!("doing new {}", matches.value_of("NAME").unwrap());
    }

    let config_path = match get_config_path(&lang.to_string()) {
        Some(p) => p,
        None => {
            println!("Could not find home directory");
            exit(1);
        }
    };

    let config: Config = match parse_config(config_path) {
        Ok(c) => c,
        Err(err) => {
            println!("Error while parsing config! {:?}", err);
            exit(1);
        }
    };

    if let Some(subcmd) = matches.subcommand_matches("new") {
        let name = subcmd.value_of("NAME").unwrap();
        if file_exists(&name.to_string()) {
            println!("A file or directory with that name already exists");
            exit(1);
        } else {
            match create_dir(name.clone()) {
                Ok(_) => println!("Created directory '{}'", name),
                Err(e) => {
                    println!("Could not create directory '{}'. {:?}", name, e);
                    exit(1);
                }
            }
            if let Err(_) = env::set_current_dir(Path::new(&*name)) {
                println!("Could not change directory!");
                exit(1);
            }
        }
    }

    if !dir_is_empty(&".".to_string()) {
        println!("Directory is not empty!");
        exit(1);
    }

    if let Some(ref includes) = config.include {
        for incl in includes {
            let path = match get_config_path(&incl) {
                Some(p) => p,
                None => {
                    println!("Could not resolve home directory");
                    exit(1);
                }
            };

            let conf: Config = match parse_config(path) {
                Ok(c) => c,
                Err(e) => {
                    println!("Could not read include '{}'. {}", incl, e);
                    exit(1);
                }
            };
            process_config(conf);
        }
    }

    process_config(config);

}

fn mkdir(dirs: &Option<Vec<String>>) {
    if let Some(ref dirs) = *dirs {
        for dir in dirs {
            if !file_exists(&dir) {
                match create_dir(dir.clone()) {
                    Ok(_) => println!("Created directory '{}'", dir),
                    Err(e) => println!("Could not create directory '{}'. {:?}", dir, e),
                }
            } else {
                println!("Directory '{}' already exists", dir);
            }
        }
    }
}

fn gitignore(gi: &Option<Vec<String>>) {
    if let Some(ref gi) = *gi {
        let ign = gitignore::get_gitignore(&gi).unwrap();
        let file = OpenOptions::new()
            .create_new(true)
            .append(true)
            .open(".gitignore");
        if let Ok(mut file) = file {
            match writeln!(file, "{}", ign) {
                Ok(_) => {}
                Err(e) => println!("Could not write .gitignore. {:?}", e),
            }
        } else {
            println!("Could not write .gitignore");
        }
    }
}

fn touch(files: &Option<Vec<String>>) {
    if let Some(ref fnames) = *files {
        for file in fnames {
            if !create_file(&file) {
                println!("Could not create file '{}'", file);
            }
        }
    }
}

fn exec_list(cmd_list: &Option<Vec<String>>) {
    if let Some(ref cmds) = *cmd_list {
        for cmd in cmds {
            println!("Executing '{}'", cmd);
            match exec(&cmd) {
                Ok((out, err)) => {
                    println!("stdout: {}", out);
                    println!("stderr: {}", err);
                }
                Err(e) => println!("Failed to execute: {:?}", e),
            }
        }
    }
}

fn process_config(config: Config) {
    let order: Vec<String> = match config.order {
        Some(order) => order,
        None => {
            vec!["mkdir".to_string(),
                 "gitignore".to_string(),
                 "touch".to_string(),
                 "exec".to_string()]
        }
    };

    for ord in order {
        match &*ord {
            "mkdir" => mkdir(&config.mkdir),
            "gitignore" => gitignore(&config.gitignore),
            "touch" => touch(&config.touch),
            "exec" => exec_list(&config.exec),
            x => println!("Unknown operation \"{}\"", x),
        }
    }
}

/// Returns the config path for a `lang` parameter.
///
/// This method concatenates $HOME with "/.skeleton/{lang}.toml"
///
/// # Examples
///
/// ```
/// let path = get_config_path(&"rust".to_string())
/// ```
fn get_config_path(lang: &String) -> Option<String> {
    let home = match env::home_dir() {
        Some(p) => p,
        None => return None,
    };
    let config_path_cow = home.to_string_lossy();
    let mut config_path = config_path_cow.into_owned();
    // let mut config_path = env!("HOME").to_string();

    config_path.push_str("/.skeleton/");
    config_path.push_str(lang);
    config_path.push_str(".toml");
    Some(config_path)
}

/// Checks if a directory is empty
///
/// # Examples
///
/// ```
/// let dir_is_empty(&".".to_string());
/// ```
fn dir_is_empty(dir: &String) -> bool {
    let paths = match read_dir(dir) {
        Ok(paths) => paths,
        Err(_) => return false,
    };

    for _ in paths {
        return false;
    }
    true
}

/// Checks if a file exists
fn file_exists(name: &String) -> bool {
    Path::new(&name).exists()
}

/// Executes a command using `sh` or `cmd.exe` depending on the used operating system.
///
/// Returns either a `Error` or a tuple `(stdout, stderr)`
fn exec(cmd: &String) -> Result<(String, String)> {
    #[cfg(unix)]
    let shell = "sh";
    #[cfg(unix)]
    let arg1 = "-c";
    #[cfg(windows)]
    let shell = "cmd.exe";
    #[cfg(windows)]
    let arg1 = "/C";

    let out = Command::new(shell).arg(arg1).arg(cmd).output()?;

    Ok((String::from_utf8(out.stdout).unwrap_or("Could not parse stdout".to_string()),
        String::from_utf8(out.stderr).unwrap_or("Could not parse stderr".to_string())))

}

/// Creates a file if it doesn't exist.
fn create_file(file_name: &String) -> bool {
    !file_exists(&file_name) &&
    OpenOptions::new()
        .append(true)
        .create(true)
        .open(file_name)
        .is_ok()
}

/// Parses a configuration file and returns the `Config` struct.
fn parse_config(file_name: String) -> Result<Config> {
    let file = File::open(file_name)?;
    let mut reader = BufReader::new(file);
    let mut contents = String::new();

    reader.read_to_string(&mut contents)?;

    toml::from_str(&contents).map_err(|err| Error::new(ErrorKind::InvalidInput, err))
}

#[test]
fn test_file_exists() {
    assert!(file_exists(&"test/foo.toml".to_string()));
    assert!(!file_exists(&"test/none".to_string()));
}

#[test]
fn test_parse_config() {
    let conf = parse_config("test/foo.toml".to_string()).unwrap();
    let gi = conf.gitignore.unwrap();
    assert_eq!(gi, vec!["rust".to_string(), "vim".to_string()]);

    let mkd = conf.mkdir.unwrap();
    assert_eq!(mkd, vec!["b".to_string()]);

    let touch = conf.touch.unwrap();
    assert_eq!(touch, vec!["a".to_string()]);

    let exec = conf.exec.unwrap();
    assert_eq!(exec, vec!["touch asdf".to_string()]);
}

#[test]
fn test_exec() {
    let (stdout, stderr) = exec(&"echo test".to_string()).unwrap();
    #[cfg(unix)]
    assert_eq!(stdout, "test\n".to_string());
    #[cfg(windows)]
    assert_eq!(stdout, "test\r\n".to_string());
    assert_eq!(stderr, "".to_string());
    let (stdout, stderr) = exec(&"echo test 1>&2".to_string()).unwrap();
    assert_eq!(stdout, "".to_string());
    #[cfg(unix)]
    assert_eq!(stderr, "test\n".to_string());
    #[cfg(windows)]
    assert_eq!(stderr, "test\r\n".to_string());
}

#[test]
fn test_dir_is_empty() {
    let is_empty = dir_is_empty(&"./test".to_string());
    assert!(!is_empty);
    let non_existent = dir_is_empty(&"./non_existent_dir".to_string());
    assert!(!non_existent);
}

#[test]
fn test_get_config_path() {
    let expected = get_config_path(&"foo".to_string()).unwrap();
    let mut actual = env::home_dir().unwrap().to_str().unwrap().to_string();
    actual.push_str("/.skeleton/foo.toml");
    assert_eq!(actual, expected);
}
<|endoftext|>


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

/* TODO:
 *  * redirect root url
 *  * add watermark? url to repo?
 *  * specify root node
 *  * update git repo?
 *  * serverside caching? redis?
 */

use std::collections::{HashMap, HashSet};
use std::env;
use std::io::{Write, Read};
use std::process::{Command, Stdio};

use tiny_http::{Header, Response};

extern crate crates_index;
extern crate tiny_http;

static INDEX_LOCAL_PATH: &'static str = "crates.io-index";

fn build_dot(crate_name: &str, dep_map: &HashMap<String, Vec<String>>) -> Vec<u8> {
    let mut crate_names = vec![crate_name];

    let mut dot = String::new();
    dot.push_str("digraph graphname {");
    dot.push_str("ratio=0.75;");

    // Which dependencies we've already seen
    let mut seen_set = HashSet::new();

    while let Some(crate_name) = crate_names.pop() {
        if seen_set.contains(crate_name as &str) {
            continue;
        }
        seen_set.insert(crate_name);
        for crate_dep in dep_map.get(crate_name).unwrap() {
            dot.push_str(&format!("\"{}\" -> \"{}\";", crate_name, crate_dep));
            if !seen_set.contains(crate_dep as &str) {
                crate_names.push(crate_dep);
            }
        }
    }
    dot.push_str("}");

    let child = Command::new("dot").arg("-Tpng").stdin(Stdio::piped()).stdout(Stdio::piped()).spawn().unwrap();
    child.stdin.unwrap().write_all(dot.as_bytes()).unwrap();

    let mut ret = vec![];
    child.stdout.unwrap().read_to_end(&mut ret).unwrap();
    ret
}

fn main() {
    let index = crates_index::CratesIndex::new(INDEX_LOCAL_PATH.into());
    if !index.exists() {
        println!("Cloning crates.io-index");
        index.clone_index();
    }

    let dep_map = index.dependency_map();

    let port = match env::var("PORT") {
        Ok(p) => p.parse::<u16>().unwrap(),
        Err(..) => 8000,
    };

    let server = tiny_http::ServerBuilder::new().with_port(port).build().unwrap();

    println!("Server listening on port {}", port);
    for req in server.incoming_requests() {
        let response = {
            let crate_name = req.url().trim_left_matches("/");
            if dep_map.get(crate_name).is_some() {
                let data = build_dot(crate_name, &dep_map);
                let content_type_header = "Content-Type: image/png".parse::<Header>().unwrap();
                let cache_control_header = "cache-control: no-cache".parse::<Header>().unwrap();
                Response::from_data(data).with_header(content_type_header)
                                         .with_header(cache_control_header)
            } else {
                Response::from_string("could not find crate").with_status_code(400)
            }
        };
        req.respond(response);
    }
}
<commit_msg>Explicitly specify root node<commit_after>// Copyright 2015 Corey Farwell
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/* TODO:
 *  * redirect root url
 *  * add watermark? url to repo?
 *  * update git repo?
 *  * serverside caching? redis?
 */

use std::collections::{HashMap, HashSet};
use std::env;
use std::io::{Write, Read};
use std::process::{Command, Stdio};

use tiny_http::{Header, Response};

extern crate crates_index;
extern crate tiny_http;

static INDEX_LOCAL_PATH: &'static str = "crates.io-index";

fn build_dot(crate_name: &str, dep_map: &HashMap<String, Vec<String>>) -> Vec<u8> {
    let mut crate_names = vec![crate_name];

    let mut dot = String::new();
    dot.push_str("digraph graphname {");
    dot.push_str("ratio=0.75;");

    dot.push_str(&format!("\"{}\" [root=true]", crate_name));

    // Which dependencies we've already seen
    let mut seen_set = HashSet::new();

    while let Some(crate_name) = crate_names.pop() {
        if seen_set.contains(crate_name as &str) {
            continue;
        }
        seen_set.insert(crate_name);
        for crate_dep in dep_map.get(crate_name).unwrap() {
            dot.push_str(&format!("\"{}\" -> \"{}\";", crate_name, crate_dep));
            if !seen_set.contains(crate_dep as &str) {
                crate_names.push(crate_dep);
            }
        }
    }
    dot.push_str("}");

    let child = Command::new("dot").arg("-Tpng").stdin(Stdio::piped()).stdout(Stdio::piped()).spawn().unwrap();
    child.stdin.unwrap().write_all(dot.as_bytes()).unwrap();

    let mut ret = vec![];
    child.stdout.unwrap().read_to_end(&mut ret).unwrap();
    ret
}

fn main() {
    let index = crates_index::CratesIndex::new(INDEX_LOCAL_PATH.into());
    if !index.exists() {
        println!("Cloning crates.io-index");
        index.clone_index();
    }

    let dep_map = index.dependency_map();

    let port = match env::var("PORT") {
        Ok(p) => p.parse::<u16>().unwrap(),
        Err(..) => 8000,
    };

    let server = tiny_http::ServerBuilder::new().with_port(port).build().unwrap();

    println!("Server listening on port {}", port);
    for req in server.incoming_requests() {
        let response = {
            let crate_name = req.url().trim_left_matches("/");
            if dep_map.get(crate_name).is_some() {
                let data = build_dot(crate_name, &dep_map);
                let content_type_header = "Content-Type: image/png".parse::<Header>().unwrap();
                let cache_control_header = "cache-control: no-cache".parse::<Header>().unwrap();
                Response::from_data(data).with_header(content_type_header)
                                         .with_header(cache_control_header)
            } else {
                Response::from_string("could not find crate").with_status_code(400)
            }
        };
        req.respond(response);
    }
}
<|endoftext|>


<commit_before>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate box2d;

use piston::window::WindowSettings;
use piston::event_loop::*;
use piston::input::*;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{GlGraphics, OpenGL};
use box2d::b2;

pub struct App {
    gl: GlGraphics, // OpenGL drawing backend.
    world: b2::World,
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
        const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];

        let ref world = self.world;
        self.gl.draw(args.viewport(), |c, gl| {
            clear(GREEN, gl);

            for (_, b) in world.bodies() {
                let ref body = (*b.borrow());
                let body_type = body.body_type();
                let fixtures = body.fixtures();
                // let position = body.position;
            }
        });
        //         let square = rectangle::square(0.0, 0.0, 50.0);
        // let rotation = self.rotation;
        // let (x, y) = ((args.width / 2) as f64, (args.height / 2) as f64);

        // let transform = c.transform
        // .trans(x, y)
        // .rot_rad(rotation)
        // .trans(-25.0, -25.0);
        //
        // Draw a box rotating around the middle of the screen.
        // rectangle(RED, square, transform, gl);
        // });
        //
    }

    fn update(&mut self, args: &UpdateArgs) {
        // Rotate 2 radians per second.
        self.world.step(args.dt as f32, 8, 3);
    }
}

fn new_world() -> b2::World {
    let mut world = b2::World::new(&b2::Vec2 { x: 0.0, y: 2.0 });

    let mut b_def = b2::BodyDef::new();
    b_def.body_type = b2::BodyType::Static;
    b_def.position = b2::Vec2 { x: 0., y: -10. };

    let mut ground_box = b2::PolygonShape::new();
    ground_box.set_as_box(20., 1.);

    let ground_handle = world.create_body(&b_def);
    world.get_body_mut(ground_handle)
         .create_fast_fixture(&ground_box, 0.);

    let mut b_def = b2::BodyDef::new();
    b_def.body_type = b2::BodyType::Dynamic;
    b_def.position = b2::Vec2 { x: -20., y: 20. };

    let mut cube_shape = b2::PolygonShape::new();
    cube_shape.set_as_box(1., 1.);

    let mut circle_shape = b2::CircleShape::new();
    circle_shape.set_radius(1.);

    let mut f_def = b2::FixtureDef::new();
    f_def.density = 1.;
    f_def.restitution = 0.2;
    f_def.friction = 0.3;

    b_def.position.x += 0.5;
    if b_def.position.x > 20. {
        b_def.position.x = -20.;
    }
    let handle = world.create_body(&b_def);
    world.get_body_mut(handle)
         .create_fixture(&circle_shape, &mut f_def);

    return world;
}

fn main() {
    // Change this to OpenGL::V2_1 if not working.
    let opengl = OpenGL::V3_2;

    // Create an Glutin window.
    let mut window: Window = WindowSettings::new("box2d", [200, 200])
                                 .opengl(opengl)
                                 .exit_on_esc(true)
                                 .build()
                                 .unwrap();

    // Create a new game and run it.
    let mut app = App {
        gl: GlGraphics::new(opengl),
        world: new_world(),
    };

    let mut events = window.events();
    while let Some(e) = events.next(&mut window) {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }

        if let Some(u) = e.update_args() {
            app.update(&u);
        }
    }
}
<commit_msg>Drawing simple bodies with gl<commit_after>extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate box2d;

use piston::window::WindowSettings;
use piston::event_loop::*;
use piston::input::*;
use glutin_window::GlutinWindow as Window;
use opengl_graphics::{GlGraphics, OpenGL};
use box2d::b2;

pub struct App {
    gl: GlGraphics,
    world: b2::World,
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        const GREEN: [f32; 4] = [0.0, 1.0, 0.0, 1.0];
        const RED: [f32; 4] = [1.0, 0.0, 0.0, 1.0];
        const BLACK: [f32; 4] = [0.0, 0.0, 0.0, 1.0];

        let ref world = self.world;
        self.gl.draw(args.viewport(), |c, gl| {
            clear(GREEN, gl);

            for (_, b) in world.bodies() {
                let body = b.borrow();
                let position = (*body).position();
                let angle = (*body).angle();

                let transform = c.transform
                                 .trans((args.width as f64 * 0.5), (args.height as f64 * 0.5))
                                 .scale(2.0, 2.0)
                                 .trans(position.x as f64, position.y as f64)
                                 .rot_deg(angle as f64);

                let square = rectangle::square(0.0, 0.0, 50.0);

                for (_, f) in body.fixtures() {
                    let fixture = f.borrow();
                    let shape = (*fixture).shape();

                    match *shape {
                        b2::UnknownShape::Circle(ref s) => {
                            let p = s.position();
                            let r = s.radius() as f64;
                            let extent = rectangle::square(p.x as f64 - r / 2.0,
                                                           p.y as f64 - r / 2.0,
                                                           r);
                            Ellipse::new(RED).draw(extent, default_draw_state(), transform, gl);
                        }
                        b2::UnknownShape::Polygon(ref s) => {
                            rectangle(BLACK, square, transform, gl);
                        }
                        _ => (),
                    }

                }
            }
        });
        //         let square = rectangle::square(0.0, 0.0, 50.0);
        // let rotation = self.rotation;
        // let (x, y) = ((args.width / 2) as f64, (args.height / 2) as f64);

        // let transform = c.transform
        // .trans(x, y)
        // .rot_rad(rotation)
        // .trans(-25.0, -25.0);
        //
        // Draw a box rotating around the middle of the screen.
        //
        // });
        //
    }

    fn update(&mut self, args: &UpdateArgs) {
        // Rotate 2 radians per second.
        self.world.step(args.dt as f32, 8, 3);
    }
}

fn new_world() -> b2::World {
    let mut world = b2::World::new(&b2::Vec2 { x: 0.0, y: 2.0 });

    let mut b_def = b2::BodyDef::new();
    b_def.body_type = b2::BodyType::Static;
    b_def.position = b2::Vec2 { x: 0., y: -10. };

    let mut ground_box = b2::PolygonShape::new();
    ground_box.set_as_box(20., 1.);

    let ground_handle = world.create_body(&b_def);
    world.get_body_mut(ground_handle)
         .create_fast_fixture(&ground_box, 0.);

    let mut b_def = b2::BodyDef::new();
    b_def.body_type = b2::BodyType::Dynamic;
    b_def.position = b2::Vec2 { x: -20., y: 20. };

    let mut cube_shape = b2::PolygonShape::new();
    cube_shape.set_as_box(1., 1.);

    let mut circle_shape = b2::CircleShape::new();
    circle_shape.set_radius(1.);

    let mut f_def = b2::FixtureDef::new();
    f_def.density = 1.;
    f_def.restitution = 0.2;
    f_def.friction = 0.3;

    b_def.position.x += 0.5;
    if b_def.position.x > 20. {
        b_def.position.x = -20.;
    }
    let handle = world.create_body(&b_def);
    world.get_body_mut(handle)
         .create_fixture(&circle_shape, &mut f_def);

    return world;
}

fn main() {
    // Change this to OpenGL::V2_1 if not working.
    let opengl = OpenGL::V3_2;

    // Create an Glutin window.
    let mut window: Window = WindowSettings::new("box2d", [200, 200])
                                 .opengl(opengl)
                                 .exit_on_esc(true)
                                 .build()
                                 .unwrap();

    // Create a new game and run it.
    let mut app = App {
        gl: GlGraphics::new(opengl),
        world: new_world(),
    };

    let mut events = window.events();
    while let Some(e) = events.next(&mut window) {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }

        if let Some(u) = e.update_args() {
            app.update(&u);
        }
    }
}
<|endoftext|>