<commit_before>use std::io::stdin;
use std::rand;
use std::rand::RngUtil;
use std::num::abs;
use std::int;

fn generate_secret_number() -> int {
  return abs(rand::rng().gen::<int>() % 100) + 1;
}

fn process_guess(secret: int, guess: int) -> bool {
  println(fmt!("You guessed: %d", guess));

  if guess > secret {
    println("Your guess was too high!");
    false
  } else if guess < secret {
    println("Your guess was too low!");
    false
  } else {
    println("You got it!");
    true
  }
}

fn main() {
  let secret = generate_secret_number();

  println("--- N U M B E R - G A M E ---");
  println("");
  println("Guess a number from 1-100 (you get five tries):");

  for round in range(1, 6) {
    println(fmt!("Guess #%d", round));

    let input = stdin().read_line();

    match int::from_str(input) {
      Some(number) => {
        if process_guess(secret, number) { break; }
      },
      None         => println("Hey, put in a number.")
    }
  }

  println("Done!");
}
<commit_msg>Better way to generate a random number between 1 and 100<commit_after>use std::io::stdin;
use std::rand;
use std::rand::RngUtil;
use std::uint;

fn generate_secret_number() -> uint {
  rand::rng().gen_uint_range(1, 100)
}

fn process_guess(secret: uint, guess: uint) -> bool {
  println(fmt!("You guessed: %u", guess));

  if guess > secret {
    println("Your guess was too high!");
    false
  } else if guess < secret {
    println("Your guess was too low!");
    false
  } else {
    println("You got it!");
    true
  }
}

fn main() {
  let secret = generate_secret_number();

  println("--- N U M B E R - G A M E ---");
  println("");
  println("Guess a number from 1-100 (you get five tries):");

  for round in range(1, 6) {
    println(fmt!("Guess #%d", round));

    let input = stdin().read_line();

    match uint::from_str(input) {
      Some(number) => {
        if process_guess(secret, number) { break; }
      },
      None         => println("Hey, put in a number.")
    }
  }

  println("Done!");
}
<|endoftext|>


<commit_before>/* The Wizards' Wallet
 * Written in 2014 by
 *   Andrew Poelstra <apoelstra@wpsoftware.net>
 *
 * To the extent possible under law, the author(s) have dedicated all
 * copyright and related and neighboring rights to this software to
 * the public domain worldwide. This software is distributed without
 * any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication
 * along with this software.
 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
 */

//! # Coinjoin Server
//!
//! Functions and data to manage a centralized coinjoin server.

use std::collections::{HashMap, TreeMap};
use std::num::from_str_radix;
use std::io::IoResult;
use std::rand::{Rng, SeedableRng};
use std::time::Duration;
use num::integer::div_mod_floor;
use serialize::json;
use serialize::{Decodable, Decoder, Encodable, Encoder};
use time::precise_time_ns;

use bitcoin::blockdata::transaction::Transaction;
use bitcoin::blockdata::utxoset::UtxoSet;
use bitcoin::network::serialize::serialize_hex;
use crypto::fortuna::Fortuna;

use coinjoin::{CoinjoinError, DuplicateInput, NonZeroLocktime,
               NoTargetOutput, UnknownInput, UnknownVersion};

/// Current state of the session
#[deriving(PartialEq, Eq, PartialOrd, Ord, Show)]
pub enum SessionState {
  /// Collecting unsigned transactions
  Joining,
  /// Collecting signed transactions
  Merging,
  /// Completed successfully
  Complete,
  /// Timed out waiting on signed transactions
  Expired,
  /// Failed (input spent out from under it)
  Failed
}

impl json::ToJson for SessionState {
  fn to_json(&self) -> json::Json {
    json::String(match *self {
      Joining => "joining",
      Merging => "merging",
      Complete => "complete",
      Expired => "expired",
      Failed => "failed"
    }.to_string())
  }
}

/// A Coinjoin session
pub struct Session {
  id: SessionId,
  rng: Fortuna,
  state: SessionState,
  // Time at which last state switch occured
  switch_time: u64,
  // Duration of "collecting unsigned transactions" phase
  join_duration: Duration,
  // Duration of every other phase before we expire or delete the session
  expiry_duration: Duration,
  target_value: u64,
  unsigned: Vec<Transaction>,
  merged: Option<Transaction>
}

impl json::ToJson for Session {
  fn to_json(&self) -> json::Json {
    let (secs, nanos) = div_mod_floor(precise_time_ns() - self.switch_time, 1_000_000_000);
    let time_since_switch = Duration::seconds(secs as i32) + Duration::nanoseconds(nanos as i32);

    let mut obj = TreeMap::new();
    obj.insert("id".to_string(), self.id.to_json());
    obj.insert("state".to_string(), self.state.to_json());
    obj.insert("join_duration".to_string(), self.join_duration.num_milliseconds().to_json());
    obj.insert("merge_duration".to_string(), self.expiry_duration.num_milliseconds().to_json());
    if self.state == Merging {
      obj.insert("merged_tx".to_string(), json::String(serialize_hex(self.merged.get_ref()).unwrap()));
    }
    if self.state == Joining {
      obj.insert("time_until_merge".to_string(),
                 (self.join_duration + time_since_switch).num_milliseconds().to_json());
    } else {
      obj.insert("time_until_expiry".to_string(),
                 (self.expiry_duration + time_since_switch).num_milliseconds().to_json());
    }
    obj.insert("target_value".to_string(), self.target_value.to_json());
    json::Object(obj)
  }
}

/// A session identifier
#[deriving(Hash, PartialEq, Eq, Clone, Show)]
pub struct SessionId(u64);

impl<E: Encoder<S>, S> Encodable<E, S> for SessionId {
  fn encode(&self, e: &mut E) -> Result<(), S> {
    let &SessionId(num) = self;
    e.emit_str(format!("{:08x}", num).as_slice())
  }
}

impl<D: Decoder<E>, E> Decodable<D, E> for SessionId {
  fn decode(d: &mut D) -> Result<SessionId, E> {
    let st = try!(d.read_str());
    match from_str_radix(st.as_slice(), 16) {
      Some(n) => Ok(SessionId(n)),
      None    => Err(d.error("Session ID was not a valid hex string"))
    }
  }
}

impl json::ToJson for SessionId {
  fn to_json(&self) -> json::Json {
    let &SessionId(num) = self;
    json::String(format!("{:08x}", num))
  }
}

impl Session {
  /// Creates a new session with a random ID
  pub fn new(target_value: u64,
             join_duration: Duration,
             expiry_duration: Duration)
             -> IoResult<Session> {
    use std::rand;
    let mut csrng: Fortuna = {
      let mut rng = try!(rand::OsRng::new());
      let mut seed = [0, ..256];
      rng.fill_bytes(seed.as_mut_slice());
      SeedableRng::from_seed(seed.as_slice())
    };
    let id = SessionId(csrng.gen());
    Ok(Session {
      id: id,
      rng: csrng,
      target_value: target_value,
      state: Joining,
      switch_time: precise_time_ns(),
      join_duration: join_duration,
      expiry_duration: expiry_duration,
      unsigned: vec![],
      merged: None
    })
  }

  /// Retrieves the immutable ID of the session
  pub fn id(&self) -> SessionId {
    self.id
  }

  /// Adds a transaction to a coinjoin session
  pub fn add_transaction(&mut self, tx: &Transaction, utxo_set: &UtxoSet)
                         -> Result<(), CoinjoinError> {
    // Check for version, locktime
    if tx.version != 1 {
      return Err(UnknownVersion(tx.version as uint));
    }
    if tx.lock_time != 0 {
      return Err(NonZeroLocktime(tx.lock_time as uint));
    }

    // Check for output of the correct size
    if !tx.output.iter().any(|o| o.value == self.target_value) {
      return Err(NoTargetOutput(self.target_value));
    }
    // Check that we know all the inputs, and that they have
    // not already been used in this join
    for input in tx.input.iter() {
      if utxo_set.get_utxo(input.prev_hash, input.prev_index).is_none() {
        return Err(UnknownInput(input.prev_hash, input.prev_index as uint));
      }
      for other_tx in self.unsigned.iter() {
        for other_input in other_tx.input.iter() {
          if input.prev_hash  == other_input.prev_hash &&
             input.prev_index == other_input.prev_index {
            return Err(DuplicateInput(input.prev_hash, input.prev_index as uint));
          }
        }
      }
    }
    // All Ok, add it
    self.unsigned.push(tx.clone());
    Ok(())
  }

  // Merges all the transactions. Shouldn't be public, this should require
  // setting the status to `Merging`
  fn merge_transactions(&mut self) {
    let mut merged = Transaction {
      version: 1,
      lock_time: 0,
      input: Vec::with_capacity(
        self.unsigned.iter().fold(0, |acc, tx| acc + tx.input.len())),
      output: Vec::with_capacity(
        self.unsigned.iter().fold(0, |acc, tx| acc + tx.output.len())),
    };

    // We validated inputs and outputs when bringing them in
    for tx in self.unsigned.iter() {
      merged.input.push_all(tx.input.as_slice());

      // When adding outputs, check for dupes and consolitate them
      for out in tx.output.iter() {
        let mut already_exists = false;
        for existing_out in merged.output.mut_iter() {
          if existing_out.script_pubkey == out.script_pubkey {
            existing_out.value += out.value;
            already_exists = true;
          }
        }
        if !already_exists {
          merged.output.push(out.clone());
        }
      }
    }

    // TODO: Randomize DER encoding

    // Randomize the input and output order
    self.rng.shuffle(merged.input.as_mut_slice());
    self.rng.shuffle(merged.output.as_mut_slice());

    self.merged = Some(merged);
  }
}

/// A Coinjoin session manager
pub struct Server {
  sessions: HashMap<SessionId, Box<Session>>,
  current: *mut Session
}

impl Server {
  /// Construct a new session manager
  pub fn new() -> Server {
    Server {
      sessions: HashMap::new(),
      current: RawPtr::null()
    }
  }

  /// Retrieves the current session, or None if there is not one
  pub fn current_session<'a>(&'a self) -> Option<&'a Session> {
    unsafe { self.current.to_option() }
  }

  /// Retrieves the current session, or None if there is not one
  pub fn current_session_mut<'a>(&'a mut self) -> Option<&'a mut Session> {
    unsafe { if self.current.is_not_null() { Some(&mut *self.current) } else { None } }
  }

  /// Retrieves a specified session, or None if it is not available
  pub fn session<'a>(&'a self, key: &SessionId) -> Option<&'a Session> {
    self.sessions.find(key).map(|r| &**r)
  }

  /// Retrieves a specified session, or None if it is not available
  pub fn session_mut<'a>(&'a mut self, key: &SessionId) -> Option<&'a mut Session> {
    self.sessions.find_mut(key).map(|r| &mut **r)
  }

  /// Sets the current session
  pub fn set_current_session(&mut self, sess: Session) {
    let boxed = box sess;
    let raw = &*boxed as *const _ as *mut _;
    self.sessions.insert(boxed.id, boxed);
    self.current = raw;
  }

  /// Updates all sessions
  pub fn update_all(&mut self) {
    let now = precise_time_ns();

    let mut keys_to_delete = Vec::new();

    // Run through list, updating session states
    for (key, session) in self.sessions.mut_iter() {
      let (secs, nanos) = div_mod_floor(now - session.switch_time, 1_000_000_000);
      let time_since_switch = Duration::seconds(secs as i32) + Duration::nanoseconds(nanos as i32);

      match session.state {
        Joining => {
          if time_since_switch > session.join_duration {
            session.state = Merging;
            session.switch_time = now;
            session.merge_transactions();
          }
        }
        state => {
          if time_since_switch > session.expiry_duration {
            session.state = match state {
              Joining => unreachable!(),
              Merging => Expired,
              Complete | Expired | Failed => { keys_to_delete.push(*key); Expired }
            };
            session.switch_time = now;
          }
        }
      }
    }
    // Delete any old sessions
    for key in keys_to_delete.iter() {
      unsafe {
        if (*self.current).id == *key {
          self.current = RawPtr::null();
        }
      }
      self.sessions.remove(key);
    }
  }
}

