<commit_before>#![feature(phase)]
#![feature(if_let)]

#[phase(plugin, link)]
extern crate ecs;
extern crate piston;
extern crate sdl2_game_window;
extern crate opengl_graphics;
use std::cell::RefCell;
use std::rand;
use std::rand::Rng;
use std::num::abs;

use opengl_graphics::{
    Gl,
    Texture,
};
use sdl2_game_window::WindowSDL2;
use piston::{
    EventIterator,
    EventSettings,
    WindowSettings,
    RenderArgs,
    UpdateArgs,
};
use piston::graphics::{
    AddBorder,
    AddEllipse,
    AddRectangle,
    AddColor,
    Context,
    Draw,
};
use piston::event::{
    PressEvent,
    RenderEvent,
    UpdateEvent,
    GenericEvent,
};
use piston::input::{
    keyboard,
    Keyboard,
};
use ecs::{
    component,
    Components,
    World,
    WorldBuilder,
    Entity,
    EntityData,
    EntityBuilder,
    EntityModifier,
    Aspect
};
use ecs::system::entitysystem::{
    BulkEntitySystem,
    BulkEntityProcess,
};

static mut update_args: Option<UpdateArgs> = None;
static mut render_args: Option<RenderArgs> = None;

struct DrawSystem {
    gl: RefCell<Gl>,
    render_args: Option<RenderArgs>,
}

impl DrawSystem {
    fn new() -> DrawSystem {
        let opengl = piston::shader_version::opengl::OpenGL_3_2;
        DrawSystem {
            gl: RefCell::new(Gl::new(opengl)),
            render_args: None
        }
    }
}

impl BulkEntityProcess for DrawSystem {
  fn process(&self, es: Vec<&Entity>, data: &mut EntityData) {
    println!("{}", self.render_args.unwrap());
    let args = self.render_args.unwrap();
    let w = args.width as f64;
    let h = args.height as f64;
    let mut glCell = self.gl.borrow_mut();
    let gl = glCell.deref_mut();
    gl.viewport(0, 0, w as i32, h as i32);
    let c = Context::abs(w, h);
    // Clear background.
    c.rgb(0.0, 0.0, 0.0).draw(gl);

    let halfw = w / 2.0;
    let halfh = h / 2.0;
    for e in es.iter() {
      if let Some(ref mut position) = data.borrow::<Position>(*e) {
        let dx = (halfw - position.x);
        let dy = (halfh - position.y);
        let dx2 = dx * dx;
        let dy2 = dy * dy;
        let maxd2 = halfw * halfw + halfh * halfh;
        let d2 = dx2 + dy2;
        let rad = position.rad * (1.0 - d2 / maxd2);
        let ref mut rng = rand::task_rng();
        let l = rng.gen_range(0.8, 1.0);
        c.rgb(0.5 * l, 0.2 * l, 0.8 * l)
          .rect(position.x, position.y, rad, rad)
          .border_width(rng.gen_range(1.0, 3.0))
          .draw(gl);
      }
    }
  }
}

impl RenderProcess for DrawSystem {
    fn set_render_args(&mut self, args: Option<RenderArgs>) {
        self.render_args = args;
    }
    fn get_render_args(&self) -> Option<RenderArgs> {
        self.render_args
    }
}

struct MoveSystem {
    update_args: Option<UpdateArgs>
}

impl MoveSystem {
  fn new() -> MoveSystem {
    MoveSystem { update_args: None }
  }
}

impl BulkEntityProcess for MoveSystem {
  fn process(&self, es: Vec<&Entity>, data: &mut EntityData) {
    println!("{}", self.update_args.unwrap());
    if self.update_args.is_none() { return; }
    let dt = self.update_args.unwrap().dt;
    for e in es.iter() {
      let xv;
      let yv;
      if let Some(ref mut velocity) = data.borrow::<Velocity>(*e) {
          let ref mut rng = rand::task_rng();
          if rng.gen_range(0u, 100u) >= 99 {
            //velocity.y = -velocity.y;
          }
          if rng.gen_range(0u, 100u) >= 99 {
            //velocity.x = -velocity.x;
          }
          xv = velocity.x;
          yv = velocity.y;
      } else {
        return
      }
      if let Some(ref mut position) = data.borrow::<Position>(*e) {
        position.x += xv * dt;
        position.y += yv * dt;
      }
    }
  }
}

impl UpdateProcess for MoveSystem {
    fn set_update_args(&mut self, args: Option<UpdateArgs>) {
        self.update_args = args;
    }
    fn get_update_args(&self) -> Option<UpdateArgs> {
        self.update_args
    }
}

trait UpdateProcess: BulkEntityProcess + 'static {
    fn set_update_args(&mut self, args: Option<UpdateArgs>);
    fn get_update_args(&self) -> Option<UpdateArgs>;
}

struct OnUpdateSystem {
    inner: Box<UpdateProcess>
}

impl OnUpdateSystem {
    fn new(inner: Box<UpdateProcess>) -> OnUpdateSystem {
        OnUpdateSystem { inner: inner }
    }
}

impl BulkEntityProcess for OnUpdateSystem {
  fn preprocess(&mut self, _: &World) {
      unsafe {
          self.inner.set_update_args(update_args);
      }
  }
  fn process(&self, es: Vec<&Entity>, data: &mut EntityData) {
      match self.inner.get_update_args() {
          Some(_) => self.inner.process(es, data),
          None => {}
      }
  }
}

trait RenderProcess: BulkEntityProcess + 'static {
    fn set_render_args(&mut self, args: Option<RenderArgs>);
    fn get_render_args(&self) -> Option<RenderArgs>;
}

struct OnRenderSystem {
    inner: Box<RenderProcess>
}

impl OnRenderSystem {
    fn new(inner: Box<RenderProcess>) -> OnRenderSystem {
        OnRenderSystem { inner: inner }
    }
}

impl BulkEntityProcess for OnRenderSystem {
  fn preprocess(&mut self, _: &World) {
      unsafe {
          self.inner.set_render_args(render_args);
      }
  }
  fn process(&self, es: Vec<&Entity>, data: &mut EntityData) {
      match self.inner.get_render_args() {
          Some(_) => self.inner.process(es, data),
          None => {}
      }
  }
}

component!(Position {
    x: f64,
    y: f64,
    rad: f64
})

component!(Velocity{
    x: f64,
    y: f64
})