<commit_msg>Refuse to merge if < 2 txes are present<commit_after>/* The Wizards' Wallet
 * Written in 2014 by
 *   Andrew Poelstra <apoelstra@wpsoftware.net>
 *
 * To the extent possible under law, the author(s) have dedicated all
 * copyright and related and neighboring rights to this software to
 * the public domain worldwide. This software is distributed without
 * any warranty.
 *
 * You should have received a copy of the CC0 Public Domain Dedication
 * along with this software.
 * If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
 */

//! # Coinjoin Server
//!
//! Functions and data to manage a centralized coinjoin server.

use std::collections::{HashMap, TreeMap};
use std::num::from_str_radix;
use std::io::IoResult;
use std::rand::{Rng, SeedableRng};
use std::time::Duration;
use num::integer::div_mod_floor;
use serialize::json;
use serialize::{Decodable, Decoder, Encodable, Encoder};
use time::precise_time_ns;

use bitcoin::blockdata::transaction::Transaction;
use bitcoin::blockdata::utxoset::UtxoSet;
use bitcoin::network::serialize::serialize_hex;
use crypto::fortuna::Fortuna;

use coinjoin::{CoinjoinError, DuplicateInput, NonZeroLocktime,
               NoTargetOutput, UnknownInput, UnknownVersion};

/// Current state of the session
#[deriving(PartialEq, Eq, PartialOrd, Ord, Show)]
pub enum SessionState {
  /// Collecting unsigned transactions
  Joining,
  /// Collecting signed transactions
  Merging,
  /// Completed successfully
  Complete,
  /// Timed out waiting on signed transactions
  Expired,
  /// Failed (input spent out from under it)
  Failed,
  /// Failed (not enough inputs)
  Unmerged
}

impl json::ToJson for SessionState {
  fn to_json(&self) -> json::Json {
    json::String(match *self {
      Joining => "joining",
      Merging => "merging",
      Complete => "complete",
      Expired => "expired",
      Failed => "failed",
      Unmerged => "unmerged"
    }.to_string())
  }
}

/// A Coinjoin session
pub struct Session {
  id: SessionId,
  rng: Fortuna,
  state: SessionState,
  // Time at which last state switch occured
  switch_time: u64,
  // Duration of "collecting unsigned transactions" phase
  join_duration: Duration,
  // Duration of every other phase before we expire or delete the session
  expiry_duration: Duration,
  target_value: u64,
  unsigned: Vec<Transaction>,
  merged: Option<Transaction>
}

impl json::ToJson for Session {
  fn to_json(&self) -> json::Json {
    let (secs, nanos) = div_mod_floor(precise_time_ns() - self.switch_time, 1_000_000_000);
    let time_since_switch = Duration::seconds(secs as i32) + Duration::nanoseconds(nanos as i32);

    let mut obj = TreeMap::new();
    obj.insert("id".to_string(), self.id.to_json());
    obj.insert("state".to_string(), self.state.to_json());
    obj.insert("join_duration".to_string(), self.join_duration.num_milliseconds().to_json());
    obj.insert("merge_duration".to_string(), self.expiry_duration.num_milliseconds().to_json());
    if self.state == Merging {
      obj.insert("merged_tx".to_string(), json::String(serialize_hex(self.merged.get_ref()).unwrap()));
    }
    if self.state == Joining {
      obj.insert("time_until_merge".to_string(),
                 (self.join_duration - time_since_switch).num_milliseconds().to_json());
    } else {
      obj.insert("time_until_expiry".to_string(),
                 (self.expiry_duration - time_since_switch).num_milliseconds().to_json());
    }
    obj.insert("target_value".to_string(), self.target_value.to_json());
    json::Object(obj)
  }
}

/// A session identifier
#[deriving(Hash, PartialEq, Eq, Clone, Show)]
pub struct SessionId(u64);

impl<E: Encoder<S>, S> Encodable<E, S> for SessionId {
  fn encode(&self, e: &mut E) -> Result<(), S> {
    let &SessionId(num) = self;
    e.emit_str(format!("{:08x}", num).as_slice())
  }
}

impl<D: Decoder<E>, E> Decodable<D, E> for SessionId {
  fn decode(d: &mut D) -> Result<SessionId, E> {
    let st = try!(d.read_str());
    match from_str_radix(st.as_slice(), 16) {
      Some(n) => Ok(SessionId(n)),
      None    => Err(d.error("Session ID was not a valid hex string"))
    }
  }
}

impl json::ToJson for SessionId {
  fn to_json(&self) -> json::Json {
    let &SessionId(num) = self;
    json::String(format!("{:08x}", num))
  }
}

impl Session {
  /// Creates a new session with a random ID
  pub fn new(target_value: u64,
             join_duration: Duration,
             expiry_duration: Duration)
             -> IoResult<Session> {
    use std::rand;
    let mut csrng: Fortuna = {
      let mut rng = try!(rand::OsRng::new());
      let mut seed = [0, ..256];
      rng.fill_bytes(seed.as_mut_slice());
      SeedableRng::from_seed(seed.as_slice())
    };
    let id = SessionId(csrng.gen());
    Ok(Session {
      id: id,
      rng: csrng,
      target_value: target_value,
      state: Joining,
      switch_time: precise_time_ns(),
      join_duration: join_duration,
      expiry_duration: expiry_duration,
      unsigned: vec![],
      merged: None
    })
  }

  /// Retrieves the immutable ID of the session
  pub fn id(&self) -> SessionId {
    self.id
  }

  /// Adds a transaction to a coinjoin session
  pub fn add_transaction(&mut self, tx: &Transaction, utxo_set: &UtxoSet)
                         -> Result<(), CoinjoinError> {
    // Check for version, locktime
    if tx.version != 1 {
      return Err(UnknownVersion(tx.version as uint));
    }
    if tx.lock_time != 0 {
      return Err(NonZeroLocktime(tx.lock_time as uint));
    }

    // Check for output of the correct size
    if !tx.output.iter().any(|o| o.value == self.target_value) {
      return Err(NoTargetOutput(self.target_value));
    }
    // Check that we know all the inputs, and that they have
    // not already been used in this join
    for input in tx.input.iter() {
      if utxo_set.get_utxo(input.prev_hash, input.prev_index).is_none() {
        return Err(UnknownInput(input.prev_hash, input.prev_index as uint));
      }
      for other_tx in self.unsigned.iter() {
        for other_input in other_tx.input.iter() {
          if input.prev_hash  == other_input.prev_hash &&
             input.prev_index == other_input.prev_index {
            return Err(DuplicateInput(input.prev_hash, input.prev_index as uint));
          }
        }
      }
    }
    // All Ok, add it
    self.unsigned.push(tx.clone());
    Ok(())
  }

  // Merges all the transactions. Shouldn't be public, this should require
  // setting the status to `Merging`
  fn merge_transactions(&mut self) {
    let mut merged = Transaction {
      version: 1,
      lock_time: 0,
      input: Vec::with_capacity(
        self.unsigned.iter().fold(0, |acc, tx| acc + tx.input.len())),
      output: Vec::with_capacity(
        self.unsigned.iter().fold(0, |acc, tx| acc + tx.output.len())),
    };

    // We validated inputs and outputs when bringing them in
    for tx in self.unsigned.iter() {
      merged.input.push_all(tx.input.as_slice());

      // When adding outputs, check for dupes and consolitate them
      for out in tx.output.iter() {
        let mut already_exists = false;
        for existing_out in merged.output.mut_iter() {
          if existing_out.script_pubkey == out.script_pubkey {
            existing_out.value += out.value;
            already_exists = true;
          }
        }
        if !already_exists {
          merged.output.push(out.clone());
        }
      }
    }

    // TODO: Randomize DER encoding

    // Randomize the input and output order
    self.rng.shuffle(merged.input.as_mut_slice());
    self.rng.shuffle(merged.output.as_mut_slice());

    self.merged = Some(merged);
  }
}

/// A Coinjoin session manager
pub struct Server {
  sessions: HashMap<SessionId, Box<Session>>,
  current: *mut Session
}

impl Server {
  /// Construct a new session manager
  pub fn new() -> Server {
    Server {
      sessions: HashMap::new(),
      current: RawPtr::null()
    }
  }

  /// Retrieves the current session, or None if there is not one
  pub fn current_session<'a>(&'a self) -> Option<&'a Session> {
    unsafe { self.current.to_option() }
  }

  /// Retrieves the current session, or None if there is not one
  pub fn current_session_mut<'a>(&'a mut self) -> Option<&'a mut Session> {
    unsafe { if self.current.is_not_null() { Some(&mut *self.current) } else { None } }
  }

  /// Retrieves a specified session, or None if it is not available
  pub fn session<'a>(&'a self, key: &SessionId) -> Option<&'a Session> {
    self.sessions.find(key).map(|r| &**r)
  }

  /// Retrieves a specified session, or None if it is not available
  pub fn session_mut<'a>(&'a mut self, key: &SessionId) -> Option<&'a mut Session> {
    self.sessions.find_mut(key).map(|r| &mut **r)
  }

  /// Sets the current session
  pub fn set_current_session(&mut self, sess: Session) {
    let boxed = box sess;
    let raw = &*boxed as *const _ as *mut _;
    self.sessions.insert(boxed.id, boxed);
    self.current = raw;
  }

  /// Updates all sessions
  pub fn update_all(&mut self) {
    let now = precise_time_ns();

    let mut keys_to_delete = Vec::new();

    // Run through list, updating session states
    for (key, session) in self.sessions.mut_iter() {
      let (secs, nanos) = div_mod_floor(now - session.switch_time, 1_000_000_000);
      let time_since_switch = Duration::seconds(secs as i32) + Duration::nanoseconds(nanos as i32);

      match session.state {
        Joining => {
          if time_since_switch > session.join_duration {
            if session.unsigned.len() > 1 {
              session.state = Merging;
              session.merge_transactions();
            } else {
              session.state = Unmerged;
            }
            session.switch_time = now;
          }
        }
        state => {
          if time_since_switch > session.expiry_duration {
            session.state = match state {
              Joining => unreachable!(),
              Merging => Expired,
              Complete | Expired | Failed | Unmerged => { keys_to_delete.push(*key); Expired }
            };
            session.switch_time = now;
          }
        }
      }
    }
    // Delete any old sessions
    for key in keys_to_delete.iter() {
      unsafe {
        if (*self.current).id == *key {
          self.current = RawPtr::null();
        }
      }
      self.sessions.remove(key);
    }
  }
}

<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc;

// #[cfg(test)]
// extern crate time;
//
// #[cfg(test)]
// fn mark_time(i:usize, bounds: (usize, usize), s_time: time::PreciseTime){
//     #[cfg(test)]
//     println!("Thread: {}, Bounds:({}, {}), time: {}", i, bounds.0, bounds.1, s_time.to(time::PreciseTime::now()));
// }

pub fn to_concurrent_on_section<T, SeqF>(seq_fun: SeqF,
            min_num: usize, max_num: usize, threads: usize, from_zero_speed_factor: usize) -> Vec<T>
            where
                T: Clone + Send + 'static,
                SeqF: Send + Sync + Copy + 'static + Fn(usize, usize) -> Vec<T>, {

    let mut res_vec:  Vec<Vec<T>> = vec![vec![]; threads];
    let (start_seg_end, seg_size) = match min_num{
        0 => {
            let seg_size = (max_num)/(threads*from_zero_speed_factor);
            (max_num - seg_size*(threads-1), seg_size)
        },
        _ => {
            let range = max_num - min_num;
            let seg_size = range/threads;
            (min_num + seg_size + range%threads, seg_size)
        },
    };

    let (tx, rx) = mpsc::channel();
    //
    // #[cfg(test)]
    // let start = time::PreciseTime::now();
    { //First section.
        let (tx, min, max) = (tx.clone(), min_num, start_seg_end);
        thread::spawn( move || {
            let to_send = match max-min{
                0 => vec![],
                _ => seq_fun(min, max),
            };
            //
            // #[cfg(test)]
            // mark_time(0, (min, max), start);
            //
            // tx.send((0, to_send)).unwrap();
        });
    }
    for i in 1..threads{
        let (tx, min, max) = (tx.clone(), start_seg_end + seg_size*(i-1),
                                start_seg_end + seg_size*i);
        thread::spawn( move || {
            let to_send = match max-min{
                0 => vec![],
                _ => seq_fun(min, max),
            };
            //
            // #[cfg(test)]
            // mark_time(i, (min, max), start);

            tx.send((i, to_send)).unwrap();
        });
    }

    for _ in 0..threads{
        let (i, p_sec) = match rx.recv(){
            Ok(mes) => mes,
            Err(e) => panic!(e.to_string()),
        };
        res_vec[i] = p_sec;
    }
    res_vec.concat()
}
<commit_msg>Commented out functionality!<commit_after>use std::thread;
use std::sync::mpsc;

// #[cfg(test)]
// extern crate time;
//
// #[cfg(test)]
// fn mark_time(i:usize, bounds: (usize, usize), s_time: time::PreciseTime){
//     #[cfg(test)]
//     println!("Thread: {}, Bounds:({}, {}), time: {}", i, bounds.0, bounds.1, s_time.to(time::PreciseTime::now()));
// }

pub fn to_concurrent_on_section<T, SeqF>(seq_fun: SeqF,
            min_num: usize, max_num: usize, threads: usize, from_zero_speed_factor: usize) -> Vec<T>
            where
                T: Clone + Send + 'static,
                SeqF: Send + Sync + Copy + 'static + Fn(usize, usize) -> Vec<T>, {

    let mut res_vec:  Vec<Vec<T>> = vec![vec![]; threads];
    let (start_seg_end, seg_size) = match min_num{
        0 => {
            let seg_size = (max_num)/(threads*from_zero_speed_factor);
            (max_num - seg_size*(threads-1), seg_size)
        },
        _ => {
            let range = max_num - min_num;
            let seg_size = range/threads;
            (min_num + seg_size + range%threads, seg_size)
        },
    };

    let (tx, rx) = mpsc::channel();
    //
    // #[cfg(test)]
    // let start = time::PreciseTime::now();
    { //First section.
        let (tx, min, max) = (tx.clone(), min_num, start_seg_end);
        thread::spawn( move || {
            let to_send = match max-min{
                0 => vec![],
                _ => seq_fun(min, max),
            };
            //
            // #[cfg(test)]
            // mark_time(0, (min, max), start);

            tx.send((0, to_send)).unwrap();
        });
    }
    for i in 1..threads{
        let (tx, min, max) = (tx.clone(), start_seg_end + seg_size*(i-1),
                                start_seg_end + seg_size*i);
        thread::spawn( move || {
            let to_send = match max-min{
                0 => vec![],
                _ => seq_fun(min, max),
            };
            //
            // #[cfg(test)]
            // mark_time(i, (min, max), start);

            tx.send((i, to_send)).unwrap();
        });
    }

    for _ in 0..threads{
        let (i, p_sec) = match rx.recv(){
            Ok(mes) => mes,
            Err(e) => panic!(e.to_string()),
        };
        res_vec[i] = p_sec;
    }
    res_vec.concat()
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use libimagrt::runtime::Runtime;

pub fn week(rt: &Runtime) -> i32 {
    unimplemented!()
}

<commit_msg>Impl "week" subcommand<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

use std::cmp::Ord;
use std::cmp::Ordering;
use std::str::FromStr;

use filters::ops::not::Not;
use filters::filter::Filter;
use itertools::Itertools;
use itertools::MinMaxResult;
use chrono::NaiveDateTime;

use libimagerror::trace::trace_error;
use libimagerror::trace::MapErrTrace;
use libimagerror::iter::TraceIterator;
use libimagstore::store::FileLockEntry;
use libimagentrytimetrack::timetrackingstore::TimeTrackStore;
use libimagentrytimetrack::timetracking::TimeTracking;
use libimagentrytimetrack::tag::TimeTrackingTag;
use libimagentrytimetrack::iter::filter::*;

use libimagrt::runtime::Runtime;

pub fn week(rt: &Runtime) -> i32 {
    let cmd = rt.cli().subcommand().1.unwrap(); // checked in main

    let filter = {
        use chrono::offset::Local;
        use chrono::naive::NaiveDate;
        use chrono::Weekday;
        use chrono::Datelike;

        let this_week = Local::now().iso_week();

        let start = match cmd.value_of("start").map(::chrono::naive::NaiveDateTime::from_str) {
            None         => NaiveDate::from_isoywd(this_week.year(), this_week.week(), Weekday::Mon)
                .and_hms(0, 0, 0),
            Some(Ok(dt)) => dt,
            Some(Err(e)) => {
                trace_error(&e);
                return 1
            }
        };

        let end = match cmd.value_of("end").map(::chrono::naive::NaiveDateTime::from_str) {
            None         => NaiveDate::from_isoywd(this_week.year(), this_week.week(), Weekday::Sun)
                .and_hms(23, 59, 59),
            Some(Ok(dt)) => dt,
            Some(Err(e)) => {
                trace_error(&e);
                return 1
            }
        };

        let tags = cmd
            .values_of("tags")
            .map(|ts| ts.into_iter().map(String::from).map(TimeTrackingTag::from).collect());

        let start_time_filter = has_start_time_where(move |dt: &NaiveDateTime| {
            start <= *dt
        });

        let end_time_filter = has_end_time_where(move |dt: &NaiveDateTime| {
            end >= *dt
        });

        let tags_filter = move |fle: &FileLockEntry| {
            match tags {
                Some(ref tags) => has_one_of_tags(&tags).filter(fle),
                None => true,
            }
        };

        tags_filter.and(start_time_filter).and(end_time_filter)
    };

    rt.store()
        .get_timetrackings()
        .and_then(|iter| {
            iter.trace_unwrap()
                .filter(|e| filter.filter(e))
                .fold(Ok(()), |acc, e| {
                    acc.and_then(|_| {
                        debug!("Processing {:?}", e.get_location());

                        let tag   = try!(e.get_timetrack_tag());
                        debug!(" -> tag = {:?}", tag);

                        let start = try!(e.get_start_datetime());
                        debug!(" -> start = {:?}", start);

                        let end   = try!(e.get_end_datetime());
                        debug!(" -> end = {:?}", end);

                        match (start, end) {
                            (None, _)          => println!("{} has no start time.", tag),
                            (Some(s), None)    => println!("{} | {} - ...", tag, s),
                            (Some(s), Some(e)) => println!("{} | {} - {}", tag, s, e),
                        }

                        Ok(())
                    })
                })
        })
        .map(|_| 0)
        .map_err_trace()
        .unwrap_or(1)
}

<|endoftext|>


<commit_before>//! Print the contents of font tables.
//!
//! This accepts command line arguments similar to what is present in ttx,
//! although it does not produce xml output.

use std::{collections::HashSet, str::FromStr};

use font_types::Tag;
use read_fonts::{traversal::SomeTable, FileRef, FontData, FontRef, ReadError, TableProvider};

mod print;
mod query;

use print::PrettyPrinter;
use query::Query;

fn main() -> Result<(), Error> {
    let args = flags::Args::from_env().map_err(|e| Error(e.to_string()))?;
    let bytes = std::fs::read(&args.input).unwrap();
    let data = FontData::new(&bytes);
    let font = FileRef::new(data)
        .unwrap()
        .fonts()
        .skip(args.index.unwrap_or(0) as usize)
        .next()
        .unwrap()
        .unwrap();
    if args.list {
        list_tables(&font);
        return Ok(());
    }

    if let Some(query) = &args.query {
        return query::print_query(&font, query).map_err(Error);
    }

    let filter = TableFilter::from_args(&args)?;
    print_tables(&font, &filter);
    Ok(())
}

fn list_tables(font: &FontRef) {
    println!("Tag  Offset  Length  Checksum");
    println!("-------------------------------");

    let offset_pad = get_offset_width(font);

    for record in font.table_directory.table_records() {
        println!(
            "{0} 0x{1:02$X} {3:8} 0x{4:08X} ",
            record.tag(),
            record.offset().to_u32(),
            offset_pad,
            record.length(),
            record.checksum()
        );
    }
}

fn print_tables(font: &FontRef, filter: &TableFilter) {
    let mut printed = HashSet::new();
    for tag in font
        .table_directory
        .table_records()
        .iter()
        .map(|rec| rec.tag())
        .filter(|tag| filter.should_print(*tag))
    {
        printed.insert(tag);
        print_table(font, tag)
    }

    if let TableFilter::Include(to_print) = filter {
        for unprinted in to_print.difference(&printed) {
            println!("Table {unprinted} not found");
        }
    }
}

fn get_offset_width(font: &FontRef) -> usize {
    // pick how much padding we use for offsets based on the max offset in directory
    let max_off = font
        .table_directory
        .table_records()
        .iter()
        .map(|rec| rec.offset().to_u32())
        .max()
        .unwrap_or_default();
    hex_width(max_off)
}

/// Return the number of hex digits required to represent a given number.
fn hex_width(val: u32) -> usize {
    match val {
        0..=0xffff => 4usize,
        0x10000..=0xffff_ff => 6,
        0x1000000.. => 8,
    }
}

/// Given a font and a tag, return the appropriate table as a [`dyn SomeTable`][SomeTable].
fn get_some_table<'a>(
    font: &FontRef<'a>,
    tag: Tag,
) -> Result<Box<dyn SomeTable<'a> + 'a>, ReadError> {
    match tag {
        read_fonts::tables::gpos::TAG => font.gpos().map(|x| Box::new(x) as _),
        read_fonts::tables::gsub::TAG => font.gsub().map(|x| Box::new(x) as _),
        read_fonts::tables::cmap::TAG => font.cmap().map(|x| Box::new(x) as _),
        read_fonts::tables::gdef::TAG => font.gdef().map(|x| Box::new(x) as _),
        read_fonts::tables::glyf::TAG => font.glyf().map(|x| Box::new(x) as _),
        read_fonts::tables::head::TAG => font.head().map(|x| Box::new(x) as _),
        read_fonts::tables::hhea::TAG => font.hhea().map(|x| Box::new(x) as _),
        read_fonts::tables::hmtx::TAG => font.hmtx().map(|x| Box::new(x) as _),
        read_fonts::tables::loca::TAG => font.loca(None).map(|x| Box::new(x) as _),
        read_fonts::tables::maxp::TAG => font.maxp().map(|x| Box::new(x) as _),
        read_fonts::tables::name::TAG => font.name().map(|x| Box::new(x) as _),
        read_fonts::tables::post::TAG => font.post().map(|x| Box::new(x) as _),
        read_fonts::tables::colr::TAG => font.colr().map(|x| Box::new(x) as _),
        _ => Err(ReadError::TableIsMissing(tag)),
    }
}