fn main() {
    let opengl = piston::shader_version::opengl::OpenGL_3_2;
    let mut window = WindowSDL2::new(
        opengl,
        WindowSettings {
            title: "Shooter".to_string(),
            size: [800, 600],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut worldBuilder = WorldBuilder::new();
    worldBuilder.register_component::<Position>();
    worldBuilder.register_component::<Velocity>();

    let aspect = Aspect::for_all(component_ids!(Position));
    let draw_sys = DrawSystem::new();
    let draw_render = OnRenderSystem::new(box draw_sys);
    let sys = BulkEntitySystem::new(box draw_render, aspect);
    worldBuilder.register_system(box sys);

    let maspect = Aspect::for_all(component_ids!(Position, Velocity));
    let mover = MoveSystem::new();
    let mover_update = OnUpdateSystem::new(box mover);
    let bsys = BulkEntitySystem::new(box mover_update, maspect);
    worldBuilder.register_system(box bsys);

    let ref mut world = worldBuilder.build();

    let numThings: i32 = 80;

    let ref mut rng = rand::task_rng();
    for i in range(0, numThings) {
        let r = 30.0;//rng.gen_range(30.0, 60.0); //(10 + i * 10) as f64;
        let x = (800.0 - r) / 2.0; // (800.0 / numThings as f64) * i as f64;
        let y = (600.0 - r) / 2.0;
        let d = Position { x: x, y: y, rad: r };
        let m = Velocity {
          x: rng.gen_range(-80.0, 80.0),
          y: rng.gen_range(-80.0, 80.0),
        };
        world.build_entity(|c: &mut Components, e: Entity|{
            c.add(&e, d);
            c.add(&e, m);
        });
    }
    let event_settings = EventSettings {
        updates_per_second: 120,
        max_frames_per_second: 60,
    };

    for e in EventIterator::new(&mut window, &event_settings) {
        println!("{}", e);
        continue;
        unsafe {
          render_args = None;
          update_args = None;
        }
        e.press(|button| {
            if button == Keyboard(keyboard::G) {
                println!("G");
            } else if button == Keyboard(keyboard::R) {
                println!("Reset");
            }
        });
        e.update(|args| {
          unsafe { update_args = Some(*args); }
          world.update();
        });
        e.render(|args| {
          unsafe { render_args = Some(*args); }
          world.update();
        });
    }
}
<commit_msg>Systems taking event rc<commit_after>#![feature(phase)]
#![feature(if_let)]

#[phase(plugin, link)]
extern crate ecs;
extern crate piston;
extern crate sdl2_game_window;
extern crate opengl_graphics;
use std::cell::RefCell;
use std::rc::Rc;
use std::rand;
use std::rand::Rng;
use std::num::abs;

use opengl_graphics::{
    Gl,
};
use sdl2_game_window::WindowSDL2;
use piston::{
    EventIterator,
    EventSettings,
    WindowSettings,
};
use piston::graphics::{
    AddBorder,
    AddRectangle,
    AddColor,
    Context,
    Draw,
};
use piston::event::{
    UpdateEvent,
    Event,
    Render,
    Update,
    Input,
};
use piston::input::{
    Focus,
};
use ecs::{
    Components,
    WorldBuilder,
    Entity,
    EntityData,
    EntityBuilder,
    Aspect
};
use ecs::system::entitysystem::{
    BulkEntitySystem,
    BulkEntityProcess,
};

struct DrawSystem {
    gl: RefCell<Gl>,
    event: Rc<RefCell<Event>>,
}

impl DrawSystem {
    fn new(event: Rc<RefCell<Event>>) -> DrawSystem {
        let opengl = piston::shader_version::opengl::OpenGL_3_2;
        DrawSystem {
            gl: RefCell::new(Gl::new(opengl)),
            event: event
        }
    }
}

impl BulkEntityProcess for DrawSystem {
  fn process(&self, es: Vec<&Entity>, data: &mut EntityData) {
    if let &Render(args) = self.event.borrow().deref() {
        let w = args.width as f64;
        let h = args.height as f64;
        let mut gl_cell = self.gl.borrow_mut();
        let gl = gl_cell.deref_mut();
        gl.viewport(0, 0, w as i32, h as i32);
        let c = Context::abs(w, h);
        // Clear background.
        c.rgb(0.0, 0.0, 0.0).draw(gl);

        let halfw = w / 2.0;
        let halfh = h / 2.0;
        for e in es.iter() {
          if let Some(ref mut position) = data.borrow::<Position>(*e) {
            let dx = halfw - position.x;
            let dy = halfh - position.y;
            let dx2 = dx * dx;
            let dy2 = dy * dy;
            let maxd2 = halfw * halfw + halfh * halfh;
            let d2 = dx2 + dy2;
            let rad = position.rad * (1.0 - d2 / maxd2);
            let ref mut rng = rand::task_rng();
            let l = rng.gen_range(0.8, 1.0);
            c.rgb(0.5 * l, 0.2 * l, 0.8 * l)
              .rect(position.x, position.y, rad, rad)
              .border_width(rng.gen_range(1.0, 3.0))
              .draw(gl);
          }
        }
    }
  }
}

struct MoveSystem {
    event: Rc<RefCell<Event>>
}

impl MoveSystem {
  fn new(event: Rc<RefCell<Event>>) -> MoveSystem {
    MoveSystem {
        event: event
    }
  }
}

impl BulkEntityProcess for MoveSystem {
  fn process(&self, es: Vec<&Entity>, data: &mut EntityData) {
    if let &Update(args) = self.event.borrow().deref() {
        let dt = args.dt;
        for e in es.iter() {
          let xv;
          let yv;
          if let Some(ref mut velocity) = data.borrow::<Velocity>(*e) {
              let ref mut rng = rand::task_rng();
              if rng.gen_range(0u, 100u) >= 99 {
                //velocity.y = -velocity.y;
              }
              if rng.gen_range(0u, 100u) >= 99 {
                //velocity.x = -velocity.x;
              }
              xv = velocity.x;
              yv = velocity.y;
          } else {
            return
          }
          if let Some(ref mut position) = data.borrow::<Position>(*e) {
            position.x += xv * dt;
            position.y += yv * dt;
          }
        }
    }
  }
}

component!(Position {
    x: f64,
    y: f64,
    rad: f64
})

component!(Velocity{
    x: f64,
    y: f64
})

fn main() {
    let ecs_event: Rc<RefCell<Event>> =
        Rc::new(
            RefCell::new(Input(Focus(false)))
        );

    let opengl = piston::shader_version::opengl::OpenGL_3_2;
    let mut window = WindowSDL2::new(
        opengl,
        WindowSettings {
            title: "Shooter".to_string(),
            size: [800, 600],
            fullscreen: false,
            exit_on_esc: true,
            samples: 4,
        }
    );

    let mut world_builder = WorldBuilder::new();
    world_builder.register_component::<Position>();
    world_builder.register_component::<Velocity>();

    let aspect = Aspect::for_all(component_ids!(Position));
    let draw_sys = DrawSystem::new(ecs_event.clone());
    let sys = BulkEntitySystem::new(box draw_sys, aspect);
    world_builder.register_system(box sys);

    let maspect = Aspect::for_all(component_ids!(Position, Velocity));
    let move_sys = MoveSystem::new(ecs_event.clone());
    let bsys = BulkEntitySystem::new(box move_sys, maspect);
    world_builder.register_system(box bsys);

    let ref mut world = world_builder.build();

    let num_things: i32 = 80;

    let ref mut rng = rand::task_rng();
    for _ in range(0, num_things) {
        let r = 30.0;
        let x = (800.0 - r) / 2.0;
        let y = (600.0 - r) / 2.0;
        let d = Position { x: x, y: y, rad: r };
        let m = Velocity {
          x: rng.gen_range(-80.0, 80.0),
          y: rng.gen_range(-80.0, 80.0),
        };
        world.build_entity(|c: &mut Components, e: Entity|{
            c.add(&e, d);
            c.add(&e, m);
        });
    }
    let event_settings = EventSettings {
        updates_per_second: 120,
        max_frames_per_second: 60,
    };

    for e in EventIterator::new(&mut window, &event_settings) {
        *ecs_event.borrow_mut() = e.clone();
        world.update();
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

struct Actor {
    // VecDeque is the current recommendation for FIFOs.
    // Right now this is a simple FIFO for messages to be printed.
    messages_queue: VecDeque<String>,
}

impl Actor {
    fn new(messages: VecDeque<String>) -> Actor {
        Actor {
           messages_queue: messages,
        }
    }

    // Right now the send and treat_messages methods are not in the same structs, which is a bad
    // API, this will be changed once the main features are working.
    fn treat_messages(&mut self) {
        if let Some(s) = self.messages_queue.pop_front() {
            println!("{}", s);
        }
    }
}

// The ActorWrapper struct is a way to be able to add Actors to the FIFO while staying safe and
// clean.
struct ActorWrapper {
    // Since the FIFO will be acccessed in a concurrent manner, wrapping it around an Arc and Mutex
    // is needed.
    // This FIFO contains Actors wrapped in the same way for the same reason.
    worker_queue: Arc<Mutex<VecDeque<Arc<Mutex<Actor>>>>>,
    // Having an inner actor is needed as it is extremely messy to have the actor add itself to the
    // FIFO.
    // The Actor is put in an Arc to avoid dangling pointers, and the Mutex is there for concurrent
    // mutability.
    actor: Arc<Mutex<Actor>>,
}

impl ActorWrapper {
    fn new(
        actor: Arc<Mutex<Actor>>,
        queue: Arc<Mutex<VecDeque<Arc<Mutex<Actor>>>>>) -> ActorWrapper {
        ActorWrapper {
            worker_queue: queue,
            actor: actor,
        }
    }

    fn send(&mut self, message: String) {
        {
            let mut actor = self.actor.lock().unwrap();
            actor.messages_queue.push_back(message);
        }

        let mut queue = self.worker_queue.lock().unwrap();
        queue.push_back(self.actor.clone());
    }
}

fn main() {
    let shared_queue: Arc<Mutex<VecDeque<_>>> = Arc::new(Mutex::new(VecDeque::new()));

    let mut actor_1 = ActorWrapper::new(
        Arc::new(Mutex::new(Actor::new(VecDeque::new()))),
        shared_queue.clone());
    let mut actor_2 = ActorWrapper::new(
        Arc::new(Mutex::new(Actor::new(VecDeque::new()))),
        shared_queue.clone());

    // The messages should be printed in this order.
    actor_1.send("Hello world 1-1!".to_string());
    actor_2.send("Hello world 2!".to_string());
    actor_1.send("Hello world 1-2!".to_string());

    loop {
        let mut queue = shared_queue.lock().unwrap();
        if let Some(actor) = queue.pop_front() {
            actor.lock().unwrap().treat_messages();
        }
    }
}
<commit_msg>There is now a thread that pops the workers from the worker FIFO.<commit_after>use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use std::thread;

struct Actor {
    // VecDeque is the current recommendation for FIFOs.
    // Right now this is a simple FIFO for messages to be printed.
    messages_queue: VecDeque<String>,
}

impl Actor {
    fn new(messages: VecDeque<String>) -> Actor {
        Actor {
           messages_queue: messages,
        }
    }

    // Right now the send and treat_messages methods are not in the same structs, which is a bad
    // API, this will be changed once the main features are working.
    fn treat_messages(&mut self) {
        if let Some(s) = self.messages_queue.pop_front() {
            println!("{}", s);
        }
    }
}

// The ActorWrapper struct is a way to be able to add Actors to the FIFO while staying safe and
// clean.
struct ActorWrapper {
    // Since the FIFO will be acccessed in a concurrent manner, wrapping it around an Arc and Mutex
    // is needed.
    // This FIFO contains Actors wrapped in the same way for the same reason.
    worker_queue: Arc<Mutex<VecDeque<Arc<Mutex<Actor>>>>>,
    // Having an inner actor is needed as it is extremely messy to have the actor add itself to the
    // FIFO.
    // The Actor is put in an Arc to avoid dangling pointers, and the Mutex is there for concurrent
    // mutability.
    actor: Arc<Mutex<Actor>>,
}

impl ActorWrapper {
    fn new(
        actor: Arc<Mutex<Actor>>,
        queue: Arc<Mutex<VecDeque<Arc<Mutex<Actor>>>>>) -> ActorWrapper {
        ActorWrapper {
            worker_queue: queue,
            actor: actor,
        }
    }

    fn send(&mut self, message: String) {
        {
            let mut actor = self.actor.lock().unwrap();
            actor.messages_queue.push_back(message);
        }

        let mut queue = self.worker_queue.lock().unwrap();
        queue.push_back(self.actor.clone());
    }
}

fn main() {
    let shared_queue: Arc<Mutex<VecDeque<_>>> = Arc::new(Mutex::new(VecDeque::new()));

    let mut actor_1 = ActorWrapper::new(
        Arc::new(Mutex::new(Actor::new(VecDeque::new()))),
        shared_queue.clone());
    let mut actor_2 = ActorWrapper::new(
        Arc::new(Mutex::new(Actor::new(VecDeque::new()))),
        shared_queue.clone());

    // The messages should be printed in this order.
    actor_1.send("Hello world 1-1!".to_string());
    actor_2.send("Hello world 2!".to_string());
    actor_1.send("Hello world 1-2!".to_string());

    // This clone is needed as the thread takes ownership on its environment, without it we could
    // not clone shared_queue again, and thus we could not create new ActorWrapper.
    let inner_queue = shared_queue.clone();
    let handle = thread::spawn(move || {
        loop {
            let mut queue = inner_queue.lock().unwrap();
            if let Some(actor) = queue.pop_front() {
                actor.lock().unwrap().treat_messages();
            }
        }
    });

    // The message should be printed.
    let mut actor_3 = ActorWrapper::new(
        Arc::new(Mutex::new(Actor::new(VecDeque::new()))),
        shared_queue.clone());
    actor_3.send("Hello world 3!".to_string());

    thread::sleep_ms(1000);
    actor_3.send("Hello world again 3!".to_string());

    // Without it we would return from main.
    handle.join().unwrap();
}
<|endoftext|>


<commit_before>use clap::Clap;
use std::cmp::Ordering;
use std::fs::File;

fn normalize_col(col: &str) -> String {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"\(.*?\)").unwrap();
    }
    let mut col = RE
        .replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace(" ", "_")
        .replace(".", "_")
        .replace("-", "_")
        .replace("/", "_")
        .replace("?", "")
        .replace(",", "_")
        .replace("&", "_")
        .replace("#", "");
    if !col.chars().next().unwrap().is_alphabetic() {
        col = format!("c_{}", col)
    }
    col
}

fn _create_table(db: &mut rusqlite::Connection, table_name: &str, cols: &[String]) {
    let create_columns = cols
        .iter()
        .map(|c| format!("{} varchar", c))
        .collect::<Vec<String>>()
        .join(", ");
    db.execute(
        &format!("CREATE TABLE {} ({})", table_name, create_columns),
        &[] as &[&dyn rusqlite::types::ToSql],
    )
    .unwrap();
}

fn _load_table_from_path(
    db: &mut rusqlite::Connection,
    table_name: &str,
    path: &str,
    delimiter: u8,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
    let mut num_rows = 0;
    let f = File::open(path)?;
    let file_size = f.metadata().unwrap().len();
    let mut reader = csv::ReaderBuilder::new()
        .flexible(true)
        .delimiter(delimiter)
        .from_reader(f);

    let normalized_cols =
        reader
            .headers()?
            .iter()
            .map(normalize_col)
            .fold(vec![], |mut v, orig_col| {
                let mut col = orig_col.clone();
                let mut i = 1;
                while v.contains(&col) {
                    col = format!("{}_{}", orig_col, i);
                    i += 1
                }
                v.push(col);
                v
            });
    _create_table(db, table_name, &normalized_cols);

    let insert_query = format!(
        "INSERT INTO {} VALUES ({})",
        table_name,
        normalized_cols
            .iter()
            .map(|_| "?")
            .collect::<Vec<_>>()
            .join(", ")
    );
    let pb = indicatif::ProgressBar::new(file_size);
    pb.set_style(
        indicatif::ProgressStyle::default_bar()
            .template("[{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})")
            .progress_chars("#>-"),
    );
    let mut records = reader.records();
    let tx = db.transaction().unwrap();
    {
        let mut stmt = tx.prepare(&insert_query).expect("tx.prepare() failed");
        while let Some(row) = records.next() {
            let mut row = row?;
            match row.len().cmp(&normalized_cols.len()) {
                Ordering::Less => {
                    for _ in 0..normalized_cols.len() - row.len() {
                        row.push_field("");
                    }
                }
                Ordering::Greater => {
                    panic!("Too many fields on row {}, fields: {:?}", num_rows + 1, row);
                }
                Ordering::Equal => {}
            }
            stmt.execute(&row).unwrap();

            num_rows += 1;
            if num_rows % 10000 == 0 {
                pb.set_position(records.reader().position().byte())
            }
        }
    }
    tx.commit().unwrap();
    pb.finish();

    println!(
        "Loaded {} rows into {}({})",
        num_rows,
        table_name,
        normalized_cols.join(", "),
    );
    Ok(normalized_cols)
}

struct FromAnySqlType {
    value: String,
}

impl rusqlite::types::FromSql for FromAnySqlType {
    fn column_result(
        value: rusqlite::types::ValueRef<'_>,
    ) -> Result<FromAnySqlType, rusqlite::types::FromSqlError> {
        let result = match value {
            rusqlite::types::ValueRef::Null => "null".to_string(),
            rusqlite::types::ValueRef::Integer(v) => v.to_string(),
            rusqlite::types::ValueRef::Real(v) => v.to_string(),
            rusqlite::types::ValueRef::Blob(v) | rusqlite::types::ValueRef::Text(v) => {
                String::from_utf8(v.to_vec()).unwrap()
            }
        };
        Ok(FromAnySqlType { value: result })
    }
}

fn _prepare_query<'a>(
    conn: &'a mut rusqlite::Connection,
    query: &str,
) -> Result<rusqlite::Statement<'a>, String> {
    conn.prepare(&query).map_err(|e| e.to_string())
}

fn _handle_query(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    let mut stmt = _prepare_query(conn, line)?;

    let mut table = comfy_table::Table::new();
    table.load_preset("││──╞═╪╡┆    ┬┴┌┐└┘");
    table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
    let mut title_row = comfy_table::Row::new();
    for col in stmt.column_names() {
        title_row.add_cell(comfy_table::Cell::new(col));
    }
    table.set_header(title_row);

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        let mut row = comfy_table::Row::new();
        for i in 0..r.column_count() {
            let cell: FromAnySqlType = r.get(i).unwrap();
            row.add_cell(comfy_table::Cell::new(&cell.value));
        }
        table.add_row(row);
    }
    println!("{}", table);
    Ok(())
}

fn _handle_export(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"^\.export\(([\w_\-\./]+)\) (.*)").unwrap();
    }
    let caps = RE
        .captures(line)
        .ok_or_else(|| "Must match `.export(file-name) SQL`".to_owned())?;
    let destination_path = &caps[1];
    let query = &caps[2];

    let mut stmt = _prepare_query(conn, query)?;

    let mut writer = csv::Writer::from_path(destination_path).unwrap();
    writer.write_record(stmt.column_names()).unwrap();

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        writer
            .write_record((0..r.column_count()).map(|i| {
                let cell: FromAnySqlType = r.get(i).unwrap();
                cell.value
            }))
            .unwrap();
    }

    Ok(())
}

fn _process_query(conn: &mut rusqlite::Connection, line: &str) {
    let result = if line.starts_with(".export") {
        _handle_export(conn, line)
    } else {
        _handle_query(conn, line)
    };
    if let Err(e) = result {
        println!("{}", e);
    }
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 4] = [b' ', b'(', b')', b','];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        SimpleWordCompleter { words }
    }
}

impl rustyline::Helper for SimpleWordCompleter {}

impl rustyline::hint::Hinter for SimpleWordCompleter {
    fn hint(&self, _line: &str, _pos: usize, _ctx: &rustyline::Context<'_>) -> Option<String> {
        None
    }
}

impl rustyline::highlight::Highlighter for SimpleWordCompleter {}

impl rustyline::validate::Validator for SimpleWordCompleter {}

impl rustyline::completion::Completer for SimpleWordCompleter {
    type Candidate = String;

    fn complete(
        &self,
        line: &str,
        pos: usize,
        _ctx: &rustyline::Context<'_>,
    ) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) = rustyline::completion::extract_word(line, pos, None, &BREAK_CHARS);

        let matches = self
            .words
            .iter()
            .filter(|w| w.starts_with(word))
            .cloned()
            .collect();
        Ok((start, matches))
    }
}

#[derive(Clap)]
struct Opts {
    #[clap(long, about = "Use ',' as the delimiter for the CSV")]
    comma: bool,
    #[clap(long, about = "Use '|' as the delimiter for the CSV")]
    pipe: bool,
    #[clap(long, about = "Use '\\t' as the delimiter for the CSV")]
    tab: bool,

    #[clap()]
    paths: Vec<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let opts = Opts::parse();

    let delim = match (opts.comma, opts.pipe, opts.tab) {
        (true, false, false) | (false, false, false) => b',',
        (false, true, false) => b'|',
        (false, false, true) => b'\t',
        _ => {
            eprintln!("Can't pass more than one of --comma, --pipe, and --tab");
            std::process::exit(1);
        }
    };

    let mut conn = rusqlite::Connection::open_in_memory().unwrap();

    let mut base_words = [
        "distinct", "select", "from", "group", "by", "order", "where", "count", "limit", "offset",
        ".export",
    ]
    .iter()
    .map(|&s| s.to_string())
    .collect::<Vec<String>>();

    if opts.paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", &opts.paths[0], delim)?;
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in opts.paths.iter().enumerate() {
            let mut col_names =
                _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path, delim)?;
            base_words.append(&mut col_names);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                _process_query(&mut conn, &line);
                rl.add_history_entry(line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }

    Ok(())
}

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

    #[test]
    fn test_normalize_col() {
        for (value, expected) in &[
            ("abc", "abc"),
            ("abc (123)", "abc"),
            ("2/6/2000", "c_2_6_2000"),
            ("COMBO#", "combo"),
        ] {
            assert_eq!(&&normalize_col(value), expected);
        }
    }
}
<commit_msg>Added .schema command<commit_after>use clap::Clap;
use std::cmp::Ordering;
use std::fs::File;

fn normalize_col(col: &str) -> String {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"\(.*?\)").unwrap();
    }
    let mut col = RE
        .replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace(" ", "_")
        .replace(".", "_")
        .replace("-", "_")
        .replace("/", "_")
        .replace("?", "")
        .replace(",", "_")
        .replace("&", "_")
        .replace("#", "");
    if !col.chars().next().unwrap().is_alphabetic() {
        col = format!("c_{}", col)
    }
    col
}

fn _create_table(db: &mut rusqlite::Connection, table_name: &str, cols: &[String]) {
    let create_columns = cols
        .iter()
        .map(|c| format!("{} varchar", c))
        .collect::<Vec<String>>()
        .join(", ");
    db.execute(
        &format!("CREATE TABLE {} ({})", table_name, create_columns),
        &[] as &[&dyn rusqlite::types::ToSql],
    )
    .unwrap();
}

fn _load_table_from_path(
    db: &mut rusqlite::Connection,
    table_name: &str,
    path: &str,
    delimiter: u8,
) -> Result<Vec<String>, Box<dyn std::error::Error>> {
    let mut num_rows = 0;
    let f = File::open(path)?;
    let file_size = f.metadata().unwrap().len();
    let mut reader = csv::ReaderBuilder::new()
        .flexible(true)
        .delimiter(delimiter)
        .from_reader(f);

    let normalized_cols =
        reader
            .headers()?
            .iter()
            .map(normalize_col)
            .fold(vec![], |mut v, orig_col| {
                let mut col = orig_col.clone();
                let mut i = 1;
                while v.contains(&col) {
                    col = format!("{}_{}", orig_col, i);
                    i += 1
                }
                v.push(col);
                v
            });
    _create_table(db, table_name, &normalized_cols);

    let insert_query = format!(
        "INSERT INTO {} VALUES ({})",
        table_name,
        normalized_cols
            .iter()
            .map(|_| "?")
            .collect::<Vec<_>>()
            .join(", ")
    );
    let pb = indicatif::ProgressBar::new(file_size);
    pb.set_style(
        indicatif::ProgressStyle::default_bar()
            .template("[{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})")
            .progress_chars("#>-"),
    );
    let mut records = reader.records();
    let tx = db.transaction().unwrap();
    {
        let mut stmt = tx.prepare(&insert_query).expect("tx.prepare() failed");
        while let Some(row) = records.next() {
            let mut row = row?;
            match row.len().cmp(&normalized_cols.len()) {
                Ordering::Less => {
                    for _ in 0..normalized_cols.len() - row.len() {
                        row.push_field("");
                    }
                }
                Ordering::Greater => {
                    panic!("Too many fields on row {}, fields: {:?}", num_rows + 1, row);
                }
                Ordering::Equal => {}
            }
            stmt.execute(&row).unwrap();

            num_rows += 1;
            if num_rows % 10000 == 0 {
                pb.set_position(records.reader().position().byte())
            }
        }
    }
    tx.commit().unwrap();
    pb.finish();

    println!(
        "Loaded {} rows into {}({})",
        num_rows,
        table_name,
        normalized_cols.join(", "),
    );
    Ok(normalized_cols)
}

struct FromAnySqlType {
    value: String,
}

impl rusqlite::types::FromSql for FromAnySqlType {
    fn column_result(
        value: rusqlite::types::ValueRef<'_>,
    ) -> Result<FromAnySqlType, rusqlite::types::FromSqlError> {
        let result = match value {
            rusqlite::types::ValueRef::Null => "null".to_string(),
            rusqlite::types::ValueRef::Integer(v) => v.to_string(),
            rusqlite::types::ValueRef::Real(v) => v.to_string(),
            rusqlite::types::ValueRef::Blob(v) | rusqlite::types::ValueRef::Text(v) => {
                String::from_utf8(v.to_vec()).unwrap()
            }
        };
        Ok(FromAnySqlType { value: result })
    }
}

fn _prepare_query<'a>(
    conn: &'a mut rusqlite::Connection,
    query: &str,
) -> Result<rusqlite::Statement<'a>, String> {
    conn.prepare(&query).map_err(|e| e.to_string())
}

fn _handle_query(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    let mut stmt = _prepare_query(conn, line)?;

    let mut table = comfy_table::Table::new();
    table.load_preset("││──╞═╪╡┆    ┬┴┌┐└┘");
    table.set_content_arrangement(comfy_table::ContentArrangement::Dynamic);
    let mut title_row = comfy_table::Row::new();
    for col in stmt.column_names() {
        title_row.add_cell(comfy_table::Cell::new(col));
    }
    table.set_header(title_row);

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        let mut row = comfy_table::Row::new();
        for i in 0..r.column_count() {
            let cell: FromAnySqlType = r.get(i).unwrap();
            row.add_cell(comfy_table::Cell::new(&cell.value));
        }
        table.add_row(row);
    }
    println!("{}", table);
    Ok(())
}

fn _handle_export(conn: &mut rusqlite::Connection, line: &str) -> Result<(), String> {
    lazy_static::lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"^\.export\(([\w_\-\./]+)\) (.*)").unwrap();
    }
    let caps = RE
        .captures(line)
        .ok_or_else(|| "Must match `.export(file-name) SQL`".to_owned())?;
    let destination_path = &caps[1];
    let query = &caps[2];

    let mut stmt = _prepare_query(conn, query)?;

    let mut writer = csv::Writer::from_path(destination_path).unwrap();
    writer.write_record(stmt.column_names()).unwrap();

    let mut results = stmt.query(&[] as &[&dyn rusqlite::types::ToSql]).unwrap();
    while let Ok(Some(r)) = results.next() {
        writer
            .write_record((0..r.column_count()).map(|i| {
                let cell: FromAnySqlType = r.get(i).unwrap();
                cell.value
            }))
            .unwrap();
    }

    Ok(())
}

fn _process_query(conn: &mut rusqlite::Connection, line: &str) {
    let result = if line.starts_with(".export") {
        _handle_export(conn, line)
    } else if line.starts_with(".schema") {
        _handle_query(
            conn,
            "SELECT sql AS schema FROM sqlite_master WHERE name like 't%'",
        )
    } else {
        _handle_query(conn, line)
    };
    if let Err(e) = result {
        println!("{}", e);
    }
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 4] = [b' ', b'(', b')', b','];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        SimpleWordCompleter { words }
    }
}