fn print_table(font: &FontRef, tag: Tag) {
    match get_some_table(font, tag) {
        Ok(table) => fancy_print_table(&table).unwrap(),
        Err(err) => println!("{tag}: Error '{err}'"),
    }
}

enum TableFilter {
    All,
    Include(HashSet<Tag>),
    Exclude(HashSet<Tag>),
}

impl TableFilter {
    fn from_args(args: &flags::Args) -> Result<Self, Error> {
        if args.tables.is_some() && args.exclude.is_some() {
            return Err(Error::new("pass only one of --tables and --exclude"));
        }
        if let Some(tags) = &args.tables {
            make_tag_set(tags).map(TableFilter::Include)
        } else if let Some(tags) = &args.exclude {
            make_tag_set(tags).map(TableFilter::Exclude)
        } else {
            Ok(TableFilter::All)
        }
    }

    fn should_print(&self, tag: Tag) -> bool {
        match self {
            TableFilter::All => true,
            TableFilter::Include(tags) => tags.contains(&tag),
            TableFilter::Exclude(tags) => !tags.contains(&tag),
        }
    }
}

fn make_tag_set(inp: &str) -> Result<HashSet<Tag>, Error> {
    inp.split(' ')
        .map(|raw| match Tag::from_str(raw) {
            Ok(tag) => Ok(tag),
            Err(e) => Err(Error(format!(
                "Invalid tag '{}': {e}",
                raw.escape_default()
            ))),
        })
        .collect()
}

#[derive(Debug, Clone)]
struct Error(String);

impl Error {
    fn new(t: impl std::fmt::Display) -> Self {
        Self(t.to_string())
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.0.fmt(f)
    }
}

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

fn fancy_print_table<'a>(table: &(dyn SomeTable<'a> + 'a)) -> std::io::Result<()> {
    let stdout = std::io::stdout();
    let mut locked = stdout.lock();
    let mut formatter = PrettyPrinter::new(&mut locked);
    formatter.print_root_table(table)
}

mod flags {
    use super::Query;
    use std::path::PathBuf;

    xflags::xflags! {
        /// Generate font table representations
        cmd args
            required input: PathBuf
            {
                optional -i, --index index: u32
                optional -l, --list
                optional -q, --query query: Query
                optional -t, --tables include: String
                optional -x, --exclude exclude: String
            }

    }
}
<commit_msg>hi clippy!<commit_after>//! Print the contents of font tables.
//!
//! This accepts command line arguments similar to what is present in ttx,
//! although it does not produce xml output.

use std::{collections::HashSet, str::FromStr};

use font_types::Tag;
use read_fonts::{traversal::SomeTable, FileRef, FontData, FontRef, ReadError, TableProvider};

mod print;
mod query;

use print::PrettyPrinter;
use query::Query;

fn main() -> Result<(), Error> {
    let args = flags::Args::from_env().map_err(|e| Error(e.to_string()))?;
    let bytes = std::fs::read(&args.input).unwrap();
    let data = FontData::new(&bytes);
    let font = FileRef::new(data)
        .unwrap()
        .fonts()
        .nth(args.index.unwrap_or(0) as usize)
        .unwrap()
        .unwrap();
    if args.list {
        list_tables(&font);
        return Ok(());
    }

    if let Some(query) = &args.query {
        return query::print_query(&font, query).map_err(Error);
    }

    let filter = TableFilter::from_args(&args)?;
    print_tables(&font, &filter);
    Ok(())
}

fn list_tables(font: &FontRef) {
    println!("Tag  Offset  Length  Checksum");
    println!("-------------------------------");

    let offset_pad = get_offset_width(font);

    for record in font.table_directory.table_records() {
        println!(
            "{0} 0x{1:02$X} {3:8} 0x{4:08X} ",
            record.tag(),
            record.offset().to_u32(),
            offset_pad,
            record.length(),
            record.checksum()
        );
    }
}

fn print_tables(font: &FontRef, filter: &TableFilter) {
    let mut printed = HashSet::new();
    for tag in font
        .table_directory
        .table_records()
        .iter()
        .map(|rec| rec.tag())
        .filter(|tag| filter.should_print(*tag))
    {
        printed.insert(tag);
        print_table(font, tag)
    }

    if let TableFilter::Include(to_print) = filter {
        for unprinted in to_print.difference(&printed) {
            println!("Table {unprinted} not found");
        }
    }
}

fn get_offset_width(font: &FontRef) -> usize {
    // pick how much padding we use for offsets based on the max offset in directory
    let max_off = font
        .table_directory
        .table_records()
        .iter()
        .map(|rec| rec.offset().to_u32())
        .max()
        .unwrap_or_default();
    hex_width(max_off)
}

/// Return the number of hex digits required to represent a given number.
fn hex_width(val: u32) -> usize {
    match val {
        0..=0xffff => 4usize,
        0x10000..=0xffff_ff => 6,
        0x1000000.. => 8,
    }
}

/// Given a font and a tag, return the appropriate table as a [`dyn SomeTable`][SomeTable].
fn get_some_table<'a>(
    font: &FontRef<'a>,
    tag: Tag,
) -> Result<Box<dyn SomeTable<'a> + 'a>, ReadError> {
    match tag {
        read_fonts::tables::gpos::TAG => font.gpos().map(|x| Box::new(x) as _),
        read_fonts::tables::gsub::TAG => font.gsub().map(|x| Box::new(x) as _),
        read_fonts::tables::cmap::TAG => font.cmap().map(|x| Box::new(x) as _),
        read_fonts::tables::gdef::TAG => font.gdef().map(|x| Box::new(x) as _),
        read_fonts::tables::glyf::TAG => font.glyf().map(|x| Box::new(x) as _),
        read_fonts::tables::head::TAG => font.head().map(|x| Box::new(x) as _),
        read_fonts::tables::hhea::TAG => font.hhea().map(|x| Box::new(x) as _),
        read_fonts::tables::hmtx::TAG => font.hmtx().map(|x| Box::new(x) as _),
        read_fonts::tables::loca::TAG => font.loca(None).map(|x| Box::new(x) as _),
        read_fonts::tables::maxp::TAG => font.maxp().map(|x| Box::new(x) as _),
        read_fonts::tables::name::TAG => font.name().map(|x| Box::new(x) as _),
        read_fonts::tables::post::TAG => font.post().map(|x| Box::new(x) as _),
        read_fonts::tables::colr::TAG => font.colr().map(|x| Box::new(x) as _),
        _ => Err(ReadError::TableIsMissing(tag)),
    }
}

fn print_table(font: &FontRef, tag: Tag) {
    match get_some_table(font, tag) {
        Ok(table) => fancy_print_table(&table).unwrap(),
        Err(err) => println!("{tag}: Error '{err}'"),
    }
}

enum TableFilter {
    All,
    Include(HashSet<Tag>),
    Exclude(HashSet<Tag>),
}

impl TableFilter {
    fn from_args(args: &flags::Args) -> Result<Self, Error> {
        if args.tables.is_some() && args.exclude.is_some() {
            return Err(Error::new("pass only one of --tables and --exclude"));
        }
        if let Some(tags) = &args.tables {
            make_tag_set(tags).map(TableFilter::Include)
        } else if let Some(tags) = &args.exclude {
            make_tag_set(tags).map(TableFilter::Exclude)
        } else {
            Ok(TableFilter::All)
        }
    }

    fn should_print(&self, tag: Tag) -> bool {
        match self {
            TableFilter::All => true,
            TableFilter::Include(tags) => tags.contains(&tag),
            TableFilter::Exclude(tags) => !tags.contains(&tag),
        }
    }
}

fn make_tag_set(inp: &str) -> Result<HashSet<Tag>, Error> {
    inp.split(' ')
        .map(|raw| match Tag::from_str(raw) {
            Ok(tag) => Ok(tag),
            Err(e) => Err(Error(format!(
                "Invalid tag '{}': {e}",
                raw.escape_default()
            ))),
        })
        .collect()
}

#[derive(Debug, Clone)]
struct Error(String);

impl Error {
    fn new(t: impl std::fmt::Display) -> Self {
        Self(t.to_string())
    }
}

impl std::fmt::Display for Error {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        self.0.fmt(f)
    }
}

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

fn fancy_print_table<'a>(table: &(dyn SomeTable<'a> + 'a)) -> std::io::Result<()> {
    let stdout = std::io::stdout();
    let mut locked = stdout.lock();
    let mut formatter = PrettyPrinter::new(&mut locked);
    formatter.print_root_table(table)
}

mod flags {
    use super::Query;
    use std::path::PathBuf;

    xflags::xflags! {
        /// Generate font table representations
        cmd args
            required input: PathBuf
            {
                optional -i, --index index: u32
                optional -l, --list
                optional -q, --query query: Query
                optional -t, --tables include: String
                optional -x, --exclude exclude: String
            }

    }
}
<|endoftext|>


<commit_before>///! Handle `cargo add` arguments

use semver;
use std::error::Error;
use cargo_edit::Dependency;
use fetch_version::get_latest_version;

macro_rules! toml_table {
    ($($key:expr => $value:expr),+) => {
        {
            let mut dep = BTreeMap::new();
            $(dep.insert(String::from($key), $value);)+
            toml::Value::Table(dep)
        }
    }
}

#[derive(Debug, RustcDecodable)]
/// Docopts input args.
pub struct Args {
    /// Crate name (usage 1)
    pub arg_crate: String,
    /// Crate names (usage 2)
    pub arg_crates: Vec<String>,
    /// dev-dependency
    pub flag_dev: bool,
    /// build-dependency
    pub flag_build: bool,
    /// Version
    pub flag_vers: Option<String>,
    /// Git repo Path
    pub flag_git: Option<String>,
    /// Crate directory path
    pub flag_path: Option<String>,
    /// Optional dependency
    pub flag_optional: bool,
    /// `Cargo.toml` path
    pub flag_manifest_path: Option<String>,
    /// `--version`
    pub flag_version: bool,
}

impl Args {
    /// Get depenency section
    pub fn get_section(&self) -> &'static str {
        if self.flag_dev {
            "dev-dependencies"
        } else if self.flag_build {
            "build-dependencies"
        } else {
            "dependencies"
        }
    }

    /// Build dependencies from arguments
    pub fn parse_dependencies(&self) -> Result<Vec<Dependency>, Box<Error>> {
        if self.arg_crates.len() > 0 {
            let mut result = Vec::<Dependency>::new();
            for arg_crate in &self.arg_crates {
                result.push(try!(parse_crate_name_with_version(arg_crate)));
            }
            Ok(result)
        } else {
            if crate_name_has_version(&self.arg_crate) {
                return Ok(vec![try!(parse_crate_name_with_version(&self.arg_crate))]);
            }

            let dependency = Dependency::new(&self.arg_crate).set_optional(self.flag_optional);

            let dependency = if let Some(ref version) = self.flag_vers {
                try!(semver::VersionReq::parse(&version));
                dependency.set_version(version)
            } else if let Some(ref repo) = self.flag_git {
                dependency.set_git(repo)
            } else if let Some(ref path) = self.flag_path {
                dependency.set_path(path)
            } else {
                let v = try!(get_latest_version(&self.arg_crate));
                dependency.set_version(&v)
            };

            Ok(vec![dependency])
        }
    }
}