impl rustyline::Helper for SimpleWordCompleter {}

impl rustyline::hint::Hinter for SimpleWordCompleter {
    fn hint(&self, _line: &str, _pos: usize, _ctx: &rustyline::Context<'_>) -> Option<String> {
        None
    }
}

impl rustyline::highlight::Highlighter for SimpleWordCompleter {}

impl rustyline::validate::Validator for SimpleWordCompleter {}

impl rustyline::completion::Completer for SimpleWordCompleter {
    type Candidate = String;

    fn complete(
        &self,
        line: &str,
        pos: usize,
        _ctx: &rustyline::Context<'_>,
    ) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) = rustyline::completion::extract_word(line, pos, None, &BREAK_CHARS);

        let matches = self
            .words
            .iter()
            .filter(|w| w.starts_with(word))
            .cloned()
            .collect();
        Ok((start, matches))
    }
}

#[derive(Clap)]
struct Opts {
    #[clap(long, about = "Use ',' as the delimiter for the CSV")]
    comma: bool,
    #[clap(long, about = "Use '|' as the delimiter for the CSV")]
    pipe: bool,
    #[clap(long, about = "Use '\\t' as the delimiter for the CSV")]
    tab: bool,

    #[clap()]
    paths: Vec<String>,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let opts = Opts::parse();

    let delim = match (opts.comma, opts.pipe, opts.tab) {
        (true, false, false) | (false, false, false) => b',',
        (false, true, false) => b'|',
        (false, false, true) => b'\t',
        _ => {
            eprintln!("Can't pass more than one of --comma, --pipe, and --tab");
            std::process::exit(1);
        }
    };

    let mut conn = rusqlite::Connection::open_in_memory().unwrap();

    let mut base_words = [
        "distinct", "select", "from", "group", "by", "order", "where", "count", "limit", "offset",
        ".export", ".schema",
    ]
    .iter()
    .map(|&s| s.to_string())
    .collect::<Vec<String>>();

    if opts.paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", &opts.paths[0], delim)?;
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in opts.paths.iter().enumerate() {
            let mut col_names =
                _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path, delim)?;
            base_words.append(&mut col_names);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                _process_query(&mut conn, &line);
                rl.add_history_entry(line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }

    Ok(())
}

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

    #[test]
    fn test_normalize_col() {
        for (value, expected) in &[
            ("abc", "abc"),
            ("abc (123)", "abc"),
            ("2/6/2000", "c_2_6_2000"),
            ("COMBO#", "combo"),
        ] {
            assert_eq!(&&normalize_col(value), expected);
        }
    }
}
<|endoftext|>


<commit_before>extern crate ansi_term;
#[macro_use]
extern crate clap;
extern crate hyper;
extern crate libzou;
extern crate num_cpus;

use clap::{App, Arg};
use libzou::cargo_helper::get_cargo_info;
use libzou::download::download_chunks;
use libzou::filesize::format_filesize;
use libzou::util::prompt_user;
use libzou::write::OutputFileWriter;
#[macro_use]
mod logs;
use std::fs::{File, remove_file};
use std::path::Path;
use std::process::exit;

fn main() {

    // Parse arguments

    let argparse = App::new("Zou")
        .about("Zou, a simple and fast download accelerator, written in Rust.")
        .version(crate_version!())
        .arg(Arg::with_name("file")
                 .long("file")
                 .short("f")
                 .takes_value(true)
                 .help("The local file to save the remote content file"))
        .arg(Arg::with_name("threads")
                 .long("threads")
                 .short("t")
                 .takes_value(true)
                 .help("Threads which can use to download"))
        .arg(Arg::with_name("debug")
                 .long("debug")
                 .short("d")
                 .help("Active the debug mode"))
        .arg(Arg::with_name("force")
                 .long("force")
                 .help("Assume Yes to all queries and do not prompt"))
        .arg(Arg::with_name("mirrors")
                 .long("mirrors")
                 .short("m")
                 .multiple(true)
                 .takes_value(true)
                 .help("Download using a list of mirrors - the list of mirrors is used WITH the original URL"))
        .arg(Arg::with_name("ssl_support")
                .long("ssl_support")
                .short("s")
                .help("Active the SSL Client to download files"))
        .arg(Arg::with_name("url")
            .index(1)
            //.multiple(true)
            .required(true))
        .get_matches();

    // Get informations from arguments

    // Get the URL as a Path structure
    let url = Path::new(argparse.value_of("url").unwrap());

    // Set the mirrors vectors
    let mut servers_urls: Vec<&str> = match url.parent() {
        Some(parent) => vec![parent.to_str().unwrap()],
        None => vec![],
    };
    // Set given mirrors
    if argparse.is_present("mirrors") {
        let mirrors_vec: Vec<&str> = argparse.values_of("mirrors").unwrap().collect();
        for mirror in mirrors_vec {
            servers_urls.push(mirror);
        }
    }

    // Get the path filename
    let filename = url.file_name().unwrap().to_str().unwrap();

    // Check if multi-threaded download is possible
    let mut threads: usize = value_t!(argparse, "threads", usize)
        .and_then(|v| if v != 0 {
            Ok(v)
        } else {
            Err(clap::Error::with_description(
                "Cannot download a file using 0 thread",
                clap::ErrorKind::InvalidValue,
            ))
        })
        .unwrap_or(num_cpus::get_physical());

    if argparse.is_present("debug") {
        info!(&format!("version: {}", crate_version!()));
        info!(&format!("file: {}", filename));
        info!(&format!("threads: {}", threads));
    }

    let local_path = Path::new(&filename);

    if local_path.exists() {
        if local_path.is_dir() {
            epanic!(
                "The local path to store the remote content is already exists, \
                        and is a directory!"
            );
        }
        if !argparse.is_present("force") {
            let user_input = prompt_user(
                "The path to store the file already exists! \
                                          Do you want to override it? [y/N]",
            );
            if !(user_input == "y" || user_input == "Y") {
                exit(0);
            }
        } else {
            warning!(
                "The path to store the file already exists! \
                                 It is going to be overriden."
            );
        }
    }

    let cargo_info = get_cargo_info(filename, servers_urls).expect("fail to parse url");
    info!(&format!(
        "Remote content length: {}",
        format_filesize(cargo_info.content_length)
    ));

    let local_file = File::create(local_path).expect("[ERROR] Cannot create a file !");

    local_file.set_len(cargo_info.content_length).expect(
        "Cannot extend local file !",
    );
    let out_file = OutputFileWriter::new(local_file);

    // If the server does not accept PartialContent status, download the remote file
    // using only one thread
    if !cargo_info.accept_partialcontent {
        warning!(
            "The remote server does not accept PartialContent status! \
                             Downloading the remote file using one thread."
        );
        threads = 1;
    }

    if download_chunks(cargo_info, out_file, threads as u64, filename) {
        ok!(&format!(
            "Your download is available in {}",
            local_path.to_str().unwrap()
        ));
    } else {
        // If the file is not ok, delete it from the file system
        error!("Download failed! An error occured - erasing file... ");
        if remove_file(local_path).is_err() {
            error!("Cannot remove downloaded file!");
        }
    }

}
<commit_msg>Usage of Config for ssl support<commit_after>extern crate ansi_term;
#[macro_use]
extern crate clap;
extern crate hyper;
extern crate libzou;
extern crate num_cpus;

use clap::{App, Arg};
use libzou::cargo_helper::get_cargo_info;
use libzou::download::download_chunks;
use libzou::filesize::format_filesize;
use libzou::util::prompt_user;
use libzou::write::OutputFileWriter;
#[macro_use]
mod logs;
use std::fs::{File, remove_file};
use std::path::Path;
use std::process::exit;

fn main() {

    // Parse arguments

    let argparse = App::new("Zou")
        .about("Zou, a simple and fast download accelerator, written in Rust.")
        .version(crate_version!())
        .arg(Arg::with_name("file")
                 .long("file")
                 .short("f")
                 .takes_value(true)
                 .help("The local file to save the remote content file"))
        .arg(Arg::with_name("threads")
                 .long("threads")
                 .short("t")
                 .takes_value(true)
                 .help("Threads which can use to download"))
        .arg(Arg::with_name("debug")
                 .long("debug")
                 .short("d")
                 .help("Active the debug mode"))
        .arg(Arg::with_name("force")
                 .long("force")
                 .help("Assume Yes to all queries and do not prompt"))
        .arg(Arg::with_name("mirrors")
                 .long("mirrors")
                 .short("m")
                 .multiple(true)
                 .takes_value(true)
                 .help("Download using a list of mirrors - the list of mirrors is used WITH the original URL"))
        .arg(Arg::with_name("ssl_support")
                .long("ssl_support")
                .short("s")
                .help("Active the SSL Client to download files"))
        .arg(Arg::with_name("url")
            .index(1)
            //.multiple(true)
            .required(true))
        .get_matches();

    // Get informations from arguments

    // Get the URL as a Path structure
    let url = Path::new(argparse.value_of("url").unwrap());

    // Set the mirrors vectors
    let mut servers_urls: Vec<&str> = match url.parent() {
        Some(parent) => vec![parent.to_str().unwrap()],
        None => vec![],
    };
    // Set given mirrors
    if argparse.is_present("mirrors") {
        let mirrors_vec: Vec<&str> = argparse.values_of("mirrors").unwrap().collect();
        for mirror in mirrors_vec {
            servers_urls.push(mirror);
        }
    }

    // Get the path filename
    let filename = url.file_name().unwrap().to_str().unwrap();

    // Check if multi-threaded download is possible
    let mut threads: usize = value_t!(argparse, "threads", usize)
        .and_then(|v| if v != 0 {
            Ok(v)
        } else {
            Err(clap::Error::with_description(
                "Cannot download a file using 0 thread",
                clap::ErrorKind::InvalidValue,
            ))
        })
        .unwrap_or(num_cpus::get_physical());

    if argparse.is_present("debug") {
        info!(&format!("version: {}", crate_version!()));
        info!(&format!("file: {}", filename));
        info!(&format!("threads: {}", threads));
    }

    let local_path = Path::new(&filename);

    if local_path.exists() {
        if local_path.is_dir() {
            epanic!(
                "The local path to store the remote content is already exists, \
                        and is a directory!"
            );
        }
        if !argparse.is_present("force") {
            let user_input = prompt_user(
                "The path to store the file already exists! \
                                          Do you want to override it? [y/N]",
            );
            if !(user_input == "y" || user_input == "Y") {
                exit(0);
            }
        } else {
            warning!(
                "The path to store the file already exists! \
                                 It is going to be overriden."
            );
        }
    }

    let ssl_support = argparse.is_present("ssl_support");

    let cargo_info =
        get_cargo_info(filename, servers_urls, ssl_support).expect("fail to parse url");
    info!(&format!(
        "Remote content length: {}",
        format_filesize(cargo_info.content_length)
    ));

    let local_file = File::create(local_path).expect("[ERROR] Cannot create a file !");

    local_file.set_len(cargo_info.content_length).expect(
        "Cannot extend local file !",
    );
    let out_file = OutputFileWriter::new(local_file);

    // If the server does not accept PartialContent status, download the remote file
    // using only one thread
    if !cargo_info.accept_partialcontent {
        warning!(
            "The remote server does not accept PartialContent status! \
                             Downloading the remote file using one thread."
        );
        threads = 1;
    }

    if download_chunks(cargo_info, out_file, threads as u64, filename, ssl_support) {
        ok!(&format!(
            "Your download is available in {}",
            local_path.to_str().unwrap()
        ));
    } else {
        // If the file is not ok, delete it from the file system
        error!("Download failed! An error occured - erasing file... ");
        if remove_file(local_path).is_err() {
            error!("Cannot remove downloaded file!");
        }
    }

}
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![feature(unsafe_no_drop_flag)]
#![feature(scoped)]