impl Default for Args {
    fn default() -> Args {
        Args {
            arg_crate: "demo".to_owned(),
            arg_crates: vec![],
            flag_dev: false,
            flag_build: false,
            flag_vers: None,
            flag_git: None,
            flag_path: None,
            flag_optional: false,
            flag_manifest_path: None,
            flag_version: false,
        }
    }
}

fn crate_name_has_version(name: &str) -> bool {
    name.contains("@")
}

fn parse_crate_name_with_version(name: &str) -> Result<Dependency, Box<Error>> {
    assert!(crate_name_has_version(&name));

    let xs: Vec<&str> = name.splitn(2, "@").collect();
    let (name, version) = (xs[0], xs[1]);
    try!(semver::VersionReq::parse(&version));

    Ok(Dependency::new(name).set_version(version))
}

#[cfg(test)]
mod tests {
    use cargo_edit::Dependency;
    use super::*;

    #[test]
    fn test_dependency_parsing() {
        let args = Args {
            arg_crate: "demo".to_owned(),
            flag_vers: Some("0.4.2".to_owned()),
            ..Args::default()
        };

        assert_eq!(args.parse_dependencies().unwrap(),
                   vec![Dependency::new("demo").set_version("0.4.2")]);
    }
}
<commit_msg>Fetch versions for multiple crates<commit_after>///! Handle `cargo add` arguments

use semver;
use std::error::Error;
use cargo_edit::Dependency;
use fetch_version::get_latest_version;

macro_rules! toml_table {
    ($($key:expr => $value:expr),+) => {
        {
            let mut dep = BTreeMap::new();
            $(dep.insert(String::from($key), $value);)+
            toml::Value::Table(dep)
        }
    }
}

#[derive(Debug, RustcDecodable)]
/// Docopts input args.
pub struct Args {
    /// Crate name (usage 1)
    pub arg_crate: String,
    /// Crate names (usage 2)
    pub arg_crates: Vec<String>,
    /// dev-dependency
    pub flag_dev: bool,
    /// build-dependency
    pub flag_build: bool,
    /// Version
    pub flag_vers: Option<String>,
    /// Git repo Path
    pub flag_git: Option<String>,
    /// Crate directory path
    pub flag_path: Option<String>,
    /// Optional dependency
    pub flag_optional: bool,
    /// `Cargo.toml` path
    pub flag_manifest_path: Option<String>,
    /// `--version`
    pub flag_version: bool,
}

impl Args {
    /// Get depenency section
    pub fn get_section(&self) -> &'static str {
        if self.flag_dev {
            "dev-dependencies"
        } else if self.flag_build {
            "build-dependencies"
        } else {
            "dependencies"
        }
    }

    /// Build dependencies from arguments
    pub fn parse_dependencies(&self) -> Result<Vec<Dependency>, Box<Error>> {
        if self.arg_crates.len() > 0 {
            let mut result = Vec::<Dependency>::new();
            for arg_crate in &self.arg_crates {
                let le_crate = if crate_name_has_version(&arg_crate) {
                    try!(parse_crate_name_with_version(arg_crate))
                } else {
                    let v = try!(get_latest_version(&self.arg_crate));
                    Dependency::new(arg_crate).set_version(&v)
                }.set_optional(self.flag_optional);

                result.push(le_crate);
            }
            return Ok(result);
        }

        if crate_name_has_version(&self.arg_crate) {
            return Ok(vec![
                try!(parse_crate_name_with_version(&self.arg_crate))
                    .set_optional(self.flag_optional)
            ]);
        }

        let dependency = Dependency::new(&self.arg_crate).set_optional(self.flag_optional);

        let dependency = if let Some(ref version) = self.flag_vers {
            try!(semver::VersionReq::parse(&version));
            dependency.set_version(version)
        } else if let Some(ref repo) = self.flag_git {
            dependency.set_git(repo)
        } else if let Some(ref path) = self.flag_path {
            dependency.set_path(path)
        } else {
            let v = try!(get_latest_version(&self.arg_crate));
            dependency.set_version(&v)
        };

        Ok(vec![dependency])
    }
}

impl Default for Args {
    fn default() -> Args {
        Args {
            arg_crate: "demo".to_owned(),
            arg_crates: vec![],
            flag_dev: false,
            flag_build: false,
            flag_vers: None,
            flag_git: None,
            flag_path: None,
            flag_optional: false,
            flag_manifest_path: None,
            flag_version: false,
        }
    }
}

fn crate_name_has_version(name: &str) -> bool {
    name.contains("@")
}

fn parse_crate_name_with_version(name: &str) -> Result<Dependency, Box<Error>> {
    assert!(crate_name_has_version(&name));

    let xs: Vec<&str> = name.splitn(2, "@").collect();
    let (name, version) = (xs[0], xs[1]);
    try!(semver::VersionReq::parse(&version));

    Ok(Dependency::new(name).set_version(version))
}

#[cfg(test)]
mod tests {
    use cargo_edit::Dependency;
    use super::*;

    #[test]
    fn test_dependency_parsing() {
        let args = Args {
            arg_crate: "demo".to_owned(),
            flag_vers: Some("0.4.2".to_owned()),
            ..Args::default()
        };

        assert_eq!(args.parse_dependencies().unwrap(),
                   vec![Dependency::new("demo").set_version("0.4.2")]);
    }
}
<|endoftext|>


<commit_before>//! `cargo add`
#![warn(
    missing_docs,
    missing_debug_implementations,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]

#[macro_use]
extern crate error_chain;

use crate::args::{Args, Command, UnstableOptions};
use cargo_edit::{
    colorize_stderr, find, manifest_from_pkgid, registry_url, update_registry_index, Dependency,
    LocalManifest,
};
use clap::Parser;
use std::collections::BTreeSet;
use std::io::Write;
use std::path::Path;
use std::process;
use termcolor::{Color, ColorSpec, StandardStream, WriteColor};
use toml_edit::Item as TomlItem;

mod args;

mod errors {
    error_chain! {
        errors {
            /// Specified a dependency with both a git URL and a version.
            GitUrlWithVersion(git: String, version: String) {
                description("Specified git URL with version")
                display("Cannot specify a git URL (`{}`) with a version (`{}`).", git, version)
            }
            /// Specified multiple crates with path or git or vers
            MultipleCratesWithGitOrPathOrVers {
                description("Specified multiple crates with path or git or vers")
                display("Cannot specify multiple crates with path or git or vers")
            }
            /// Specified multiple crates with renaming.
            MultipleCratesWithRename {
                description("Specified multiple crates with rename")
                display("Cannot specify multiple crates with rename")
            }
            /// Specified multiple crates with features.
            MultipleCratesWithFeatures {
                description("Specified multiple crates with features")
                display("Cannot specify multiple crates with features")
            }
            AddingSelf(crate_: String) {
                description("Adding crate to itself")
                display("Cannot add `{}` as a dependency to itself", crate_)
            }
        }
        links {
            CargoEditLib(::cargo_edit::Error, ::cargo_edit::ErrorKind);
        }
        foreign_links {
            CargoMetadata(::cargo_metadata::Error)#[doc = "An error from the cargo_metadata crate"];
            Io(::std::io::Error);
        }
    }
}

use crate::errors::*;

fn print_msg(dep: &Dependency, section: &[String], optional: bool) -> Result<()> {
    let colorchoice = colorize_stderr();
    let mut output = StandardStream::stderr(colorchoice);
    output.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?;
    write!(output, "{:>12}", "Adding")?;
    output.reset()?;
    write!(output, " {}", dep.name)?;
    if dep.path().is_some() {
        write!(output, " (local)")?;
    } else if let Some(version) = dep.version() {
        if version.chars().next().unwrap_or('0').is_ascii_digit() {
            write!(output, " v{}", version)?;
        } else {
            write!(output, " {}", version)?;
        }
    }
    write!(output, " to")?;
    if optional {
        write!(output, " optional")?;
    }
    let section = if section.len() == 1 {
        section[0].clone()
    } else {
        format!("{} for target `{}`", &section[2], &section[1])
    };
    write!(output, " {}", section)?;
    if let Some(f) = &dep.features {
        if !f.is_empty() {
            write!(output, " with features: {}", f.join(", "))?;
        }
    }
    writeln!(output, ".")?;

    if !&dep.available_features.is_empty() {
        writeln!(output, "{:>13}Available features:", " ")?;
        for feat in dep.available_features.iter() {
            writeln!(output, "{:>13}- {}", " ", feat)?;
        }
    }
    Ok(())
}

// Based on Iterator::is_sorted from nightly std; remove in favor of that when stabilized.
fn is_sorted(mut it: impl Iterator<Item = impl PartialOrd>) -> bool {
    let mut last = match it.next() {
        Some(e) => e,
        None => return true,
    };

    for curr in it {
        if curr < last {
            return false;
        }
        last = curr;
    }

    true
}

fn unrecognized_features_message(message: &str) -> Result<()> {
    let colorchoice = colorize_stderr();
    let mut output = StandardStream::stderr(colorchoice);
    output.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true))?;
    write!(output, "{:>12}", "Warning:")?;
    output.reset()?;
    writeln!(output, " {}", message)
        .chain_err(|| "Failed to write unrecognized features message")?;
    Ok(())
}

fn handle_add(mut args: Args) -> Result<()> {
    if args.git.is_some() && !args.unstable_features.contains(&UnstableOptions::Git) {
        return Err("`--git` is unstable and requires `-Z git`".into());
    }

    if let Some(ref pkgid) = args.pkgid {
        let pkg = manifest_from_pkgid(args.manifest_path.as_deref(), pkgid)?;
        args.manifest_path = Some(pkg.manifest_path.into_std_path_buf());
    }
    let mut manifest = LocalManifest::find(&args.manifest_path)?;

    if !args.offline && std::env::var("CARGO_IS_TEST").is_err() {
        let url = registry_url(
            &find(&args.manifest_path)?,
            args.registry.as_ref().map(String::as_ref),
        )?;
        update_registry_index(&url, args.quiet)?;
    }
    let requested_features: Option<BTreeSet<&str>> = args.features.as_ref().map(|v| {
        v.iter()
            .map(|s| s.split(' '))
            .flatten()
            .filter(|s| !s.is_empty())
            .collect()
    });

    let deps = &args.parse_dependencies(
        requested_features
            .as_ref()
            .map(|s| s.iter().map(|s| s.to_string()).collect()),
    )?;

    if let Some(req_feats) = requested_features {
        assert!(deps.len() == 1);
        let available_features = deps[0]
            .available_features
            .iter()
            .map(|s| s.as_ref())
            .collect::<BTreeSet<&str>>();

        let mut unknown_features: Vec<&&str> = req_feats.difference(&available_features).collect();
        unknown_features.sort();

        if !unknown_features.is_empty() {
            unrecognized_features_message(&format!(
                "Unrecognized features: {:?}",
                unknown_features
            ))?;
        };
    };

    let was_sorted = manifest
        .get_table(&args.get_section())
        .map(TomlItem::as_table_mut)
        .map_or(true, |table_option| {
            table_option.map_or(true, |table| is_sorted(table.iter().map(|(name, _)| name)))
        });
    deps.iter()
        .map(|dep| {
            if !args.quiet {
                print_msg(dep, &args.get_section(), args.optional)?;
            }
            if let Some(path) = dep.path() {
                if path == manifest.path.parent().unwrap_or_else(|| Path::new("")) {
                    return Err(ErrorKind::AddingSelf(manifest.package_name()?.to_owned()).into());
                }
            }
            manifest
                .insert_into_table(&args.get_section(), dep)
                .map(|_| {
                    manifest
                        .get_table(&args.get_section())
                        .map(TomlItem::as_table_mut)
                        .map(|table_option| {
                            table_option.map(|table| {
                                if was_sorted {
                                    table.sort_values();
                                }
                            })
                        })
                })
                .map_err(Into::into)
        })
        .collect::<Result<Vec<_>>>()
        .map_err(|err| {
            eprintln!("Could not edit `Cargo.toml`.\n\nERROR: {}", err);
            err
        })?;

    manifest.write()?;

    Ok(())
}