extern crate rand;

mod types;
mod config;
mod player;
mod zobrist;
mod cell;
mod field;
mod uct;
mod bot;

use std::io;
use std::io::{Read, Write};
use std::str::FromStr;
use std::string::ToString;
use types::Coord;
use bot::Bot;

fn write_author<T: Write>(output: &mut T, id: u32) {
  output.write_all("= ".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" author kurnevsky_evgeny\n".as_bytes()).ok();
}

fn write_author_error<T: Write>(output: &mut T, id: u32) {
  output.write_all("? \n".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" author\n".as_bytes()).ok();
}

fn write_init<T: Write>(output: &mut T, id: u32) {
  output.write_all("= ".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" init\n".as_bytes()).ok();
}

fn write_init_error<T: Write>(output: &mut T, id: u32) {
  output.write_all("? \n".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" init\n".as_bytes()).ok();
}

fn write_error<T: Write>(output: &mut T, id: u32) {
  output.write_all("? \n".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" input_error\n".as_bytes()).ok();
}

fn main() {
  let mut input = io::stdin();
  let mut output = io::stdout();
  let mut bot = None;
  let mut s = String::new();
  loop {
    input.read_to_string(&mut s).ok();
    let mut split = s.split(' ').fuse();
    if let Some(id) = split.next().and_then(|id_str| u32::from_str(id_str).ok()) {
      match split.next() {
        Some("author") => {
          if split.next().is_some() {
            write_author_error(&mut output, id);
          } else {
            write_author(&mut output, id);
          }
        },
        Some("init") => {
          let x_option = split.next().and_then(|x_str| Coord::from_str(x_str).ok());
          let y_option = split.next().and_then(|y_str| Coord::from_str(y_str).ok());;
          let seed_option = split.next();
          if split.next().is_some() {
            write_init_error(&mut output, id);
          } else if let (Some(x), Some(y), Some(seed)) = (x_option, y_option, seed_option) {
            bot = Some(Bot::new(x, y));
            write_init(&mut output, id);
          } else {
            write_init_error(&mut output, id);
          }
        },
        _ => {
          write_error(&mut output, id);
        }
      }
    } else {
      write_error(&mut output, 0);
    }
  }
}
<commit_msg>Bugfix.<commit_after>#![allow(dead_code)]
#![feature(unsafe_no_drop_flag)]
#![feature(scoped)]

extern crate rand;

mod types;
mod config;
mod player;
mod zobrist;
mod cell;
mod field;
mod uct;
mod bot;

use std::io;
use std::io::{Read, Write};
use std::str::FromStr;
use std::string::ToString;
use types::Coord;
use bot::Bot;

fn write_author<T: Write>(output: &mut T, id: u32) {
  output.write_all("= ".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" author kurnevsky_evgeny\n".as_bytes()).ok();
}

fn write_author_error<T: Write>(output: &mut T, id: u32) {
  output.write_all("? ".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" author\n".as_bytes()).ok();
}

fn write_init<T: Write>(output: &mut T, id: u32) {
  output.write_all("= ".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" init\n".as_bytes()).ok();
}

fn write_init_error<T: Write>(output: &mut T, id: u32) {
  output.write_all("? ".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" init\n".as_bytes()).ok();
}

fn write_error<T: Write>(output: &mut T, id: u32) {
  output.write_all("? ".as_bytes()).ok();
  output.write_all(id.to_string().as_bytes()).ok();
  output.write_all(" input_error\n".as_bytes()).ok();
}

fn main() {
  let mut input = io::stdin();
  let mut output = io::stdout();
  let mut bot = None;
  let mut s = String::new();
  loop {
    input.read_to_string(&mut s).ok();
    let mut split = s.split(' ').fuse();
    if let Some(id) = split.next().and_then(|id_str| u32::from_str(id_str).ok()) {
      match split.next() {
        Some("author") => {
          if split.next().is_some() {
            write_author_error(&mut output, id);
          } else {
            write_author(&mut output, id);
          }
        },
        Some("init") => {
          let x_option = split.next().and_then(|x_str| Coord::from_str(x_str).ok());
          let y_option = split.next().and_then(|y_str| Coord::from_str(y_str).ok());;
          let seed_option = split.next();
          if split.next().is_some() {
            write_init_error(&mut output, id);
          } else if let (Some(x), Some(y), Some(seed)) = (x_option, y_option, seed_option) {
            bot = Some(Bot::new(x, y));
            write_init(&mut output, id);
          } else {
            write_init_error(&mut output, id);
          }
        },
        _ => {
          write_error(&mut output, id);
        }
      }
    } else {
      write_error(&mut output, 0);
    }
  }
}
<|endoftext|>


<commit_before>//
// main.rs
// Copyright (C) 2017 Szymon Urbaś <szymon.urbas@aol.com>
// Distributed under terms of the BSD (2-clause) license.
//
// Created on: 13 Mar 2017 21:03:41 +0100 (CET)
//

extern crate rand;
extern crate cursive;

use std::thread;
use std::time;

mod process;
mod scheduler;
mod fcfs;
mod tui;

use scheduler::*;
use tui::*;

/// Length of a single system clock tick (frequency of actual, real time)
const CLOCK_HZ: u64 = 50;
/// Switch context every <value> clock ticks
const SYSTEM_HZ: usize = 8;

fn main() {
  let mut tui = tui::new();

  run_simulation(&mut tui, fcfs::new(), vec![8, 8, 8, 8, 8, 8, 8, 64]);
  run_simulation(&mut tui, fcfs::new(), vec![64, 8, 8, 8, 8, 8, 8, 8]);
  run_simulation(&mut tui, fcfs::new(), vec![8, 8, 8, 32, 32, 6, 8, 8]);

  loop {}
}

fn run_simulation<S>(mut tui: &mut Tui, mut scheduler: S, mut process_list: Vec<usize>)
where S: Scheduler {
  let mut clock_tick = 0;
  let mut process_spawner = process::new_spawner();

  tui.set_header(format!("Using algorithm: {}", scheduler.name()));
  tui.debug(format!("{:05}: Starting simulation using {}", clock_tick, scheduler.name()));

  // vectors only support the pop (from the back) operation so
  // reverse it (so we pop from the front)
  process_list.reverse();

  // Add the equivalent of the 'init' process
  scheduler.add_process(process_spawner.spawn(process_list.pop().unwrap()));

  loop {
    // update the process view
    scheduler.list_processes(&mut tui);
    // update all the views
    tui.update();

    if !scheduler.has_processes() {
      // if there's no more processes - end the simulation
      // if a process can only be created by another process - there's
      // nothing else to do
      break;
    }

    // simulate executing the current process
    tui.debug(format!("{:05}: Executing {}", clock_tick, scheduler.current_proc().unwrap().name));
    scheduler.current_proc_mut().unwrap().record_execution();

    // Simulate other processes creating new processes
    // Assume that you can't create new processes, if there's none already
    if clock_tick % SYSTEM_HZ == 0 {
      if let Some(burst_time) = process_list.pop() {
        let new_proc = process_spawner.spawn(burst_time);
        tui.debug(format!("{:05}: Spawning {}", clock_tick, new_proc.name));
        scheduler.add_process(new_proc);
      }
    }

    if scheduler.current_proc().unwrap().done_executing() {
      tui.debug(format!("{:05}: Killing process {}", clock_tick, scheduler.current_proc().unwrap().name));
      scheduler.kill_current_proc();
    }

    if scheduler.has_processes() {
      if clock_tick % SYSTEM_HZ == SYSTEM_HZ - 1 {
        tui.debug(format!("{:05}: Triggering a scheduling round", clock_tick));
        scheduler.schedule();
        tui.debug(format!("{:05}: {} was waiting {} clock ticks", clock_tick, scheduler.current_proc().unwrap().name, scheduler.current_proc().unwrap().waiting_time));
      }

      // increase the waiting time for every process
      scheduler.increase_waiting_times();
    }

    thread::sleep(time::Duration::from_millis(1000 / CLOCK_HZ));

    clock_tick += 1;
  }
}

/*
 * vi: ts=2 sw=2 expandtab
 */

<commit_msg>Calculate the average waiting time in every simulation run<commit_after>//
// main.rs
// Copyright (C) 2017 Szymon Urbaś <szymon.urbas@aol.com>
// Distributed under terms of the BSD (2-clause) license.
//
// Created on: 13 Mar 2017 21:03:41 +0100 (CET)
//

extern crate rand;
extern crate cursive;

use std::thread;
use std::time;

mod process;
mod scheduler;
mod fcfs;
mod tui;

use scheduler::*;
use tui::*;

/// Length of a single system clock tick (frequency of actual, real time)
const CLOCK_HZ: u64 = 50;
/// Switch context every <value> clock ticks
const SYSTEM_HZ: usize = 8;

fn main() {
  let mut tui = tui::new();

  run_simulation(&mut tui, fcfs::new(), vec![8, 8, 8, 8, 8, 8, 8, 64]);
  run_simulation(&mut tui, fcfs::new(), vec![64, 8, 8, 8, 8, 8, 8, 8]);
  run_simulation(&mut tui, fcfs::new(), vec![8, 8, 8, 32, 32, 6, 8, 8]);

  loop {}
}

fn run_simulation<S>(mut tui: &mut Tui, mut scheduler: S, mut process_list: Vec<usize>) -> f64
where S: Scheduler {
  let mut clock_tick = 0;
  let mut process_spawner = process::new_spawner();
  let mut average_waiting_time = 0f64;
  let mut num_of_spawned_procs = 1;

  tui.set_header(format!("Using algorithm: {}", scheduler.name()));
  tui.debug(format!("{:05}: Starting simulation using {}", clock_tick, scheduler.name()));

  // vectors only support the pop (from the back) operation so
  // reverse it (so we pop from the front)
  process_list.reverse();

  // Add the equivalent of the 'init' process
  scheduler.add_process(process_spawner.spawn(process_list.pop().unwrap()));

  loop {
    // update the process view
    scheduler.list_processes(&mut tui);
    // update all the views
    tui.update();

    if !scheduler.has_processes() {
      // if there's no more processes - end the simulation
      // if a process can only be created by another process - there's
      // nothing else to do
      break;
    }

    // simulate executing the current process
    tui.debug(format!("{:05}: Executing {}", clock_tick, scheduler.current_proc().unwrap().name));
    scheduler.current_proc_mut().unwrap().record_execution();

    // Simulate other processes creating new processes
    // Assume that you can't create new processes, if there's none already
    if clock_tick % SYSTEM_HZ == 0 {
      if let Some(burst_time) = process_list.pop() {
        let new_proc = process_spawner.spawn(burst_time);
        tui.debug(format!("{:05}: Spawning {}", clock_tick, new_proc.name));
        scheduler.add_process(new_proc);
        num_of_spawned_procs += 1;
      }
    }

    if scheduler.current_proc().unwrap().done_executing() {
      tui.debug(format!("{:05}: Killing process {}", clock_tick, scheduler.current_proc().unwrap().name));
      scheduler.kill_current_proc();
    }

    if scheduler.has_processes() {
      if clock_tick % SYSTEM_HZ == SYSTEM_HZ - 1 {
        tui.debug(format!("{:05}: Triggering a scheduling round", clock_tick));
        scheduler.schedule();
        tui.debug(format!("{:05}: {} was waiting {} clock ticks", clock_tick, scheduler.current_proc().unwrap().name, scheduler.current_proc().unwrap().waiting_time));
        average_waiting_time -= average_waiting_time / num_of_spawned_procs as f64;
        average_waiting_time += scheduler.current_proc().unwrap().waiting_time as f64 / num_of_spawned_procs as f64;
      }

      // increase the waiting time for every process
      scheduler.increase_waiting_times();
    }

    thread::sleep(time::Duration::from_millis(1000 / CLOCK_HZ));

    clock_tick += 1;
  }

  average_waiting_time
}

/*
 * vi: ts=2 sw=2 expandtab
 */

<|endoftext|>


<commit_before>mod raw {
    extern crate libc;

    #[allow(non_camel_case_types)]
    pub type wl_display = libc::c_void;

    #[link(name = "wayland-client")]
    extern {
        pub fn wl_display_connect(name: *const u8) -> *mut wl_display;
        pub fn wl_display_disconnect(display: *mut wl_display);
    }
}

pub struct Display {
    ptr: *mut raw::wl_display
}

impl Display {
    pub fn new() -> Display {
        unsafe {
            let ptr = raw::wl_display_connect(std::ptr::null());
            assert!(!ptr.is_null());
            Display { ptr: ptr }
        }
    }
}

impl Drop for Display {
    fn drop(&mut self) {
        unsafe {
            raw::wl_display_disconnect(self.ptr);
        }
    }
}

fn main() {
    let logfile_path = match std::os::homedir() {
        Some(ref p) => p.join(".eyl-shell.log"),
        None        => fail!("finding homedir")
    };
    let mut logfile = std::io::File::create(&logfile_path);
    let display = Display::new();
    match logfile.write(b"Connected to display\n") {
        Ok(()) => (),
        Err(_) => fail!("writing to logfile")
    }
}
<commit_msg>Clean up the raw module a bit<commit_after>mod raw {
    extern crate libc;

    use self::libc::{c_char, c_void};

    #[allow(non_camel_case_types)]
    pub type wl_display = c_void;

    #[link(name = "wayland-client")]
    extern {
        pub fn wl_display_connect(name: *const c_char) -> *mut wl_display;
        pub fn wl_display_disconnect(display: *mut wl_display);
    }
}

pub struct Display {
    ptr: *mut raw::wl_display
}

impl Display {
    pub fn new() -> Display {
        unsafe {
            let ptr = raw::wl_display_connect(std::ptr::null());
            assert!(!ptr.is_null());
            Display { ptr: ptr }
        }
    }
}

impl Drop for Display {
    fn drop(&mut self) {
        unsafe {
            raw::wl_display_disconnect(self.ptr);
        }
    }
}

fn main() {
    let logfile_path = match std::os::homedir() {
        Some(ref p) => p.join(".eyl-shell.log"),
        None        => fail!("finding homedir")
    };
    let mut logfile = std::io::File::create(&logfile_path);
    let display = Display::new();
    match logfile.write(b"Connected to display\n") {
        Ok(()) => (),
        Err(_) => fail!("writing to logfile")
    }
}
<|endoftext|>


<commit_before>///! GIT REQ!
mod git;
mod remotes;

use clap::{crate_authors, crate_version, App, Arg};
use log::{debug, info, trace};
use std::io::{self, Write};
use std::process;
use tabwriter::TabWriter;

/// Get the `origin` remote
fn get_origin() -> String {
    git::get_remote_url("origin")
}

/// Get the remote for the current project
fn get_remote() -> Result<Box<remotes::Remote>, String> {
    let origin = get_origin();
    remotes::get_remote(&origin)
}

/// Get the remote, fail hard otherwise
fn get_remote_hard() -> Box<remotes::Remote> {
    match get_remote() {
        Ok(x) => x,
        Err(error) => {
            eprintln!(
                "There was a problem finding the remote Git repo: {}",
                &error
            );
            process::exit(1);
        }
    }
}

/// Check out the branch corresponding to the MR ID
fn checkout_mr(mr_id: i64) {
    info!("Getting MR: {}", mr_id);
    let mut remote = get_remote_hard();
    debug!("Found remote: {}", remote);
    let branch_name = match remote.get_req_branch(mr_id) {
        Ok(name) => name,
        Err(error) => {
            eprintln!(
                "There was a problem ascertaining the branch name: {}",
                &error
            );
            process::exit(1);
        }
    };
    debug!("Got branch name: {}", branch_name);
    match git::checkout_branch(&branch_name) {
        Ok(_) => {
            info!("Done!");
        }
        Err(error) => {
            eprintln!("There was an error checking out the branch: {}", &error);
            process::exit(1)
        }
    };
}

/// Delete the project ID entry
fn clear_project_id() {
    trace!("Deleting project ID");
    git::delete_config("projectid");
    eprintln!("Project ID cleared!");
}

/// Set the project ID
fn set_project_id(new_id: &str) {
    trace!("Setting project ID: {}", new_id);
    git::set_config("projectid", new_id);
    eprintln!("New project ID set!");
}

/// Print the open requests
fn list_open_requests() {
    info!("Getting open requests");
    let mut remote = get_remote_hard();
    debug!("Found remote: {}", remote);
    let mrs = remote.get_req_names().unwrap();
    let mut tw = TabWriter::new(io::stdout()).padding(4);
    for mr in &mrs {
        if remote.has_useful_branch_names() {
            writeln!(&mut tw, "{}\t{}\t{}",  mr.id, mr.source_branch, mr.title).unwrap();
        } else {
            writeln!(&mut tw, "{}\t{}",  mr.id, mr.title).unwrap();
        }
    }
    tw.flush().unwrap();
}

/// Do the thing
fn main() {
    let _ = env_logger::try_init();
    let matches = App::new("git-req")
        .bin_name("git req")
        .author(crate_authors!("\n"))
        .version(crate_version!())
        .about(
            "Switch between merge/pull requests in your GitLab and GitHub repositories with just the request ID.",
        )
        .arg(Arg::with_name("LIST_MR")
             .long("list")
             .short("l")
             .help("List all open requests against the repository")
             .takes_value(false)
             .required(false)
             .conflicts_with_all(&["CLEAR_PROJECT_ID", "NEW_PROJECT_ID", "REQUEST_ID"]))
        .arg(Arg::with_name("NEW_PROJECT_ID")
             .long("set-project-id")
             .value_name("PROJECT_ID")
             .help("A project ID for the current repository")
             .required(false)
             .takes_value(true)
             .conflicts_with_all(&["CLEAR_PROJECT_ID", "LIST_MR", "REQUEST_ID"]))
        .arg(Arg::with_name("CLEAR_PROJECT_ID")
             .long("clear-project-id")
             .help("A project ID for the current repository")
             .required(false)
             .takes_value(false)
             .conflicts_with_all(&["REQUEST_ID", "LIST_MR", "NEW_PROJECT_ID"]))
        .arg(Arg::with_name("REQUEST_ID")
             .required(true)
             .conflicts_with_all(&["NEW_PROJECT_ID", "LIST_MR", "CLEAR_PROJECT_ID"])
             .index(1))
        .get_matches();
    if let Some(project_id) = matches.value_of("NEW_PROJECT_ID") {
        set_project_id(project_id);
    } else if matches.is_present("CLEAR_PROJECT_ID") {
        clear_project_id();
    } else if matches.is_present("LIST_MR") {
        list_open_requests();
    } else {
        checkout_mr(matches.value_of("REQUEST_ID").unwrap().parse().unwrap());
    }
}
<commit_msg>Use REQ_LOG instead of RUST_LOG<commit_after>///! GIT REQ!
mod git;
mod remotes;

use clap::{crate_authors, crate_version, App, Arg};
use log::{debug, info, trace};
use std::io::{self, Write};
use std::{env, process};
use tabwriter::TabWriter;

/// Get the `origin` remote
fn get_origin() -> String {
    git::get_remote_url("origin")
}

/// Get the remote for the current project
fn get_remote() -> Result<Box<remotes::Remote>, String> {
    let origin = get_origin();
    remotes::get_remote(&origin)
}

/// Get the remote, fail hard otherwise
fn get_remote_hard() -> Box<remotes::Remote> {
    match get_remote() {
        Ok(x) => x,
        Err(error) => {
            eprintln!(
                "There was a problem finding the remote Git repo: {}",
                &error
            );
            process::exit(1);
        }
    }
}

/// Check out the branch corresponding to the MR ID
fn checkout_mr(mr_id: i64) {
    info!("Getting MR: {}", mr_id);
    let mut remote = get_remote_hard();
    debug!("Found remote: {}", remote);
    let branch_name = match remote.get_req_branch(mr_id) {
        Ok(name) => name,
        Err(error) => {
            eprintln!(
                "There was a problem ascertaining the branch name: {}",
                &error
            );
            process::exit(1);
        }
    };
    debug!("Got branch name: {}", branch_name);
    match git::checkout_branch(&branch_name) {
        Ok(_) => {
            info!("Done!");
        }
        Err(error) => {
            eprintln!("There was an error checking out the branch: {}", &error);
            process::exit(1)
        }
    };
}

/// Delete the project ID entry
fn clear_project_id() {
    trace!("Deleting project ID");
    git::delete_config("projectid");
    eprintln!("Project ID cleared!");
}

/// Set the project ID
fn set_project_id(new_id: &str) {
    trace!("Setting project ID: {}", new_id);
    git::set_config("projectid", new_id);
    eprintln!("New project ID set!");
}

/// Print the open requests
fn list_open_requests() {
    info!("Getting open requests");
    let mut remote = get_remote_hard();
    debug!("Found remote: {}", remote);
    let mrs = remote.get_req_names().unwrap();
    let mut tw = TabWriter::new(io::stdout()).padding(4);
    for mr in &mrs {
        if remote.has_useful_branch_names() {
            writeln!(&mut tw, "{}\t{}\t{}",  mr.id, mr.source_branch, mr.title).unwrap();
        } else {
            writeln!(&mut tw, "{}\t{}",  mr.id, mr.title).unwrap();
        }
    }
    tw.flush().unwrap();
}

/// Do the thing
fn main() {
    let _ = env_logger::Builder::new()
        .parse_filters(&env::var("REQ_LOG").unwrap_or_default())
        .try_init();
    let matches = App::new("git-req")
        .bin_name("git req")
        .author(crate_authors!("\n"))
        .version(crate_version!())
        .about(
            "Switch between merge/pull requests in your GitLab and GitHub repositories with just the request ID.",
        )
        .arg(Arg::with_name("LIST_MR")
             .long("list")
             .short("l")
             .help("List all open requests against the repository")
             .takes_value(false)
             .required(false)
             .conflicts_with_all(&["CLEAR_PROJECT_ID", "NEW_PROJECT_ID", "REQUEST_ID"]))
        .arg(Arg::with_name("NEW_PROJECT_ID")
             .long("set-project-id")
             .value_name("PROJECT_ID")
             .help("A project ID for the current repository")
             .required(false)
             .takes_value(true)
             .conflicts_with_all(&["CLEAR_PROJECT_ID", "LIST_MR", "REQUEST_ID"]))
        .arg(Arg::with_name("CLEAR_PROJECT_ID")
             .long("clear-project-id")
             .help("A project ID for the current repository")
             .required(false)
             .takes_value(false)
             .conflicts_with_all(&["REQUEST_ID", "LIST_MR", "NEW_PROJECT_ID"]))
        .arg(Arg::with_name("REQUEST_ID")
             .required(true)
             .conflicts_with_all(&["NEW_PROJECT_ID", "LIST_MR", "CLEAR_PROJECT_ID"])
             .index(1))
        .get_matches();
    if let Some(project_id) = matches.value_of("NEW_PROJECT_ID") {
        set_project_id(project_id);
    } else if matches.is_present("CLEAR_PROJECT_ID") {
        clear_project_id();
    } else if matches.is_present("LIST_MR") {
        list_open_requests();
    } else {
        checkout_mr(matches.value_of("REQUEST_ID").unwrap().parse().unwrap());
    }
}
<|endoftext|>