fn main() {
    let args: Command = Command::parse();
    let Command::Add(args) = args;

    if let Err(err) = handle_add(args) {
        eprintln!("Command failed due to unhandled error: {}", err);

        let mut gap = false;
        for e in err.iter().skip(1) {
            if !gap {
                eprintln!();
                gap = true;
            }
            eprintln!("Caused by: {}", e);
        }

        if let Some(backtrace) = err.backtrace() {
            eprintln!();
            eprintln!("Backtrace: {:?}", backtrace);
        }

        process::exit(1);
    }
}
<commit_msg>refactor: Only sort the table once<commit_after>//! `cargo add`
#![warn(
    missing_docs,
    missing_debug_implementations,
    missing_copy_implementations,
    trivial_casts,
    trivial_numeric_casts,
    unsafe_code,
    unstable_features,
    unused_import_braces,
    unused_qualifications
)]

#[macro_use]
extern crate error_chain;

use crate::args::{Args, Command, UnstableOptions};
use cargo_edit::{
    colorize_stderr, find, manifest_from_pkgid, registry_url, update_registry_index, Dependency,
    LocalManifest,
};
use clap::Parser;
use std::collections::BTreeSet;
use std::io::Write;
use std::path::Path;
use std::process;
use termcolor::{Color, ColorSpec, StandardStream, WriteColor};
use toml_edit::Item as TomlItem;

mod args;

mod errors {
    error_chain! {
        errors {
            /// Specified a dependency with both a git URL and a version.
            GitUrlWithVersion(git: String, version: String) {
                description("Specified git URL with version")
                display("Cannot specify a git URL (`{}`) with a version (`{}`).", git, version)
            }
            /// Specified multiple crates with path or git or vers
            MultipleCratesWithGitOrPathOrVers {
                description("Specified multiple crates with path or git or vers")
                display("Cannot specify multiple crates with path or git or vers")
            }
            /// Specified multiple crates with renaming.
            MultipleCratesWithRename {
                description("Specified multiple crates with rename")
                display("Cannot specify multiple crates with rename")
            }
            /// Specified multiple crates with features.
            MultipleCratesWithFeatures {
                description("Specified multiple crates with features")
                display("Cannot specify multiple crates with features")
            }
            AddingSelf(crate_: String) {
                description("Adding crate to itself")
                display("Cannot add `{}` as a dependency to itself", crate_)
            }
        }
        links {
            CargoEditLib(::cargo_edit::Error, ::cargo_edit::ErrorKind);
        }
        foreign_links {
            CargoMetadata(::cargo_metadata::Error)#[doc = "An error from the cargo_metadata crate"];
            Io(::std::io::Error);
        }
    }
}

use crate::errors::*;

fn print_msg(dep: &Dependency, section: &[String], optional: bool) -> Result<()> {
    let colorchoice = colorize_stderr();
    let mut output = StandardStream::stderr(colorchoice);
    output.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?;
    write!(output, "{:>12}", "Adding")?;
    output.reset()?;
    write!(output, " {}", dep.name)?;
    if dep.path().is_some() {
        write!(output, " (local)")?;
    } else if let Some(version) = dep.version() {
        if version.chars().next().unwrap_or('0').is_ascii_digit() {
            write!(output, " v{}", version)?;
        } else {
            write!(output, " {}", version)?;
        }
    }
    write!(output, " to")?;
    if optional {
        write!(output, " optional")?;
    }
    let section = if section.len() == 1 {
        section[0].clone()
    } else {
        format!("{} for target `{}`", &section[2], &section[1])
    };
    write!(output, " {}", section)?;
    if let Some(f) = &dep.features {
        if !f.is_empty() {
            write!(output, " with features: {}", f.join(", "))?;
        }
    }
    writeln!(output, ".")?;

    if !&dep.available_features.is_empty() {
        writeln!(output, "{:>13}Available features:", " ")?;
        for feat in dep.available_features.iter() {
            writeln!(output, "{:>13}- {}", " ", feat)?;
        }
    }
    Ok(())
}

// Based on Iterator::is_sorted from nightly std; remove in favor of that when stabilized.
fn is_sorted(mut it: impl Iterator<Item = impl PartialOrd>) -> bool {
    let mut last = match it.next() {
        Some(e) => e,
        None => return true,
    };

    for curr in it {
        if curr < last {
            return false;
        }
        last = curr;
    }

    true
}

fn unrecognized_features_message(message: &str) -> Result<()> {
    let colorchoice = colorize_stderr();
    let mut output = StandardStream::stderr(colorchoice);
    output.set_color(ColorSpec::new().set_fg(Some(Color::Yellow)).set_bold(true))?;
    write!(output, "{:>12}", "Warning:")?;
    output.reset()?;
    writeln!(output, " {}", message)
        .chain_err(|| "Failed to write unrecognized features message")?;
    Ok(())
}

fn handle_add(mut args: Args) -> Result<()> {
    if args.git.is_some() && !args.unstable_features.contains(&UnstableOptions::Git) {
        return Err("`--git` is unstable and requires `-Z git`".into());
    }

    if let Some(ref pkgid) = args.pkgid {
        let pkg = manifest_from_pkgid(args.manifest_path.as_deref(), pkgid)?;
        args.manifest_path = Some(pkg.manifest_path.into_std_path_buf());
    }
    let mut manifest = LocalManifest::find(&args.manifest_path)?;

    if !args.offline && std::env::var("CARGO_IS_TEST").is_err() {
        let url = registry_url(
            &find(&args.manifest_path)?,
            args.registry.as_ref().map(String::as_ref),
        )?;
        update_registry_index(&url, args.quiet)?;
    }
    let requested_features: Option<BTreeSet<&str>> = args.features.as_ref().map(|v| {
        v.iter()
            .map(|s| s.split(' '))
            .flatten()
            .filter(|s| !s.is_empty())
            .collect()
    });

    let deps = &args.parse_dependencies(
        requested_features
            .as_ref()
            .map(|s| s.iter().map(|s| s.to_string()).collect()),
    )?;

    if let Some(req_feats) = requested_features {
        assert!(deps.len() == 1);
        let available_features = deps[0]
            .available_features
            .iter()
            .map(|s| s.as_ref())
            .collect::<BTreeSet<&str>>();

        let mut unknown_features: Vec<&&str> = req_feats.difference(&available_features).collect();
        unknown_features.sort();

        if !unknown_features.is_empty() {
            unrecognized_features_message(&format!(
                "Unrecognized features: {:?}",
                unknown_features
            ))?;
        };
    };

    let was_sorted = manifest
        .get_table(&args.get_section())
        .map(TomlItem::as_table_mut)
        .map_or(true, |table_option| {
            table_option.map_or(true, |table| is_sorted(table.iter().map(|(name, _)| name)))
        });
    deps.iter()
        .map(|dep| {
            if !args.quiet {
                print_msg(dep, &args.get_section(), args.optional)?;
            }
            if let Some(path) = dep.path() {
                if path == manifest.path.parent().unwrap_or_else(|| Path::new("")) {
                    return Err(ErrorKind::AddingSelf(manifest.package_name()?.to_owned()).into());
                }
            }
            manifest.insert_into_table(&args.get_section(), dep)?;
            Ok(())
        })
        .collect::<Result<Vec<_>>>()
        .map_err(|err| {
            eprintln!("Could not edit `Cargo.toml`.\n\nERROR: {}", err);
            err
        })?;

    if was_sorted {
        if let Some(table) = manifest
            .get_table(&args.get_section())
            .ok()
            .and_then(TomlItem::as_table_like_mut)
        {
            table.sort_values();
        }
    }

    manifest.write()?;

    Ok(())
}

fn main() {
    let args: Command = Command::parse();
    let Command::Add(args) = args;

    if let Err(err) = handle_add(args) {
        eprintln!("Command failed due to unhandled error: {}", err);

        let mut gap = false;
        for e in err.iter().skip(1) {
            if !gap {
                eprintln!();
                gap = true;
            }
            eprintln!("Caused by: {}", e);
        }

        if let Some(backtrace) = err.backtrace() {
            eprintln!();
            eprintln!("Backtrace: {:?}", backtrace);
        }

        process::exit(1);
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(test, allow(dead_code))]

#![feature(collections)]
#![feature(core)]
#![feature(io)]
#![feature(env)]
#![feature(path)]
#![feature(rustc_private)]

extern crate document;
extern crate xpath;
extern crate getopts;

use std::cmp::min;
use std::borrow::ToOwned;
use std::env;
use std::collections::HashMap;
use std::old_io::File;

use document::parser::Parser;

use xpath::nodeset::ToNode;
use xpath::{EvaluationContext,Factory,Expression,Value};

use getopts::{reqopt,optmulti,getopts,OptGroup,usage};

fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options] FILE...", program);
    print!("{}", usage(&brief, opts));
}

fn pretty_error(xml: &str, position: usize) -> &str {
    let s = &xml[position..];
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn build_xpath(xpath_str: &str) -> Box<Expression> {
    let factory = Factory::new();

    match factory.build(xpath_str) {
        Err(x) => panic!("Unable to compile XPath: {:?}", x),
        Ok(None) => panic!("Unable to compile XPath"),
        Ok(Some(x)) => x,
    }
}

fn load_xml(filename: &str) -> document::Package {
    let p = Parser::new();
    let path = Path::new(filename);
    let mut file = File::open(&path);

    let data = match file.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    match p.parse(&data) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(&data, point)),
    }
}

fn argument_name_value(s: &str, delim: char) -> Option<(&str, &str)> {
    let parts: Vec<_> = s.splitn(2, delim).collect();
    if parts.len() < 2 {
        None
    } else {
        Some((parts[0], parts[1]))
    }
}

fn build_functions() -> xpath::Functions {
    let mut functions = HashMap::new();
    xpath::function::register_core_functions(&mut functions);
    functions
}

fn build_variables<'a>(arguments: &getopts::Matches) -> xpath::Variables<'a> {
    let mut vars = HashMap::new();

    for boolean in arguments.opt_strs("boolean") {
        match argument_name_value(&boolean, '=') {
            Some((name, "true")) => { vars.insert(name.to_owned(), Value::Boolean(true)); },
            Some((name, "false")) => { vars.insert(name.to_owned(), Value::Boolean(false)); },
            Some((_, val)) => panic!("Unknown boolean value '{}'", val),
            None => panic!("boolean argument '{}' is malformed", boolean),
        }
    }

    for number in arguments.opt_strs("number") {
        match argument_name_value(&number, '=') {
            Some((name, val)) => {
                match val.parse() {
                    Ok(val) => { vars.insert(name.to_owned(), Value::Number(val)); },
                    Err(e) => panic!("Unknown numeric value '{}': {}", val, e),
                }
            },
            None => panic!("number argument '{}' is malformed", number),
        }
    }

    for string in arguments.opt_strs("string") {
        match argument_name_value(&string, '=') {
            Some((name, val)) => { vars.insert(name.to_owned(), Value::String(val.to_owned())); },
            None => panic!("string argument '{}' is malformed", string),
        }
    }

    vars
}