<commit_before>use std::io;

struct PrioData {
    lists: Vec<PrioList>,
}

struct PrioList {
    name: String,
    items: Vec<String>,
}
impl PrioList {
    fn new(name: &str, items: Vec<String>) -> PrioList {
        PrioList {
            name: name.to_string(),
            items: items.clone(),
        }
    }

    fn add_item(&mut self, new_item: &str) {
        self.items.push(new_item.to_string());
    }
}

fn main() {
    let mut data = PrioData {
        lists: vec![PrioList::new("High", vec!["something".to_string(), "something else".to_string()])]
    };

    loop {
        let prompt = "What do you want to do?";
        let choices = vec![
            "1. View priority lists".to_string(),
            "2. Create a new priority".to_string(),
        ];

        let desire = switch_board(prompt, choices);

        match desire.as_ref() {
            "1" => {view_priority_lists(&data);},
            "2" => {create_priority_list(&data);},
            _ => {println!("Please enter a valid number!");}
        }
    }
}

fn view_priority_lists(data: &PrioData) {
    if data.lists.len() == 0 {
        println!("You have no lists!");
    }
    else {
        let mut choices: Vec<String> = vec![];
        let mut index = 0;

        for list in &data.lists {
            index += 1;
            let mut text = index.to_string();
            text.push_str(". ");
            text.push_str(&list.name);
            choices.push(text);
        }

        println!("");

        let prompt = "Which list do you want to view?";

        let desire = switch_board(prompt, choices);
        let mut index: usize = desire.parse().unwrap();
        index -= 1;
        view_list(index, &data);
    }
}

fn view_list(list_index: usize, data: &PrioData) {
    let list = &data.lists[list_index];
    println!("\n--{}--", list.name);

    for item in &list.items {
        println!("{}", item);

    }

}

fn create_priority_list(data: &PrioData) {
    println!("create list!");
}

fn switch_board(prompt: &str, choices: Vec<String>) -> String {
    println!("{}", prompt);
    for choice in choices {
        println!("{}", choice);
    }

    let mut choice = String::new();

    io::stdin().read_line(&mut choice)
        .ok()
        .expect("Failed to read line.");

    choice.trim().to_string()
}
<commit_msg>added the ability to add items to a list and made typing 'back' at any prompt go up a level<commit_after>use std::io;

struct PrioData {
    lists: Vec<PrioList>,
}

struct PrioList {
    name: String,
    items: Vec<String>,
}
impl PrioList {
    fn new(name: &str, items: Vec<String>) -> PrioList {
        PrioList {
            name: name.to_string(),
            items: items.clone(),
        }
    }

    fn add_item(&mut self, new_item: &str) {
        self.items.push(new_item.to_string());
    }
}

fn main() {
    let mut data = PrioData {
        lists: vec![PrioList::new("High", vec!["something".to_string(), "something else".to_string()])]
    };

    loop {
        let prompt = "What do you want to do? (Type \"back\" at any time to return to the previos menu)";
        let choices = vec![
            "1. View priority lists".to_string(),
            "2. Create a new priority".to_string(),
        ];

        let desire = switch_board(prompt, choices);

        match desire.as_ref() {
            "1" => {view_priority_lists(&mut data);},
            "2" => {create_priority_list(&mut data);},
            "back" => {break;},
            _ => {println!("Please enter a valid number!");},
        }
    }
}

fn view_priority_lists(data: &mut PrioData) {
    if data.lists.len() == 0 {
        println!("You have no lists!");
    }
    else {
        loop {
            let mut choices: Vec<String> = vec![];
            let mut index = 0;

            for list in &data.lists {
                index += 1;
                let mut text = index.to_string();
                text.push_str(". ");
                text.push_str(&list.name);
                choices.push(text);
            }

            println!("");

            let prompt = "Which list do you want to view?";

            let desire = switch_board(prompt, choices);
            if desire == "back" {
                break;
            }

            let mut index: usize = desire.parse().unwrap();
            index -= 1;
            view_list(&mut data.lists[index]);
        }
    }
}

fn view_list(list: &mut PrioList) {
    loop {
        println!("\n--{}--", list.name);

        for item in &list.items {
            println!("{}", item);
        }

        println!("\nEnter a new item");
        let new_item = read_line();

        if new_item == "back" {
            break;
        }

        list.add_item(&new_item);
    }
}

fn create_priority_list(data: &PrioData) {
    println!("create list!");
}

fn switch_board(prompt: &str, choices: Vec<String>) -> String {
    println!("\n{}", prompt);
    for choice in choices {
        println!("{}", choice);
    }

    let choice = read_line();

    choice.to_string()
}

fn read_line() -> String{
    let mut line = String::new();

    io::stdin().read_line(&mut line)
        .ok()
        .expect("Failed to read line");

    line.trim().to_string()
}
<|endoftext|>


<commit_before>use std::num::{Zero, One, Algebraic};
use std::vec;
use std::vec::{VecIterator, VecMutIterator};
use std::cmp::ApproxEq;
use std::iterator::FromIterator;
use traits::vector::{Vec, AlgebraicVec};
use traits::iterable::{Iterable, IterableMut};
use traits::translation::Translation;
use traits::scalar_op::{ScalarAdd, ScalarSub};

/// Vector with a dimension unknown at compile-time.
#[deriving(Eq, ToStr, Clone)]
pub struct DVec<N> {
    /// Components of the vector. Contains as much elements as the vector dimension.
    at: ~[N]
}

impl<N: Zero + Clone> DVec<N> {
    /// Builds a vector filled with zeros.
    ///
    /// # Arguments
    ///   * `dim` - The dimension of the vector.
    #[inline]
    pub fn new_zeros(dim: uint) -> DVec<N> {
        DVec::from_elem(dim, Zero::zero())
    }

    /// Tests if all components of the vector are zeroes.
    #[inline]
    pub fn is_zero(&self) -> bool {
        self.at.iter().all(|e| e.is_zero())
    }
}

impl<N: One + Clone> DVec<N> {
    /// Builds a vector filled with ones.
    ///
    /// # Arguments
    ///   * `dim` - The dimension of the vector.
    #[inline]
    pub fn new_ones(dim: uint) -> DVec<N> {
        DVec::from_elem(dim, One::one())
    }
}

impl<N: Clone> DVec<N> {
    /// Builds a vector filled with a constant.
    #[inline]
    pub fn from_elem(dim: uint, elem: N) -> DVec<N> {
        DVec { at: vec::from_elem(dim, elem) }
    }
}

impl<N: Clone> DVec<N> {
    /// Builds a vector filled with the result of a function.
    #[inline(always)]
    pub fn from_fn(dim: uint, f: &fn(uint) -> N) -> DVec<N> {
        DVec { at: vec::from_fn(dim, |i| f(i)) }
    }
}

impl<N> Container for DVec<N> {
    #[inline]
    fn len(&self) -> uint {
        self.at.len()
    }
}

impl<N> Iterable<N> for DVec<N> {
    #[inline]
    fn iter<'l>(&'l self) -> VecIterator<'l, N> {
        self.at.iter()
    }
}

impl<N> IterableMut<N> for DVec<N> {
    #[inline]
    fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N> {
        self.at.mut_iter()
    }
}

impl<N> FromIterator<N> for DVec<N> {
    #[inline]
    fn from_iterator<I: Iterator<N>>(mut param: &mut I) -> DVec<N> {
        let mut res = DVec { at: ~[] };

        for e in param {
            res.at.push(e)
        }

        res
    }
}

impl<N: Clone + Num + Algebraic + ApproxEq<N>> DVec<N> {
    /// Computes the canonical basis for the given dimension. A canonical basis is a set of
    /// vectors, mutually orthogonal, with all its component equal to 0.0 exept one which is equal
    /// to 1.0.
    pub fn canonical_basis_with_dim(dim: uint) -> ~[DVec<N>] {
        let mut res : ~[DVec<N>] = ~[];

        for i in range(0u, dim) {
            let mut basis_element : DVec<N> = DVec::new_zeros(dim);

            basis_element.at[i] = One::one();

            res.push(basis_element);
        }

        res
    }

    /// Computes a basis of the space orthogonal to the vector. If the input vector is of dimension
    /// `n`, this will return `n - 1` vectors.
    pub fn orthogonal_subspace_basis(&self) -> ~[DVec<N>] {
        // compute the basis of the orthogonal subspace using Gram-Schmidt
        // orthogonalization algorithm
        let     dim              = self.at.len();
        let mut res : ~[DVec<N>] = ~[];

        for i in range(0u, dim) {
            let mut basis_element : DVec<N> = DVec::new_zeros(self.at.len());

            basis_element.at[i] = One::one();

            if res.len() == dim - 1 {
                break;
            }

            let mut elt = basis_element.clone();

            elt = elt - self * basis_element.dot(self);

            for v in res.iter() {
                elt = elt - v * elt.dot(v)
            };

            if !elt.sqnorm().approx_eq(&Zero::zero()) {
                res.push(elt.normalized());
            }
        }

        assert!(res.len() == dim - 1);

        res
    }
}

impl<N: Add<N,N>> Add<DVec<N>, DVec<N>> for DVec<N> {
    #[inline]
    fn add(&self, other: &DVec<N>) -> DVec<N> {
        assert!(self.at.len() == other.at.len());
        DVec {
            at: self.at.iter().zip(other.at.iter()).map(|(a, b)| *a + *b).collect()
        }
    }
}

impl<N: Sub<N,N>> Sub<DVec<N>, DVec<N>> for DVec<N> {
    #[inline]
    fn sub(&self, other: &DVec<N>) -> DVec<N> {
        assert!(self.at.len() == other.at.len());
        DVec {
            at: self.at.iter().zip(other.at.iter()).map(|(a, b)| *a - *b).collect()
        }
    }
}

impl<N: Neg<N>> Neg<DVec<N>> for DVec<N> {
    #[inline]
    fn neg(&self) -> DVec<N> {
        DVec { at: self.at.iter().map(|a| -a).collect() }
    }
}

impl<N: Num> DVec<N> {
    #[inline]
    fn dot(&self, other: &DVec<N>) -> N {
        assert!(self.at.len() == other.at.len());

        let mut res: N = Zero::zero();

        for i in range(0u, self.at.len()) {
            res = res + self.at[i] * other.at[i];
        }

        res
    }

    #[inline]
    fn sub_dot(&self, a: &DVec<N>, b: &DVec<N>) -> N {
        let mut res: N = Zero::zero();

        for i in range(0u, self.at.len()) {
            res = res + (self.at[i] - a.at[i]) * b.at[i];
        }

        res
    }
}

impl<N: Mul<N, N>> Mul<N, DVec<N>> for DVec<N> {
    #[inline]
    fn mul(&self, s: &N) -> DVec<N> {
        DVec { at: self.at.iter().map(|a| a * *s).collect() }
    }
}

impl<N: Div<N, N>> Div<N, DVec<N>> for DVec<N> {
    #[inline]
    fn div(&self, s: &N) -> DVec<N> {
        DVec { at: self.at.iter().map(|a| a / *s).collect() }
    }
}

impl<N: Add<N, N>> ScalarAdd<N> for DVec<N> {
    #[inline]
    fn scalar_add(&self, s: &N) -> DVec<N> {
        DVec { at: self.at.iter().map(|a| a + *s).collect() }
    }

    #[inline]
    fn scalar_add_inplace(&mut self, s: &N) {
        for i in range(0u, self.at.len()) {
            self.at[i] = self.at[i] + *s;
        }
    }
}

impl<N: Sub<N, N>> ScalarSub<N> for DVec<N> {
    #[inline]
    fn scalar_sub(&self, s: &N) -> DVec<N> {
        DVec { at: self.at.iter().map(|a| a - *s).collect() }
    }