fn build_namespaces(arguments: &getopts::Matches) -> xpath::Namespaces {
    let mut namespaces = HashMap::new();

    for ns_defn in arguments.opt_strs("namespace") {
        match argument_name_value(&ns_defn, ':') {
            Some((prefix, uri)) => { namespaces.insert(prefix.to_owned(), uri.to_owned()); },
            None => panic!("Namespace definition '{}' is malformed", ns_defn),
        }
    }

    namespaces
}

fn main() {
    let args: Vec<_> = env::args().collect();

    let program_name = &args[0];

    let opts = &[
        reqopt("", "xpath", "The XPath to execute", "XPATH"),
        optmulti("", "namespace", "set namespace prefix", "PREFIX:URI"),
        optmulti("", "string", "set string variable", "NAME=VALUE"),
        optmulti("", "number", "set number variable", "NAME=VALUE"),
        optmulti("", "boolean", "set boolean variable", "NAME=VALUE"),
    ];

    let arguments = match getopts(args.tail(), opts) {
        Ok(x) => x,
        Err(x) => {
            println!("{}", x);
            print_usage(program_name, opts);
            return;
        },
    };

    let xpath_str = arguments.opt_str("xpath").unwrap();
    let xpath = build_xpath(&xpath_str);

    for filename in arguments.free.iter() {
        let package = load_xml(filename);
        let doc = package.as_document();
        let root = doc.root().into_node();

        let functions = build_functions();
        let variables = build_variables(&arguments);
        let namespaces = build_namespaces(&arguments);

        let context = EvaluationContext::new(
            root,
            &functions,
            &variables,
            &namespaces,
        );

        let res = xpath.evaluate(&context);

        println!("{:?}", res);
    }
}
<commit_msg>Accept XML document from stdin<commit_after>#![cfg_attr(test, allow(dead_code))]

#![feature(collections)]
#![feature(core)]
#![feature(io)]
#![feature(env)]
#![feature(path)]
#![feature(rustc_private)]

extern crate document;
extern crate xpath;
extern crate getopts;

use std::cmp::min;
use std::borrow::ToOwned;
use std::env;
use std::collections::HashMap;
use std::old_io::File;
use std::old_io::stdio;

use document::parser::Parser;

use xpath::nodeset::ToNode;
use xpath::{EvaluationContext,Factory,Expression,Value};

use getopts::{reqopt,optmulti,getopts,OptGroup,usage};

fn print_usage(program: &str, opts: &[OptGroup]) {
    let brief = format!("Usage: {} [options] FILE...", program);
    print!("{}", usage(&brief, opts));
}

fn pretty_error(xml: &str, position: usize) -> &str {
    let s = &xml[position..];
    let l = s.chars().count();
    s.slice_chars(0, min(l, 15))
}

fn build_xpath(xpath_str: &str) -> Box<Expression> {
    let factory = Factory::new();

    match factory.build(xpath_str) {
        Err(x) => panic!("Unable to compile XPath: {:?}", x),
        Ok(None) => panic!("Unable to compile XPath"),
        Ok(Some(x)) => x,
    }
}

fn load_xml<R>(input: R) -> document::Package
    where R: Reader
{
    let mut input = input;
    let p = Parser::new();

    let data = match input.read_to_string() {
        Ok(x) => x,
        Err(x) => panic!("Can't read: {}", x),
    };

    match p.parse(&data) {
        Ok(d) => d,
        Err(point) => panic!("Unable to parse: {}", pretty_error(&data, point)),
    }
}

fn argument_name_value(s: &str, delim: char) -> Option<(&str, &str)> {
    let parts: Vec<_> = s.splitn(2, delim).collect();
    if parts.len() < 2 {
        None
    } else {
        Some((parts[0], parts[1]))
    }
}

fn build_functions() -> xpath::Functions {
    let mut functions = HashMap::new();
    xpath::function::register_core_functions(&mut functions);
    functions
}

fn build_variables<'a>(arguments: &getopts::Matches) -> xpath::Variables<'a> {
    let mut vars = HashMap::new();

    for boolean in arguments.opt_strs("boolean") {
        match argument_name_value(&boolean, '=') {
            Some((name, "true")) => { vars.insert(name.to_owned(), Value::Boolean(true)); },
            Some((name, "false")) => { vars.insert(name.to_owned(), Value::Boolean(false)); },
            Some((_, val)) => panic!("Unknown boolean value '{}'", val),
            None => panic!("boolean argument '{}' is malformed", boolean),
        }
    }

    for number in arguments.opt_strs("number") {
        match argument_name_value(&number, '=') {
            Some((name, val)) => {
                match val.parse() {
                    Ok(val) => { vars.insert(name.to_owned(), Value::Number(val)); },
                    Err(e) => panic!("Unknown numeric value '{}': {}", val, e),
                }
            },
            None => panic!("number argument '{}' is malformed", number),
        }
    }

    for string in arguments.opt_strs("string") {
        match argument_name_value(&string, '=') {
            Some((name, val)) => { vars.insert(name.to_owned(), Value::String(val.to_owned())); },
            None => panic!("string argument '{}' is malformed", string),
        }
    }

    vars
}

fn build_namespaces(arguments: &getopts::Matches) -> xpath::Namespaces {
    let mut namespaces = HashMap::new();

    for ns_defn in arguments.opt_strs("namespace") {
        match argument_name_value(&ns_defn, ':') {
            Some((prefix, uri)) => { namespaces.insert(prefix.to_owned(), uri.to_owned()); },
            None => panic!("Namespace definition '{}' is malformed", ns_defn),
        }
    }

    namespaces
}

fn main() {
    let args: Vec<_> = env::args().collect();

    let program_name = &args[0];

    let opts = &[
        reqopt("", "xpath", "The XPath to execute", "XPATH"),
        optmulti("", "namespace", "set namespace prefix", "PREFIX:URI"),
        optmulti("", "string", "set string variable", "NAME=VALUE"),
        optmulti("", "number", "set number variable", "NAME=VALUE"),
        optmulti("", "boolean", "set boolean variable", "NAME=VALUE"),
    ];

    let arguments = match getopts(args.tail(), opts) {
        Ok(x) => x,
        Err(x) => {
            println!("{}", x);
            print_usage(program_name, opts);
            return;
        },
    };

    let xpath_str = arguments.opt_str("xpath").unwrap();
    let xpath = build_xpath(&xpath_str);

    for filename in &arguments.free {
        let package = if *filename == "-" {
            load_xml(stdio::stdin_raw())
        } else {
            load_xml(File::open(&Path::new(filename)))
        };

        let doc = package.as_document();
        let root = doc.root().into_node();

        let functions = build_functions();
        let variables = build_variables(&arguments);
        let namespaces = build_namespaces(&arguments);

        let context = EvaluationContext::new(
            root,
            &functions,
            &variables,
            &namespaces,
        );

        let res = xpath.evaluate(&context);

        println!("{:?}", res);
    }
}
<|endoftext|>


<commit_before>extern crate arguments;
extern crate configuration;
extern crate random;
extern crate sql;
extern crate sqlite;
extern crate term;
extern crate time;

#[macro_use]
extern crate log;

#[macro_use]
extern crate streamer;

use configuration::format::TOML;
use log::LogLevel;
use streamer::{platform, schedule, system, traffic, workload};

pub use streamer::{Config, Error, Result};

pub type Data = (platform::Profile, platform::Profile);
pub type Event = system::Event;

pub type System = system::System<traffic::Fractal,
                                 workload::Random,
                                 platform::Thermal,
                                 schedule::Impartial>;

const USAGE: &'static str = "
Usage: streamer [options]

Options:
    --config <path>          Configuration file (required).
    --length <time>          Time span to synthesize in seconds [default: 10].
    --output <path>          Output file for power and temperature profiles.

    --verbose                Display progress information.
    --help                   Display this message.
";

mod logger;
mod output;

use output::Output;

fn main() {
    start().unwrap_or_else(|error| fail(error));
}

fn start() -> Result<()> {
    let arguments = ok!(arguments::parse(std::env::args()));
    if arguments.get::<bool>("help").unwrap_or(false) {
        help();
    }
    if arguments.get::<bool>("verbose").unwrap_or(false) {
        logger::setup(LogLevel::Info);
    } else {
        logger::setup(LogLevel::Warn);
    }

    let config = ok!(TOML::open(some!(arguments.get::<String>("config"),
                                      "a configuration file is required")));

    let mut system = try!(construct_system(&config));
    let mut output = try!(output::new(&system, arguments.get::<String>("output")));

    let length = arguments.get::<f64>("length").unwrap_or(10.0);
    info!(target: "Streamer", "Synthesizing {} seconds...", length);
    let start = time::now();

    while let Some((event, data)) = try!(system.next()) {
        display(&system, &event);
        try!(output.next(&event, &data));
        if event.time > length {
            break;
        }
    }

    let elapsed = time::now() - start;
    info!(target: "Streamer", "Well done in {:.2} seconds.",
          elapsed.num_milliseconds() as f64 / 1000.0);

    Ok(())
}

fn construct_system(config: &Config) -> Result<System> {
    let source = {
        let seed = config.get::<i64>("seed").map(|&seed| seed as u64).unwrap_or(0);
        let seed = if seed > 0 { seed } else { time::now().to_timespec().sec as u64 };
        let seed = [0x12345678 & seed, 0x87654321 & seed];
        random::default().seed(seed)
    };

    macro_rules! branch(($name:expr) => (config.branch($name).as_ref().unwrap_or(config)));

    let traffic = try!(traffic::Fractal::new(branch!("traffic"), &source));
    let workload = try!(workload::Random::new(branch!("workload"), &source));
    let platform = try!(platform::Thermal::new(branch!("platform")));
    let schedule = try!(schedule::Impartial::new(branch!("schedule"), &platform));

    System::new(traffic, workload, platform, schedule)
}

fn display(system: &System, event: &Event) {
    use streamer::system::EventKind;

    let (job, kind) = match &event.kind {
        &EventKind::Arrived(ref job) => (job, "arrived"),
        &EventKind::Started(ref job) => (job, "started"),
        &EventKind::Finished(ref job) => (job, "finished"),
    };
    info!(target: "Streamer",
          "{:7.2} s | job #{:3} ( {:20} | {:2} units | {:6.2} s ) {:8} | {:2} queued",
          event.time, job.id, job.name, job.units, job.duration(), kind,
          system.history().arrived - system.history().started);
}

fn help() -> ! {
    println!("{}", USAGE.trim());
    std::process::exit(0);
}

#[allow(unused_must_use)]
fn fail(error: Error) -> ! {
    use std::io::Write;
    if let Some(mut output) = term::stderr() {
        output.fg(term::color::RED);
        output.write_all(format!("Error: {}.\n", error).as_bytes());
    }
    std::process::exit(1);
}
<commit_msg>bin: adjust --verbose’s output<commit_after>extern crate arguments;
extern crate configuration;
extern crate random;
extern crate sql;
extern crate sqlite;
extern crate term;
extern crate time;

#[macro_use]
extern crate log;

#[macro_use]
extern crate streamer;

use configuration::format::TOML;
use log::LogLevel;
use streamer::{platform, schedule, system, traffic, workload};

pub use streamer::{Config, Error, Result};

pub type Data = (platform::Profile, platform::Profile);
pub type Event = system::Event;

pub type System = system::System<traffic::Fractal,
                                 workload::Random,
                                 platform::Thermal,
                                 schedule::Impartial>;

const USAGE: &'static str = "
Usage: streamer [options]

Options:
    --config <path>          Configuration file (required).
    --length <time>          Time span to synthesize in seconds [default: 10].
    --output <path>          Output file for power and temperature profiles.

    --verbose                Display progress information.
    --help                   Display this message.
";

mod logger;
mod output;

use output::Output;

fn main() {
    start().unwrap_or_else(|error| fail(error));
}

fn start() -> Result<()> {
    let arguments = ok!(arguments::parse(std::env::args()));
    if arguments.get::<bool>("help").unwrap_or(false) {
        help();
    }
    if arguments.get::<bool>("verbose").unwrap_or(false) {
        logger::setup(LogLevel::Info);
    } else {
        logger::setup(LogLevel::Warn);
    }

    let config = ok!(TOML::open(some!(arguments.get::<String>("config"),
                                      "a configuration file is required")));

    let mut system = try!(construct_system(&config));
    let mut output = try!(output::new(&system, arguments.get::<String>("output")));

    let length = arguments.get::<f64>("length").unwrap_or(10.0);
    info!(target: "Streamer", "Synthesizing {} seconds...", length);
    let start = time::now();

    while let Some((event, data)) = try!(system.next()) {
        display(&system, &event);
        try!(output.next(&event, &data));
        if event.time > length {
            break;
        }
    }

    let elapsed = time::now() - start;
    info!(target: "Streamer", "Well done in {:.2} seconds.",
          elapsed.num_milliseconds() as f64 / 1000.0);

    Ok(())
}

fn construct_system(config: &Config) -> Result<System> {
    let source = {
        let seed = config.get::<i64>("seed").map(|&seed| seed as u64).unwrap_or(0);
        let seed = if seed > 0 { seed } else { time::now().to_timespec().sec as u64 };
        let seed = [0x12345678 & seed, 0x87654321 & seed];
        random::default().seed(seed)
    };

    macro_rules! branch(($name:expr) => (config.branch($name).as_ref().unwrap_or(config)));

    let traffic = try!(traffic::Fractal::new(branch!("traffic"), &source));
    let workload = try!(workload::Random::new(branch!("workload"), &source));
    let platform = try!(platform::Thermal::new(branch!("platform")));
    let schedule = try!(schedule::Impartial::new(branch!("schedule"), &platform));

    System::new(traffic, workload, platform, schedule)
}

fn display(system: &System, event: &Event) {
    use streamer::system::EventKind;

    let (job, kind) = match &event.kind {
        &EventKind::Arrived(ref job) => (job, "arrived"),
        &EventKind::Started(ref job) => (job, "started"),
        &EventKind::Finished(ref job) => (job, "finished"),
    };
    info!(target: "Streamer",
          "{:7.2} s | job #{:4} ( {:20} | {:2} units | {:6.2} s ) {:8} | {:2} queued",
          event.time, job.id, job.name, job.units, job.duration(), kind,
          system.history().arrived - system.history().started);
}

fn help() -> ! {
    println!("{}", USAGE.trim());
    std::process::exit(0);
}

#[allow(unused_must_use)]
fn fail(error: Error) -> ! {
    use std::io::Write;
    if let Some(mut output) = term::stderr() {
        output.fg(term::color::RED);
        output.write_all(format!("Error: {}.\n", error).as_bytes());
    }
    std::process::exit(1);
}
<|endoftext|>


<commit_before>use super::block_tokenizer::BlockTokenizer;
use super::tokens::LineType;
use super::ast::{Block, HeadingLevel, ListType};

#[derive(Debug)]
pub struct BlockParser {
    tokenizer: BlockTokenizer,
}

#[derive(Debug)]
pub struct TextAccumulator {
    buffer: String,
}

impl BlockParser {
    pub fn new<S: Into<String>>(input: S) -> Self {
        BlockParser { tokenizer: BlockTokenizer::new(input) }
    }

    fn parse_text(&mut self) -> Option<Block> {
        let mut accumulator = TextAccumulator::new();

        loop {
            let next_type = self.tokenizer.peek();

            if let Some(LineType::Text) = next_type {
                let line = self.tokenizer.consume(next_type.unwrap()).unwrap();

                accumulator.add(&line.value().unwrap());
            } else {
                break;
            }
        }

        Some(Block::Text { content: accumulator.consume() })
    }

    fn parse_quote(&mut self) -> Option<Block> {
        let mut accumulator = TextAccumulator::new();

        loop {
            let next_type = self.tokenizer.peek();

            if let Some(LineType::Quote) = next_type {
                let line = self.tokenizer.consume(next_type.unwrap()).unwrap();

                accumulator.add(&line.value().unwrap());
            } else {
                break;
            }
        }

        Some(Block::Quote { content: accumulator.consume() })
    }

    fn parse_heading(&mut self, line_type: LineType) -> Option<Block> {
        let level = match line_type {
            LineType::Heading1 => HeadingLevel::Level1,
            LineType::Heading2 => HeadingLevel::Level2,
            LineType::Heading3 => HeadingLevel::Level3,
            _ => return None,
        };

        let content = self.tokenizer.consume(line_type)?.value()?.trim().into();

        Some(Block::Heading { content, level })
    }
}

impl Iterator for BlockParser {
    type Item = Block;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.tokenizer.peek() {
                None => return None,
                Some(LineType::Blank) => {
                    self.tokenizer.consume(LineType::Blank);
                    continue;
                }
                Some(LineType::Text) => return self.parse_text(),
                Some(LineType::Quote) => return self.parse_quote(),
                Some(LineType::Heading1) => return self.parse_heading(LineType::Heading1),
                Some(LineType::Heading2) => return self.parse_heading(LineType::Heading2),
                Some(LineType::Heading3) => return self.parse_heading(LineType::Heading3),
                _ => return None,
            };
        }
    }
}

impl TextAccumulator {
    pub fn new() -> Self {
        TextAccumulator { buffer: String::new() }
    }

    ///
    /// Adds a new line to the current accumulated text.
    /// Todo: this should also take care of newlines with two spaces
    ///
    pub fn add(&mut self, line: &str) {
        if self.buffer.len() > 0 {
            self.buffer.push_str(" ");
        }

        self.buffer.push_str(line);
    }

    pub fn consume(self) -> String {
        self.buffer
    }
}

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

    #[test]
    fn it_works() {
        let mut parser = BlockParser::new("Lorem ipsum\ndolor sit amet");

        assert_eq!(
            Some(Block::Text {
                content: "Lorem ipsum dolor sit amet".to_string(),
            }),
            parser.next()
        );
    }

    #[test]
    fn parsing_headings_works() {
        let mut parser = BlockParser::new("# hello world\n##    level 2\n### three");

        assert_eq!(
            Some(Block::Heading {
                content: "hello world".into(),
                level: HeadingLevel::Level1,
            }),
            parser.next()
        );

        assert_eq!(
            Some(Block::Heading {
                content: "level 2".into(),
                level: HeadingLevel::Level2,
            }),
            parser.next()
        );
    }
}<commit_msg>Remove unused import<commit_after>use super::block_tokenizer::BlockTokenizer;
use super::tokens::LineType;
use super::ast::{Block, HeadingLevel};

#[derive(Debug)]
pub struct BlockParser {
    tokenizer: BlockTokenizer,
}

#[derive(Debug)]
pub struct TextAccumulator {
    buffer: String,
}

impl BlockParser {
    pub fn new<S: Into<String>>(input: S) -> Self {
        BlockParser { tokenizer: BlockTokenizer::new(input) }
    }

    fn parse_text(&mut self) -> Option<Block> {
        let mut accumulator = TextAccumulator::new();

        loop {
            let next_type = self.tokenizer.peek();

            if let Some(LineType::Text) = next_type {
                let line = self.tokenizer.consume(next_type.unwrap()).unwrap();

                accumulator.add(&line.value().unwrap());
            } else {
                break;
            }
        }

        Some(Block::Text { content: accumulator.consume() })
    }

    fn parse_quote(&mut self) -> Option<Block> {
        let mut accumulator = TextAccumulator::new();

        loop {
            let next_type = self.tokenizer.peek();

            if let Some(LineType::Quote) = next_type {
                let line = self.tokenizer.consume(next_type.unwrap()).unwrap();

                accumulator.add(&line.value().unwrap());
            } else {
                break;
            }
        }

        Some(Block::Quote { content: accumulator.consume() })
    }

    fn parse_heading(&mut self, line_type: LineType) -> Option<Block> {
        let level = match line_type {
            LineType::Heading1 => HeadingLevel::Level1,
            LineType::Heading2 => HeadingLevel::Level2,
            LineType::Heading3 => HeadingLevel::Level3,
            _ => return None,
        };

        let content = self.tokenizer.consume(line_type)?.value()?.trim().into();

        Some(Block::Heading { content, level })
    }
}

impl Iterator for BlockParser {
    type Item = Block;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            match self.tokenizer.peek() {
                None => return None,
                Some(LineType::Blank) => {
                    self.tokenizer.consume(LineType::Blank);
                    continue;
                }
                Some(LineType::Text) => return self.parse_text(),
                Some(LineType::Quote) => return self.parse_quote(),
                Some(LineType::Heading1) => return self.parse_heading(LineType::Heading1),
                Some(LineType::Heading2) => return self.parse_heading(LineType::Heading2),
                Some(LineType::Heading3) => return self.parse_heading(LineType::Heading3),
                _ => return None,
            };
        }
    }
}

impl TextAccumulator {
    pub fn new() -> Self {
        TextAccumulator { buffer: String::new() }
    }

    ///
    /// Adds a new line to the current accumulated text.
    /// Todo: this should also take care of newlines with two spaces
    ///
    pub fn add(&mut self, line: &str) {
        if self.buffer.len() > 0 {
            self.buffer.push_str(" ");
        }

        self.buffer.push_str(line);
    }

    pub fn consume(self) -> String {
        self.buffer
    }
}

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

    #[test]
    fn it_works() {
        let mut parser = BlockParser::new("Lorem ipsum\ndolor sit amet");

        assert_eq!(
            Some(Block::Text {
                content: "Lorem ipsum dolor sit amet".to_string(),
            }),
            parser.next()
        );
    }

    #[test]
    fn parsing_headings_works() {
        let mut parser = BlockParser::new("# hello world\n##    level 2\n### three");

        assert_eq!(
            Some(Block::Heading {
                content: "hello world".into(),
                level: HeadingLevel::Level1,
            }),
            parser.next()
        );

        assert_eq!(
            Some(Block::Heading {
                content: "level 2".into(),
                level: HeadingLevel::Level2,
            }),
            parser.next()
        );
    }
}<|endoftext|>


<commit_before><commit_msg>Rename a variable<commit_after><|endoftext|>


<commit_before><commit_msg>crosvm: fix run_vm return values for plugin<commit_after><|endoftext|>


<commit_before><commit_msg>changed to non-copied downloaddb & fixed a magic number UNSTABLE<commit_after><|endoftext|>


<commit_before><commit_msg>decendant check is working<commit_after><|endoftext|>