    #[inline]
    fn scalar_sub_inplace(&mut self, s: &N) {
        for i in range(0u, self.at.len()) {
            self.at[i] = self.at[i] - *s;
        }
    }
}

impl<N: Add<N, N> + Neg<N> + Clone> Translation<DVec<N>> for DVec<N> {
    #[inline]
    fn translation(&self) -> DVec<N> {
        self.clone()
    }

    #[inline]
    fn inv_translation(&self) -> DVec<N> {
        -self
    }

    #[inline]
    fn translate_by(&mut self, t: &DVec<N>) {
        *self = *self + *t;
    }

    #[inline]
    fn translated(&self, t: &DVec<N>) -> DVec<N> {
        self + *t
    }

    #[inline]
    fn set_translation(&mut self, t: DVec<N>) {
        *self = t
    }
}

impl<N: Num + Algebraic + Clone> DVec<N> {
    #[inline]
    fn sqnorm(&self) -> N {
        self.dot(self)
    }

    #[inline]
    fn norm(&self) -> N {
        self.sqnorm().sqrt()
    }

    #[inline]
    fn normalized(&self) -> DVec<N> {
        let mut res : DVec<N> = self.clone();

        res.normalize();

        res
    }

    #[inline]
    fn normalize(&mut self) -> N {
        let l = self.norm();

        for i in range(0u, self.at.len()) {
            self.at[i] = self.at[i] / l;
        }

        l
    }
}

impl<N: ApproxEq<N>> ApproxEq<N> for DVec<N> {
    #[inline]
    fn approx_epsilon() -> N {
        fail!("Fix me.")
        // let res: N = ApproxEq::<N>::approx_epsilon();

        // res
    }

    #[inline]
    fn approx_eq(&self, other: &DVec<N>) -> bool {
        let mut zip = self.at.iter().zip(other.at.iter());

        do zip.all |(a, b)| {
            a.approx_eq(b)
        }
    }

    #[inline]
    fn approx_eq_eps(&self, other: &DVec<N>, epsilon: &N) -> bool {
        let mut zip = self.at.iter().zip(other.at.iter());

        do zip.all |(a, b)| {
            a.approx_eq_eps(b, epsilon)
        }
    }
}
<commit_msg>Make the dot-product and normalization related methods public for DVec.<commit_after>use std::num::{Zero, One, Algebraic};
use std::vec;
use std::vec::{VecIterator, VecMutIterator};
use std::cmp::ApproxEq;
use std::iterator::FromIterator;
use traits::vector::{Vec, AlgebraicVec};
use traits::iterable::{Iterable, IterableMut};
use traits::translation::Translation;
use traits::scalar_op::{ScalarAdd, ScalarSub};

/// Vector with a dimension unknown at compile-time.
#[deriving(Eq, ToStr, Clone)]
pub struct DVec<N> {
    /// Components of the vector. Contains as much elements as the vector dimension.
    at: ~[N]
}

impl<N: Zero + Clone> DVec<N> {
    /// Builds a vector filled with zeros.
    ///
    /// # Arguments
    ///   * `dim` - The dimension of the vector.
    #[inline]
    pub fn new_zeros(dim: uint) -> DVec<N> {
        DVec::from_elem(dim, Zero::zero())
    }

    /// Tests if all components of the vector are zeroes.
    #[inline]
    pub fn is_zero(&self) -> bool {
        self.at.iter().all(|e| e.is_zero())
    }
}

impl<N: One + Clone> DVec<N> {
    /// Builds a vector filled with ones.
    ///
    /// # Arguments
    ///   * `dim` - The dimension of the vector.
    #[inline]
    pub fn new_ones(dim: uint) -> DVec<N> {
        DVec::from_elem(dim, One::one())
    }
}

impl<N: Clone> DVec<N> {
    /// Builds a vector filled with a constant.
    #[inline]
    pub fn from_elem(dim: uint, elem: N) -> DVec<N> {
        DVec { at: vec::from_elem(dim, elem) }
    }
}

impl<N: Clone> DVec<N> {
    /// Builds a vector filled with the result of a function.
    #[inline(always)]
    pub fn from_fn(dim: uint, f: &fn(uint) -> N) -> DVec<N> {
        DVec { at: vec::from_fn(dim, |i| f(i)) }
    }
}

impl<N> Container for DVec<N> {
    #[inline]
    fn len(&self) -> uint {
        self.at.len()
    }
}

impl<N> Iterable<N> for DVec<N> {
    #[inline]
    fn iter<'l>(&'l self) -> VecIterator<'l, N> {
        self.at.iter()
    }
}

impl<N> IterableMut<N> for DVec<N> {
    #[inline]
    fn mut_iter<'l>(&'l mut self) -> VecMutIterator<'l, N> {
        self.at.mut_iter()
    }
}

impl<N> FromIterator<N> for DVec<N> {
    #[inline]
    fn from_iterator<I: Iterator<N>>(mut param: &mut I) -> DVec<N> {
        let mut res = DVec { at: ~[] };

        for e in param {
            res.at.push(e)
        }

        res
    }
}

impl<N: Clone + Num + Algebraic + ApproxEq<N>> DVec<N> {
    /// Computes the canonical basis for the given dimension. A canonical basis is a set of
    /// vectors, mutually orthogonal, with all its component equal to 0.0 exept one which is equal
    /// to 1.0.
    pub fn canonical_basis_with_dim(dim: uint) -> ~[DVec<N>] {
        let mut res : ~[DVec<N>] = ~[];

        for i in range(0u, dim) {
            let mut basis_element : DVec<N> = DVec::new_zeros(dim);

            basis_element.at[i] = One::one();

            res.push(basis_element);
        }

        res
    }

    /// Computes a basis of the space orthogonal to the vector. If the input vector is of dimension
    /// `n`, this will return `n - 1` vectors.
    pub fn orthogonal_subspace_basis(&self) -> ~[DVec<N>] {
        // compute the basis of the orthogonal subspace using Gram-Schmidt
        // orthogonalization algorithm
        let     dim              = self.at.len();
        let mut res : ~[DVec<N>] = ~[];

        for i in range(0u, dim) {
            let mut basis_element : DVec<N> = DVec::new_zeros(self.at.len());

            basis_element.at[i] = One::one();

            if res.len() == dim - 1 {
                break;
            }

            let mut elt = basis_element.clone();

            elt = elt - self * basis_element.dot(self);

            for v in res.iter() {
                elt = elt - v * elt.dot(v)
            };

            if !elt.sqnorm().approx_eq(&Zero::zero()) {
                res.push(elt.normalized());
            }
        }

        assert!(res.len() == dim - 1);

        res
    }
}

impl<N: Add<N,N>> Add<DVec<N>, DVec<N>> for DVec<N> {
    #[inline]
    fn add(&self, other: &DVec<N>) -> DVec<N> {
        assert!(self.at.len() == other.at.len());
        DVec {
            at: self.at.iter().zip(other.at.iter()).map(|(a, b)| *a + *b).collect()
        }
    }
}

impl<N: Sub<N,N>> Sub<DVec<N>, DVec<N>> for DVec<N> {
    #[inline]
    fn sub(&self, other: &DVec<N>) -> DVec<N> {
        assert!(self.at.len() == other.at.len());
        DVec {
            at: self.at.iter().zip(other.at.iter()).map(|(a, b)| *a - *b).collect()
        }
    }
}

impl<N: Neg<N>> Neg<DVec<N>> for DVec<N> {
    #[inline]
    fn neg(&self) -> DVec<N> {
        DVec { at: self.at.iter().map(|a| -a).collect() }
    }
}

impl<N: Num> DVec<N> {
    /// Will change soon.
    #[inline]
    pub fn dot(&self, other: &DVec<N>) -> N {
        assert!(self.at.len() == other.at.len());

        let mut res: N = Zero::zero();

        for i in range(0u, self.at.len()) {
            res = res + self.at[i] * other.at[i];
        }

        res
    }

    /// Will change soon.
    #[inline]
    pub fn sub_dot(&self, a: &DVec<N>, b: &DVec<N>) -> N {
        let mut res: N = Zero::zero();

        for i in range(0u, self.at.len()) {
            res = res + (self.at[i] - a.at[i]) * b.at[i];
        }

        res
    }
}

impl<N: Mul<N, N>> Mul<N, DVec<N>> for DVec<N> {
    #[inline]
    fn mul(&self, s: &N) -> DVec<N> {
        DVec { at: self.at.iter().map(|a| a * *s).collect() }
    }
}

impl<N: Div<N, N>> Div<N, DVec<N>> for DVec<N> {
    #[inline]
    fn div(&self, s: &N) -> DVec<N> {
        DVec { at: self.at.iter().map(|a| a / *s).collect() }
    }
}

impl<N: Add<N, N>> ScalarAdd<N> for DVec<N> {
    #[inline]
    fn scalar_add(&self, s: &N) -> DVec<N> {
        DVec { at: self.at.iter().map(|a| a + *s).collect() }
    }

    #[inline]
    fn scalar_add_inplace(&mut self, s: &N) {
        for i in range(0u, self.at.len()) {
            self.at[i] = self.at[i] + *s;
        }
    }
}

impl<N: Sub<N, N>> ScalarSub<N> for DVec<N> {
    #[inline]
    fn scalar_sub(&self, s: &N) -> DVec<N> {
        DVec { at: self.at.iter().map(|a| a - *s).collect() }
    }

    #[inline]
    fn scalar_sub_inplace(&mut self, s: &N) {
        for i in range(0u, self.at.len()) {
            self.at[i] = self.at[i] - *s;
        }
    }
}

impl<N: Add<N, N> + Neg<N> + Clone> Translation<DVec<N>> for DVec<N> {
    #[inline]
    fn translation(&self) -> DVec<N> {
        self.clone()
    }

    #[inline]
    fn inv_translation(&self) -> DVec<N> {
        -self
    }

    #[inline]
    fn translate_by(&mut self, t: &DVec<N>) {
        *self = *self + *t;
    }

    #[inline]
    fn translated(&self, t: &DVec<N>) -> DVec<N> {
        self + *t
    }

    #[inline]
    fn set_translation(&mut self, t: DVec<N>) {
        *self = t
    }
}

impl<N: Num + Algebraic + Clone> DVec<N> {
    /// Will change soon.
    #[inline]
    pub fn sqnorm(&self) -> N {
        self.dot(self)
    }

    /// Will change soon.
    #[inline]
    pub fn norm(&self) -> N {
        self.sqnorm().sqrt()
    }

    /// Will change soon.
    #[inline]
    pub fn normalized(&self) -> DVec<N> {
        let mut res : DVec<N> = self.clone();

        res.normalize();

        res
    }

    /// Will change soon.
    #[inline]
    pub fn normalize(&mut self) -> N {
        let l = self.norm();

        for i in range(0u, self.at.len()) {
            self.at[i] = self.at[i] / l;
        }

        l
    }
}

impl<N: ApproxEq<N>> ApproxEq<N> for DVec<N> {
    #[inline]
    fn approx_epsilon() -> N {
        fail!("Fix me.")
        // let res: N = ApproxEq::<N>::approx_epsilon();

        // res
    }

    #[inline]
    fn approx_eq(&self, other: &DVec<N>) -> bool {
        let mut zip = self.at.iter().zip(other.at.iter());

        do zip.all |(a, b)| {
            a.approx_eq(b)
        }
    }

    #[inline]
    fn approx_eq_eps(&self, other: &DVec<N>, epsilon: &N) -> bool {
        let mut zip = self.at.iter().zip(other.at.iter());

        do zip.all |(a, b)| {
            a.approx_eq_eps(b, epsilon)
        }
    }
}
<|endoftext|>