<commit_before>extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;
extern crate robots;
extern crate persistent;
extern crate env_logger;

use iron::prelude::*;
use iron::status;
use router::Router;
use staticfile::Static;
use mount::Mount;
use std::path::Path;
use std::any::Any;
use std::sync::{Arc,Mutex};
use std::thread;
use std::time;
use robots::actors::{ActorSystem,Actor,ActorCell,ActorContext,Props,ActorRef,ActorPath};
use persistent::Read;
use iron::typemap::Key;
use std::fmt::{Debug, Display,Formatter,Result};
use gpioaccess::PinProxy;

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum DirectionProxied {
    In,
    Out,
    High,
    Low,
}

#[derive(Debug)]
pub enum ProxyError {
	MonErreur,
}

impl ::std::error::Error for ProxyError {
	fn description(&self) -> &str {
		"an error"
	}
}

impl Display for ProxyError {
	fn fmt(&self, f: &mut Formatter) -> Result {
		write!(f, "an error")
	}
}

pub type ProxyResult<T> = ::std::result::Result<T, ProxyError>;

//depend on abstractions not concretions lulz
trait PinProxyContract {

	fn new(pin_num: u64) -> Self;
	//FIXME :figure out mapping overloaded Result from gpio library
	fn export(&self) -> ProxyResult<()>;

	fn unexport(&self) ->  ProxyResult<()>;

	fn set_value(&self, value: u8) -> ProxyResult<()>;

	fn set_direction(&self, dir: DirectionProxied) ->  ProxyResult<()>;
}

#[cfg(unix)]
pub mod gpioaccess{

	extern crate sysfs_gpio;
	use self::sysfs_gpio::{Direction, Pin};
	use super::{PinProxyContract,DirectionProxied,ProxyError,ProxyResult};

	pub struct PinProxy {
		pin : Pin,
	}

	impl PinProxyContract for PinProxy
	{
		fn new(pin_num: u64) -> PinProxy {
			PinProxy{ pin: Pin::new(pin_num) }
		}

		fn export(&self) ->  ProxyResult<()>{
			match self.pin.export()
			{
				Ok(()) => Ok(()),
				_ => Err(ProxyError::MonErreur),

			}
		}

		fn unexport(&self) ->  ProxyResult<()> {
			match self.pin.unexport()
			{
				Ok(()) => Ok(()),
				_ => Err(ProxyError::MonErreur),
			}
		}

		fn set_value(&self, value: u8) ->  ProxyResult<()> {
			match self.pin.set_value(value)
			{
				Ok(()) => Ok(()),
				_ => Err(ProxyError::MonErreur),
			}
		}

		fn set_direction(&self, dir: DirectionProxied) ->  ProxyResult<()>{
			let dirmapped =  match dir {
                                           DirectionProxied::In =>  Direction::In,
                                           DirectionProxied::Out => Direction::Out,
                                           DirectionProxied::High => Direction::High,
                                           DirectionProxied::Low => Direction::Low,
                                       };
			match self.pin.set_direction(dirmapped)
			{
				Ok(()) => Ok(()),
				_ => Err(ProxyError::MonErreur),
			}
		}

    }
}

#[cfg(not(unix))]
pub mod gpioaccess{
	//use std::fmt;
	use super::{PinProxyContract,DirectionProxied,ProxyError,ProxyResult};

	pub struct PinProxy {
		pin_num: u64,
	}

	impl PinProxyContract for PinProxy
	{
		fn new(pin_num: u64) -> PinProxy {
			PinProxy{ pin_num: pin_num }
		}
		fn export(&self) -> ProxyResult<()>
		{
      println!("exporting pin {}",self.pin_num);
			Ok::<(),ProxyError>(())
		}
		fn unexport(&self) -> ProxyResult<()>
		{
        println!("unexporting pin {}",self.pin_num);
			  Ok::<(),ProxyError>(())
		}

		fn set_value(&self, value: u8) -> ProxyResult<()>
		{
			Ok::<(),ProxyError>(())
		}

		fn set_direction(&self, dir: DirectionProxied) -> ProxyResult<()>
		{
			Ok::<(),ProxyError>(())
		}
    }
}

#[derive(Copy, Clone)]
pub struct Sys;
impl Key for Sys { type Value = ActorSystem; }

struct Resolver;

impl Actor for Resolver {
    fn receive(&self, message: Box<Any>, context: ActorCell) {
        if let Ok(message) = Box::<Any>::downcast::<String>(message) {
            let future = context.identify_actor(*message, "resolver_request".to_owned());
            context.forward_result_to_future::<Option<ActorRef>>(future, context.sender());
			      context.stop(context.actor_ref());
        }
    }
}

impl Resolver {
    fn new(_dummy: ()) -> Resolver {
        Resolver
    }
}

fn main() {
  match env_logger::init() {
      Ok(()) => {}
      _ => {}
  };
	let dragon_actor_system  = ActorSystem::new("dragon".to_owned());
	dragon_actor_system.spawn_threads(3);

	dragon_actor_system.actor_of(Props::new(Arc::new(Dragon::new),()), "gorynich".to_owned());
    // the router (for RESTfull actions)
	let mut router = Router::new();
	router.get("/wings", move_wings,"wings");
	router.get("/mouth", open_mouth,"mouth");
	router.get("/eyes", blink_eyes,"eyes");

	fn handle_command(req: &mut Request, dragon_command: DragonCommands, dragon_event: DragonEvents ) ->IronResult<Response> {
		let arcsys = req.get::<Read<Sys>>().unwrap();
    	let sys = arcsys.as_ref();
		let props = Props::new(Arc::new(Resolver::new), ());
    	let answerer = sys.actor_of(props.clone(), "answerer".to_owned());
        let dragon = sys.ask(answerer, "/user/gorynich".to_owned(), "future".to_owned());
    	let dragon: Option<ActorRef> = sys.extract_result(dragon);
		match dragon {
			None => {
				Ok(Response::with((status::Ok, "Dragon not found")))
			}
			Some(dragonunwrapped) => {
				let future = sys.ask(dragonunwrapped, dragon_command, "request".to_owned());
	    		let event: DragonEvents = sys.extract_result(future);
				if event == dragon_event {
					Ok(Response::with((status::Ok, dragon_event.to_string())))
				} else
				{
					Ok(Response::with((status::Ok, "Unknown event!")))
				}
			}
		}
	}

	fn move_wings(req:&mut Request)  -> IronResult<Response>  {
		handle_command(req,DragonCommands::MoveWings,DragonEvents::WingsMoved)
	}

	fn open_mouth(req: &mut Request) -> IronResult<Response> {
		handle_command(req,DragonCommands::OpenMouth,DragonEvents::MouthOpened)
	}

	fn blink_eyes(req: &mut Request) -> IronResult<Response> {
		handle_command(req,DragonCommands::BlinkEyes,DragonEvents::EyesBlinked)
	}

	let mut chain = Chain::new(router);
	chain.link(Read::<Sys>::both(dragon_actor_system));
	// the mounter for static files
	let mut mount = Mount::new();
	mount
		.mount("/",Static::new(Path::new("static")))
		.mount("/api/",chain);
	Iron::new(mount).http("0.0.0.0:8080").unwrap();
}

#[derive(Copy, Clone, PartialEq,Debug)]
enum DragonCommands {
	MoveWings,
	OpenMouth,
	BlinkEyes,
}

#[derive(Copy, Clone, PartialEq,Debug)]
enum DragonEvents {
	WingsMoved,
	MouthOpened,
	EyesBlinked,
}

impl Display for DragonCommands {
    fn fmt(&self, f: &mut Formatter) -> Result {
        Debug::fmt(self, f)
    }
}

impl Display for DragonEvents {
    fn fmt(&self, f: &mut Formatter) -> Result {
        Debug::fmt(self, f)
    }
}

struct Dragon;

impl Actor for Dragon {

	fn pre_start(&self, context: ActorCell) {
		let wings = context.actor_of(Props::new(Arc::new(Wings::new),()), "wings".to_owned()).unwrap();
		let mouth = context.actor_of(Props::new(Arc::new(Mouth::new),()), "mouth".to_owned()).unwrap();
		let eyes = context.actor_of(Props::new(Arc::new(Eyes::new),()), "eyes".to_owned()).unwrap();
		context.tell(wings,LimbCommands::Init(10));
		context.tell(mouth,LimbCommands::Init(10));
		context.tell(eyes,LimbCommands::Init(10));
	}
	fn receive(&self, _message: Box<Any>, _context: ActorCell){
		if let Ok(_message) = Box::<Any>::downcast::<DragonCommands>(_message){
			match *_message {
				DragonCommands::MoveWings => {
						let wings: ActorRef = _context.children().get(&ActorPath::new_local("/user/gorynich/wings".to_owned())).cloned().unwrap();
						_context.tell(wings,LimbCommands::Aggitate);
						_context.complete(_context.sender(),DragonEvents::WingsMoved);
						},
				DragonCommands::OpenMouth => {
						let mouth: ActorRef = _context.children().get(&ActorPath::new_local("/user/gorynich/mouth".to_owned())).cloned().unwrap();
						_context.tell(mouth,LimbCommands::Aggitate);
						_context.complete(_context.sender(),DragonEvents::MouthOpened);
						},
				DragonCommands::BlinkEyes => {
						let eyes: ActorRef = _context.children().get(&ActorPath::new_local("/user/gorynich/eyes".to_owned())).cloned().unwrap();
						_context.tell(eyes,LimbCommands::Aggitate);
						_context.complete(_context.sender(),DragonEvents::EyesBlinked);
						}
			}
		} else {
			println!("Gorynich does not understand!");
		}
	}
}

impl Dragon {
	fn new(_: ()) -> Dragon {
		Dragon
	}
}

#[derive(Copy, Clone, PartialEq,Debug)]
enum LimbCommands {
	Init(u64),
	Aggitate,
	Reset,
}

#[derive(Copy, Clone, PartialEq,Debug)]
enum LimbEvents {
	Aggitated,
	NotAggitated(u64),
}

impl Display for LimbCommands {
    fn fmt(&self, f: &mut Formatter) -> Result {
        Debug::fmt(self, f)
    }
}

impl Display for LimbEvents {
    fn fmt(&self, f: &mut Formatter) -> Result {
        Debug::fmt(self, f)
    }
}

struct Wings;

impl Actor for Wings {
    fn pre_start(&self, context: ActorCell) {
		   context.actor_of(Props::new(Arc::new(PinActor::new), 18), "pin18".to_owned()).unwrap();
    }
    fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<LimbCommands>(_message){
			match *_message {
				LimbCommands::Init(max) => { println!("Initializing with maximum {}",max); },
				LimbCommands::Aggitate => {
                        let pin18 : ActorRef = _context.children().get(&ActorPath::new_local("/user/gorynich/wings/pin18".to_owned())).cloned().unwrap();
						_context.tell(pin18,PinCommands::Blink(5));
						println!("Moving Wings");
				},
				LimbCommands::Reset => { println!("Received reset"); }
			}
		} else {
			println!("Gorynich does not understand!");
		}
	}
}

impl Wings {
    fn new(_: ()) -> Wings {
        Wings
    }
}

struct Mouth;

impl Actor for Mouth {
    fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<LimbCommands>(_message){
			match *_message {
				LimbCommands::Init(max) => { println!("Initializing with maximum {}",max); },
				LimbCommands::Aggitate => {
						println!("Opening Mouth");
						},
				LimbCommands::Reset => { println!("Received reset"); }
			}
		} else {
			println!("Gorynich does not understand!");
		}
	}
}

impl Mouth {
    fn new(_: ()) -> Mouth {
        Mouth
    }
}

struct Eyes;

impl Actor for Eyes {
    fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<LimbCommands>(_message){
			match *_message {
				LimbCommands::Init(max) => { println!("Initializing with maximum {}",max); },
				LimbCommands::Aggitate => {
						println!("Blinking Eyes");
						//_context.complete(_context.sender(),LimbEvents::Aggitated);
						},
				LimbCommands::Reset => { println!("Received reset"); }
			}
		} else {
			println!("Gorynich does not understand!");
		}
	}
}

impl Eyes {
    fn new(_: ()) -> Eyes {
        Eyes
    }
}

#[derive(Copy, Clone, PartialEq,Debug)]
enum PinCommands {
	Blink(u64),
	Switch,
}

struct PinActor {
	pinproxy :  Mutex<PinProxy>,
}

impl Actor for PinActor {
    fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<PinCommands>(_message){
			match *_message {
			    PinCommands::Blink(times) => {
                let pin = self.pinproxy.lock().unwrap();
                match pin.export() {
                  Ok(()) => {
						        println!("Pin exported");
                                for x in 1..times {
                                    pin.set_direction(DirectionProxied::Out);
                                    pin.set_direction(DirectionProxied::High);
                                    thread::sleep(time::Duration::from_millis(200));
                                    pin.set_direction(DirectionProxied::Low);
                                    thread::sleep(time::Duration::from_millis(200));
                                    println!("Blink {}",x);
                                }
                                match pin.unexport() {
                          Ok(()) => {
						                  println!("Pin unexported");
                          }
                          _ => {}
                      }
                  }
                  _ => {}
              }
          },
				PinCommands::Switch => {	}
			}
		}
	}
}

impl PinActor{
	fn new(pin_number: u64) -> PinActor {
		PinActor{ pinproxy : Mutex::new(PinProxy::new(pin_number)) }
    }
}

mod test;
<commit_msg>pwmproxy<commit_after>extern crate iron;
extern crate router;
extern crate mount;
extern crate staticfile;
extern crate robots;
extern crate persistent;
extern crate env_logger;

use iron::prelude::*;
use iron::status;
use router::Router;
use staticfile::Static;
use mount::Mount;
use std::path::Path;
use std::any::Any;
use std::sync::{Arc,Mutex};
use std::thread;
use std::time;
use robots::actors::{ActorSystem,Actor,ActorCell,ActorContext,Props,ActorRef,ActorPath};
use persistent::Read;
use iron::typemap::Key;
use std::fmt::{Debug, Display,Formatter,Result};
use gpioaccess::PinProxy;

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum DirectionProxied {
    In,
    Out,
    High,
    Low,
}

#[derive(Debug)]
pub enum ProxyError {
	MonErreur,
}

impl ::std::error::Error for ProxyError {
	fn description(&self) -> &str {
		"an error"
	}
}

impl Display for ProxyError {
	fn fmt(&self, f: &mut Formatter) -> Result {
		write!(f, "an error")
	}
}

pub type ProxyResult<T> = ::std::result::Result<T, ProxyError>;

//depend on abstractions not concretions lulz
trait PinProxyContract {

	fn new(pin_num: u64) -> Self;
	//FIXME :figure out mapping overloaded Result from gpio library
	fn export(&self) -> ProxyResult<()>;

	fn unexport(&self) ->  ProxyResult<()>;

	fn set_value(&self, value: u8) -> ProxyResult<()>;

	fn set_direction(&self, dir: DirectionProxied) ->  ProxyResult<()>;
}

trait PwmProxyContract {

	fn  new(chip: u32, number: u32) -> Self;
	//FIXME :figure out mapping overloaded Result from gpio library
	fn export(&self) -> ProxyResult<()>;

	fn unexport(&self) ->  ProxyResult<()>;

	fn enable(&self, enable: bool) -> ProxyResult<()>;

	fn set_duty_cycle_ns(&self, duty_cycle_ns: u32) -> ProxyResult<()>;

	fn set_period_ns(&self, period_ns: u32) -> ProxyResult<()>;
}

#[cfg(unix)]
pub mod gpioaccess{

	extern crate sysfs_gpio;
	use self::sysfs_gpio::{Direction, Pin};
	use super::{PinProxyContract,DirectionProxied,ProxyError,ProxyResult};

	pub struct PinProxy {
		pin : Pin,
	}

	impl PinProxyContract for PinProxy
	{
		fn new(pin_num: u64) -> PinProxy {
			PinProxy{ pin: Pin::new(pin_num) }
		}

		fn export(&self) ->  ProxyResult<()>{
			match self.pin.export()
			{
				Ok(()) => Ok(()),
				_ => Err(ProxyError::MonErreur),

			}
		}

		fn unexport(&self) ->  ProxyResult<()> {
			match self.pin.unexport()
			{
				Ok(()) => Ok(()),
				_ => Err(ProxyError::MonErreur),
			}
		}

		fn set_value(&self, value: u8) ->  ProxyResult<()> {
			match self.pin.set_value(value)
			{
				Ok(()) => Ok(()),
				_ => Err(ProxyError::MonErreur),
			}
		}

		fn set_direction(&self, dir: DirectionProxied) ->  ProxyResult<()>{
			let dirmapped =  match dir {
                                           DirectionProxied::In =>  Direction::In,
                                           DirectionProxied::Out => Direction::Out,
                                           DirectionProxied::High => Direction::High,
                                           DirectionProxied::Low => Direction::Low,
                                       };
			match self.pin.set_direction(dirmapped)
			{
				Ok(()) => Ok(()),
				_ => Err(ProxyError::MonErreur),
			}
		}

    }
}

#[cfg(not(unix))]
pub mod gpioaccess{
	//use std::fmt;
	use super::{PinProxyContract,DirectionProxied,ProxyError,ProxyResult};

	pub struct PinProxy {
		pin_num: u64,
	}

	impl PinProxyContract for PinProxy
	{
		fn new(pin_num: u64) -> PinProxy {
			PinProxy{ pin_num: pin_num }
		}
		fn export(&self) -> ProxyResult<()>
		{
      println!("exporting pin {}",self.pin_num);
			Ok::<(),ProxyError>(())
		}
		fn unexport(&self) -> ProxyResult<()>
		{
        println!("unexporting pin {}",self.pin_num);
			  Ok::<(),ProxyError>(())
		}

		fn set_value(&self, value: u8) -> ProxyResult<()>
		{
			Ok::<(),ProxyError>(())
		}

		fn set_direction(&self, dir: DirectionProxied) -> ProxyResult<()>
		{
			Ok::<(),ProxyError>(())
		}
    }
}

#[derive(Copy, Clone)]
pub struct Sys;
impl Key for Sys { type Value = ActorSystem; }

struct Resolver;

impl Actor for Resolver {
    fn receive(&self, message: Box<Any>, context: ActorCell) {
        if let Ok(message) = Box::<Any>::downcast::<String>(message) {
            let future = context.identify_actor(*message, "resolver_request".to_owned());
            context.forward_result_to_future::<Option<ActorRef>>(future, context.sender());
			      context.stop(context.actor_ref());
        }
    }
}

impl Resolver {
    fn new(_dummy: ()) -> Resolver {
        Resolver
    }
}

fn main() {
  match env_logger::init() {
      Ok(()) => {}
      _ => {}
  };
	let dragon_actor_system  = ActorSystem::new("dragon".to_owned());
	dragon_actor_system.spawn_threads(3);

	dragon_actor_system.actor_of(Props::new(Arc::new(Dragon::new),()), "gorynich".to_owned());
    // the router (for RESTfull actions)
	let mut router = Router::new();
	router.get("/wings", move_wings,"wings");
	router.get("/mouth", open_mouth,"mouth");
	router.get("/eyes", blink_eyes,"eyes");

	fn handle_command(req: &mut Request, dragon_command: DragonCommands, dragon_event: DragonEvents ) ->IronResult<Response> {
		let arcsys = req.get::<Read<Sys>>().unwrap();
    	let sys = arcsys.as_ref();
		let props = Props::new(Arc::new(Resolver::new), ());
    	let answerer = sys.actor_of(props.clone(), "answerer".to_owned());
        let dragon = sys.ask(answerer, "/user/gorynich".to_owned(), "future".to_owned());
    	let dragon: Option<ActorRef> = sys.extract_result(dragon);
		match dragon {
			None => {
				Ok(Response::with((status::Ok, "Dragon not found")))
			}
			Some(dragonunwrapped) => {
				let future = sys.ask(dragonunwrapped, dragon_command, "request".to_owned());
	    		let event: DragonEvents = sys.extract_result(future);
				if event == dragon_event {
					Ok(Response::with((status::Ok, dragon_event.to_string())))
				} else
				{
					Ok(Response::with((status::Ok, "Unknown event!")))
				}
			}
		}
	}

	fn move_wings(req:&mut Request)  -> IronResult<Response>  {
		handle_command(req,DragonCommands::MoveWings,DragonEvents::WingsMoved)
	}

	fn open_mouth(req: &mut Request) -> IronResult<Response> {
		handle_command(req,DragonCommands::OpenMouth,DragonEvents::MouthOpened)
	}

	fn blink_eyes(req: &mut Request) -> IronResult<Response> {
		handle_command(req,DragonCommands::BlinkEyes,DragonEvents::EyesBlinked)
	}

	let mut chain = Chain::new(router);
	chain.link(Read::<Sys>::both(dragon_actor_system));
	// the mounter for static files
	let mut mount = Mount::new();
	mount
		.mount("/",Static::new(Path::new("static")))
		.mount("/api/",chain);
	Iron::new(mount).http("0.0.0.0:8080").unwrap();
}

#[derive(Copy, Clone, PartialEq,Debug)]
enum DragonCommands {
	MoveWings,
	OpenMouth,
	BlinkEyes,
}

#[derive(Copy, Clone, PartialEq,Debug)]
enum DragonEvents {
	WingsMoved,
	MouthOpened,
	EyesBlinked,
}

impl Display for DragonCommands {
    fn fmt(&self, f: &mut Formatter) -> Result {
        Debug::fmt(self, f)
    }
}

impl Display for DragonEvents {
    fn fmt(&self, f: &mut Formatter) -> Result {
        Debug::fmt(self, f)
    }
}

struct Dragon;

impl Actor for Dragon {

	fn pre_start(&self, context: ActorCell) {
		let wings = context.actor_of(Props::new(Arc::new(Wings::new),()), "wings".to_owned()).unwrap();
		let mouth = context.actor_of(Props::new(Arc::new(Mouth::new),()), "mouth".to_owned()).unwrap();
		let eyes = context.actor_of(Props::new(Arc::new(Eyes::new),()), "eyes".to_owned()).unwrap();
		context.tell(wings,LimbCommands::Init(10));
		context.tell(mouth,LimbCommands::Init(10));
		context.tell(eyes,LimbCommands::Init(10));
	}
	fn receive(&self, _message: Box<Any>, _context: ActorCell){
		if let Ok(_message) = Box::<Any>::downcast::<DragonCommands>(_message){
			match *_message {
				DragonCommands::MoveWings => {
						let wings: ActorRef = _context.children().get(&ActorPath::new_local("/user/gorynich/wings".to_owned())).cloned().unwrap();
						_context.tell(wings,LimbCommands::Aggitate);
						_context.complete(_context.sender(),DragonEvents::WingsMoved);
						},
				DragonCommands::OpenMouth => {
						let mouth: ActorRef = _context.children().get(&ActorPath::new_local("/user/gorynich/mouth".to_owned())).cloned().unwrap();
						_context.tell(mouth,LimbCommands::Aggitate);
						_context.complete(_context.sender(),DragonEvents::MouthOpened);
						},
				DragonCommands::BlinkEyes => {
						let eyes: ActorRef = _context.children().get(&ActorPath::new_local("/user/gorynich/eyes".to_owned())).cloned().unwrap();
						_context.tell(eyes,LimbCommands::Aggitate);
						_context.complete(_context.sender(),DragonEvents::EyesBlinked);
						}
			}
		} else {
			println!("Gorynich does not understand!");
		}
	}
}

impl Dragon {
	fn new(_: ()) -> Dragon {
		Dragon
	}
}

#[derive(Copy, Clone, PartialEq,Debug)]
enum LimbCommands {
	Init(u64),
	Aggitate,
	Reset,
}

#[derive(Copy, Clone, PartialEq,Debug)]
enum LimbEvents {
	Aggitated,
	NotAggitated(u64),
}

impl Display for LimbCommands {
    fn fmt(&self, f: &mut Formatter) -> Result {
        Debug::fmt(self, f)
    }
}

impl Display for LimbEvents {
    fn fmt(&self, f: &mut Formatter) -> Result {
        Debug::fmt(self, f)
    }
}

struct Wings;

impl Actor for Wings {
    fn pre_start(&self, context: ActorCell) {
		   context.actor_of(Props::new(Arc::new(PinActor::new), 18), "pin18".to_owned()).unwrap();
    }
    fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<LimbCommands>(_message){
			match *_message {
				LimbCommands::Init(max) => { println!("Initializing with maximum {}",max); },
				LimbCommands::Aggitate => {
                        let pin18 : ActorRef = _context.children().get(&ActorPath::new_local("/user/gorynich/wings/pin18".to_owned())).cloned().unwrap();
						_context.tell(pin18,PinCommands::Blink(5));
						println!("Moving Wings");
				},
				LimbCommands::Reset => { println!("Received reset"); }
			}
		} else {
			println!("Gorynich does not understand!");
		}
	}
}

impl Wings {
    fn new(_: ()) -> Wings {
        Wings
    }
}

struct Mouth;

impl Actor for Mouth {
    fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<LimbCommands>(_message){
			match *_message {
				LimbCommands::Init(max) => { println!("Initializing with maximum {}",max); },
				LimbCommands::Aggitate => {
						println!("Opening Mouth");
						},
				LimbCommands::Reset => { println!("Received reset"); }
			}
		} else {
			println!("Gorynich does not understand!");
		}
	}
}

impl Mouth {
    fn new(_: ()) -> Mouth {
        Mouth
    }
}

struct Eyes;

impl Actor for Eyes {
    fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<LimbCommands>(_message){
			match *_message {
				LimbCommands::Init(max) => { println!("Initializing with maximum {}",max); },
				LimbCommands::Aggitate => {
						println!("Blinking Eyes");
						//_context.complete(_context.sender(),LimbEvents::Aggitated);
						},
				LimbCommands::Reset => { println!("Received reset"); }
			}
		} else {
			println!("Gorynich does not understand!");
		}
	}
}

impl Eyes {
    fn new(_: ()) -> Eyes {
        Eyes
    }
}

#[derive(Copy, Clone, PartialEq,Debug)]
enum PinCommands {
	Blink(u64),
	Switch,
}

struct PinActor {
	pinproxy :  Mutex<PinProxy>,
}

impl Actor for PinActor {
    fn receive(&self, _message: Box<Any>, _context: ActorCell) {
		if let Ok(_message) = Box::<Any>::downcast::<PinCommands>(_message){
			match *_message {
			    PinCommands::Blink(times) => {
                let pin = self.pinproxy.lock().unwrap();
                match pin.export() {
                  Ok(()) => {
						        println!("Pin exported");
                                for x in 1..times {
                                    pin.set_direction(DirectionProxied::Out);
                                    pin.set_direction(DirectionProxied::High);
                                    thread::sleep(time::Duration::from_millis(200));
                                    pin.set_direction(DirectionProxied::Low);
                                    thread::sleep(time::Duration::from_millis(200));
                                    println!("Blink {}",x);
                                }
                                match pin.unexport() {
                          Ok(()) => {
						                  println!("Pin unexported");
                          }
                          _ => {}
                      }
                  }
                  _ => {}
              }
          },
				PinCommands::Switch => {	}
			}
		}
	}
}

impl PinActor{
	fn new(pin_number: u64) -> PinActor {
		PinActor{ pinproxy : Mutex::new(PinProxy::new(pin_number)) }
    }
}

mod test;
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!")
}
<commit_msg>implement first table parsing<commit_after>#![feature(slicing_syntax)]
#![feature(if_let)]
#![feature(phase)]

extern crate collections;
extern crate time;

#[phase(plugin, link)]
extern crate log;

use std::collections::HashMap;
use std::io::{BufferedReader, File};
use std::str::CharSplits;
use time::precise_time_ns;

use collections::hash::Hash;

use numeric::Numeric;

mod numeric {
    use std::char::{is_whitespace, to_digit};
    use std::num;

    #[deriving(Clone, Show, Eq)]
    pub struct Numeric {
        value: i64,
        len: uint,
        precision: uint
    }

    impl Numeric {
        pub fn from_str(s: &str, len: uint, precision: uint) -> Option<Numeric> {
            let mut s = s.trim_chars(is_whitespace);
            let mut value = 0i64;
            let mut negative = false;
            let mut fraction = false;
            if s[0..1] == "-" {
                negative = true;
                s = s[1..];
            }

            if s.contains_char('.') {
                while s.chars().last() == Some('0') {
                    s = s[..s.len() - 1]
                }
            }

            let mut digits_seen = 0u;
            let mut digits_seen_fraction = 0u;
            for c in s.chars() {
                if let Some(n) = to_digit(c, 10) {
                    value = value * 10 + n as i64;
                    if fraction {
                        digits_seen_fraction += 1;
                    } else {
                        digits_seen += 1;
                    }
                } else if c == '.' {
                    fraction = match fraction {
                        true => return None,
                        false => true
                    };
                } else {
                    return None;
                }
            }

            if negative {
                value *= -1;
            }

            if digits_seen > len - precision || digits_seen_fraction > precision {
                None
            } else {
                Some(Numeric {
                    value: value * num::pow(10, precision - digits_seen_fraction),
                    len: len,
                    precision: precision,
                })
            }
        }
    }

    impl PartialEq for Numeric {
        fn eq(&self, other: &Numeric) -> bool {
            self.value == other.value &&
                self.len == other.len &&
                self.precision == other.precision
        }
    }

    #[test]
    fn test_from_str() {
        assert_eq!(Numeric::from_str("50", 2, 0), Some(Numeric {value: 50, len: 2, precision: 0}))
        assert_eq!(Numeric::from_str("-50", 2, 0), Some(Numeric {value: -50, len: 2, precision: 0}))
        assert_eq!(Numeric::from_str("50.25", 4, 2), Some(Numeric {value: 5025, len: 4, precision: 2}))
        assert_eq!(Numeric::from_str("-50.25", 4, 2), Some(Numeric {value: -5025, len: 4, precision: 2}))
        assert_eq!(Numeric::from_str("-50.250", 4, 2), Some(Numeric {value: -5025, len: 4, precision: 2}))
        assert_eq!(Numeric::from_str("-50.25", 5, 3), Some(Numeric {value: -50250, len: 5, precision: 3}))
        assert_eq!(Numeric::from_str("10.2.1", 4, 0), None)
        assert_eq!(Numeric::from_str("abc", 4, 0), None)
    }
}

trait PrimaryKey<T> {
    fn primary_key(&self) -> T;
}

trait FromRow {
    fn from_row(mut row: CharSplits<char>) -> Self;
}

#[deriving(Show)]
struct Table<Data, Index: Eq + Hash> {
    rows: Vec<Data>,
    index: HashMap<Index, uint>
}

impl<Data: PrimaryKey<Index> + Clone, Index: Eq + Hash> Table<Data, Index> {
    fn new() -> Table<Data, Index> {
        Table {
            rows: Vec::new(),
            index: HashMap::new()
        }
    }

    fn insert(&mut self, data: Data) {
        self.rows.push(data.clone());
        self.index.insert(data.primary_key(), self.rows.len() - 1);
    }

    fn size(&self) -> uint {
        self.rows.len()
    }
}

#[deriving(Clone, Show)]
struct Warehouse {
    w_id: i32,
    w_name: String,
    w_street_1: String,
    w_street_2: String,
    w_city: String,
    w_state: String,
    w_zip: String,
    w_tax: Numeric, // FIXME: numeric(4, 4)
    w_ytd: Numeric, // FIXME: numeric(12, 2)
}

impl PrimaryKey<i32> for Warehouse {
    fn primary_key(&self) -> i32 {
        self.w_id
    }
}

impl FromRow for Warehouse {
    fn from_row(mut row: CharSplits<char>) -> Warehouse {
        Warehouse {
            w_id: from_str(row.next().unwrap()).unwrap(),
            w_name: row.next().unwrap().into_string(),
            w_street_1: row.next().unwrap().into_string(),
            w_street_2: row.next().unwrap().into_string(),
            w_city: row.next().unwrap().into_string(),
            w_state: row.next().unwrap().into_string(),
            w_zip: row.next().unwrap().into_string(),
            w_tax: Numeric::from_str(row.next().unwrap(), 4, 4).unwrap(),
            w_ytd: Numeric::from_str(row.next().unwrap(), 12, 2).unwrap(),
        }
    }
}

type WarehouseTable = Table<Warehouse, i32>;

#[deriving(Clone, Show)]
struct District {
    d_id: i32,
    d_w_id: i32,
    d_name: String,
    d_street_1: String,
    d_street_2: String,
    d_city: String,
    d_state: String,
    d_zip: String,
    d_tax: Numeric, // numeric(4, 4)
    d_ytd: Numeric, // numeric(12,2)
    d_next_o_id: i32,
}

impl PrimaryKey<(i32, i32)> for District {
    fn primary_key(&self) -> (i32, i32) {
        (self.d_w_id, self.d_id)
    }
}

impl FromRow for District {
    fn from_row(mut row: CharSplits<char>) -> District {
        District {
            d_id: from_str(row.next().unwrap()).unwrap(),
            d_w_id: from_str(row.next().unwrap()).unwrap(),
            d_name: row.next().unwrap().into_string(),
            d_street_1: row.next().unwrap().into_string(),
            d_street_2: row.next().unwrap().into_string(),
            d_city: row.next().unwrap().into_string(),
            d_state: row.next().unwrap().into_string(),
            d_zip: row.next().unwrap().into_string(),
            d_tax: Numeric::from_str(row.next().unwrap(), 4, 4).unwrap(),
            d_ytd: Numeric::from_str(row.next().unwrap(), 12, 2).unwrap(),
            d_next_o_id: from_str(row.next().unwrap()).unwrap(),
        }
    }
}

type DistrictTable = Table<District, (i32, i32)>;

#[deriving(Clone, Show)]
struct Customer {
    c_id: i32,
    c_d_id: i32,
    c_w_id: i32,
    c_first: String,
    c_middle: String,
    c_last: String,
    c_street_1: String,
    c_street_2: String,
    c_city: String,
    c_state: String,
    c_zip: String,
    c_phone: String,
    c_since: i32, // Timestamp
    c_credit: String,
    c_credit_lim: Numeric, // numeric(12,2)
    c_discount: Numeric, // numeric(4, 4)
    c_balance: Numeric, // numeric(12,2)
    c_ytd_paymenr: Numeric, // numeric(12,2)
    c_payment_cnt: Numeric, // numeric(4,0)
    c_delivery_cnt: Numeric, // numeric(4,0)
    c_data: String,
}

impl PrimaryKey<(i32, i32, i32)> for Customer {
    fn primary_key(&self) -> (i32, i32, i32) {
        (self.c_w_id, self.c_d_id, self.c_id)
    }
}

impl FromRow for Customer {
    fn from_row(mut row: CharSplits<char>) -> Customer {
        Customer {
            c_id: from_str(row.next().unwrap()).unwrap(),
            c_d_id: from_str(row.next().unwrap()).unwrap(),
            c_w_id: from_str(row.next().unwrap()).unwrap(),
            c_first: row.next().unwrap().into_string(),
            c_middle: row.next().unwrap().into_string(),
            c_last: row.next().unwrap().into_string(),
            c_street_1: row.next().unwrap().into_string(),
            c_street_2: row.next().unwrap().into_string(),
            c_city: row.next().unwrap().into_string(),
            c_state: row.next().unwrap().into_string(),
            c_zip: row.next().unwrap().into_string(),
            c_phone: row.next().unwrap().into_string(),
            c_since: from_str(row.next().unwrap()).unwrap(), // Timestamp
            c_credit: row.next().unwrap().into_string(),
            c_credit_lim: Numeric::from_str(row.next().unwrap(), 12, 2).unwrap(), // numeric(12,2)
            c_discount: Numeric::from_str(row.next().unwrap(), 4, 4).unwrap(), // numeric(4, 4)
            c_balance: Numeric::from_str(row.next().unwrap(), 12, 2).unwrap(), // numeric(12,2)
            c_ytd_paymenr: Numeric::from_str(row.next().unwrap(), 12, 2).unwrap(), // numeric(12,2)
            c_payment_cnt: Numeric::from_str(row.next().unwrap(), 4, 0).unwrap(), // numeric(4,0)
            c_delivery_cnt: Numeric::from_str(row.next().unwrap(), 4, 0).unwrap(), // numeric(4,0)
            c_data: row.next().unwrap().into_string(),
        }
    }
}

type CustomerTable = Table<Customer, (i32, i32, i32)>;

#[deriving(Clone, Show)]
struct Neworder {
    no_o_id: i32,
    no_d_id: i32,
    no_w_id: i32,
}

impl PrimaryKey<(i32, i32, i32)> for Neworder {
    fn primary_key(&self) -> (i32, i32, i32) {
        (self.no_w_id, self.no_d_id, self.no_o_id)
    }
}

impl FromRow for Neworder {
    fn from_row(mut row: CharSplits<char>) -> Neworder {
        Neworder {
            no_o_id: from_str(row.next().unwrap()).unwrap(),
            no_d_id: from_str(row.next().unwrap()).unwrap(),
            no_w_id: from_str(row.next().unwrap()).unwrap(),
        }
    }
}

type NeworderTable = Table<Neworder, (i32, i32, i32)>;

#[deriving(Clone, Show)]
struct Order {
    o_id: i32,
    o_d_id: i32,
    o_w_id: i32,
    o_c_id: i32,
    o_entry_d: i32, // Timestamp
    o_carrier_id: i32,
    o_ol_cnt: Numeric, // numeric(2,0)
    o_all_local: Numeric, // numeric(1, 0)
}

impl PrimaryKey<(i32, i32, i32)> for Order {
    fn primary_key(&self) -> (i32, i32, i32) {
        (self.o_w_id, self.o_d_id, self.o_id)
    }
}

impl FromRow for Order {
    fn from_row(mut row: CharSplits<char>) -> Order {
        Order {
            o_id: from_str(row.next().unwrap()).unwrap(),
            o_d_id: from_str(row.next().unwrap()).unwrap(),
            o_w_id: from_str(row.next().unwrap()).unwrap(),
            o_c_id: from_str(row.next().unwrap()).unwrap(),
            o_entry_d: from_str(row.next().unwrap()).unwrap(),
            o_carrier_id: from_str(row.next().unwrap()).unwrap(),
            o_ol_cnt: Numeric::from_str(row.next().unwrap(), 2, 0).unwrap(),
            o_all_local: Numeric::from_str(row.next().unwrap(), 1, 0).unwrap(),
        }
    }
}

type OrderTable = Table<Order, (i32, i32, i32)>;

struct Tables {
    warehouse_table: WarehouseTable,
    district_table: DistrictTable,
    customer_table: CustomerTable,
    neworder_table: NeworderTable,
    order_table: OrderTable,
}

impl Tables {
    fn new() -> Tables {
        Tables {
            warehouse_table: Table::new(),
            district_table: Table::new(),
            customer_table: Table::new(),
            neworder_table: Table::new(),
            order_table: Table::new(),
        }
    }
}

fn read_table<Data: Clone + FromRow + PrimaryKey<Index>, Index: Eq + Hash>
        (filename: &str, table: &mut Table<Data, Index>) {
    let path = Path::new(filename);
    let mut file = BufferedReader::new(File::open(&path));
    for line in file.lines() {
        let row = FromRow::from_row(line.unwrap()[].trim_chars('\n').split('|'));
        table.insert(row);
    }
}

fn read_tables(tables: &mut Tables) {
    read_table::<Warehouse, i32>("../data/tpcc_warehouse.tbl", &mut tables.warehouse_table);
    read_table::<District, (i32, i32)>("../data/tpcc_district.tbl", &mut tables.district_table);
    read_table::<Customer, (i32, i32, i32)>("../data/tpcc_customer.tbl", &mut tables.customer_table);
    read_table::<Neworder, (i32, i32, i32)>("../data/tpcc_neworder.tbl", &mut tables.neworder_table);
    read_table::<Order, (i32, i32, i32)>("../data/tpcc_order.tbl", &mut tables.order_table);
}

fn main() {
    let time = precise_time_ns();

    let tables: &mut Tables =  &mut Tables::new();
    read_tables(tables);
    println!("Warehouse: {}", tables.warehouse_table.size());
    println!("District: {}", tables.district_table.size());
    println!("Customer: {}", tables.customer_table.size());
    println!("Neworder: {}", tables.neworder_table.size());
    println!("Order: {}", tables.order_table.size());

    println!("insert {}s", ((precise_time_ns() - time) as f64) / 1e9f64);
}
<|endoftext|>


<commit_before>extern crate getopts;
extern crate gmp;
extern crate vote;

use getopts::Options;
use gmp::mpq::Mpq;
use gmp::mpz::Mpz;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader, Read, Write, stdin, stderr};
use std::process::exit;
use std::str::FromStr;
use vote::schulze_stv::schulze_stv;

fn main() {
    let args = env::args().collect::<Vec<_>>();
    let program = &args[0];

    let mut opts = Options::new();
    opts.optflag("h", "help", "show this help message and exit");
    opts.optopt("w",
                "winners",
                "elect an N-winner committee (default: 1)",
                "N");
    let matches = match opts.parse(&args[1..]) {
        Err(fail) => {
            writeln!(&mut stderr(), "{}: {}", program, fail).unwrap();
            exit(1)
        }
        Ok(matches) => matches,
    };

    let usage = || opts.usage(&format!(
        "Usage: {} [-w N|--winners N] BALLOTFILE...

Each BALLOTFILE has one ballot description per line, with candidate
names separated by > or = to indicate strict and equal preference.
Prefixing a ballot with WEIGHT: makes WEIGHT copies of it.

  Chocolate > Vanilla > Strawberry > Cookie Dough
  Cookie Dough > Chocolate > Strawberry
  2: Strawberry = Chocolate > Vanilla

Candidate names are case-sensitive, and may include whitespace but may
not include > or =.  Whitespace around operators is ignored.
Candidates not listed in a ballot will be treated as tied for least
preferred.

Pass - to read ballots from stdin.",
        program));

    if matches.opt_present("h") {
        print!("{}", usage());
        return;
    }

    if matches.free.is_empty() {
        write!(&mut stderr(), "{}", usage()).unwrap();
        exit(1)
    }

    let num_seats = matches.opt_str("w").map(|s| s.parse().unwrap()).unwrap_or(1);

    let mut candidates = Vec::new();
    let mut candidate_index = HashMap::new();

    let ballots = matches.free
        .iter()
        .flat_map(|filename| {
            let file: Box<Read> = if filename == "-" {
                Box::new(stdin())
            } else {
                Box::new(File::open(filename).unwrap())
            };
            let buf = BufReader::new(file);
            buf.lines()
        })
        .map(|line| line.unwrap())
        .filter(|line| !line.trim().is_empty())
        .map(|line| {
            let (w, groups) = match line.find(':') {
                Some(i) => {
                    (Mpq::ratio(&Mpz::from_str(&line[..i]).unwrap(), &Mpz::one()), &line[i + 1..])
                }
                None => (Mpq::one(), &line[..]),
            };
            (groups.split('>')
                 .map(|group| {
                    group.split('=')
                        .map(|name| {
                            let name = name.trim();
                            match candidate_index.entry(name.to_string()) {
                                Entry::Occupied(e) => *e.get(),
                                Entry::Vacant(e) => {
                                    let n = candidates.len();
                                    e.insert(n);
                                    candidates.push(name.to_string());
                                    n
                                }
                            }
                        })
                        .collect::<Vec<_>>()
                        .into_boxed_slice()
                })
                 .collect::<Vec<_>>()
                 .into_boxed_slice(),
             w)
        })
        .collect::<Vec<_>>()
        .into_boxed_slice();

    if ballots.is_empty() {
        writeln!(&mut stderr(), "error: No ballots found").unwrap();
        exit(1);
    }

    println!("Tallying Schulze STV election.");
    println!("");

    println!("Candidates ({}):", candidates.len());
    let mut candidates_sorted = candidates.clone();
    candidates_sorted.sort();
    for candidate in &candidates_sorted {
        println!("  {}", candidate);
    }
    println!("");

    let total_weight = ballots.iter().map(|&(_, ref w)| w).fold(Mpq::zero(), |acc, x| acc + x);
    println!("Ballots ({:?}):", total_weight);
    for &(ref groups, ref w) in ballots.iter() {
        println!("  {:?}: {}",
                 w,
                 groups.iter()
                     .map(|group| {
                         group.iter().map(|&c| &candidates[c][..]).collect::<Vec<_>>().join(" = ")
                     })
                     .collect::<Vec<_>>()
                     .join(" > "));
    }
    println!("");

    let mut winners = schulze_stv(candidates.len(), num_seats, &ballots);

    for set in winners.iter_mut() {
        set.sort_by(|&a, &b| candidates[a].cmp(&candidates[b]));
    }
    winners.sort_by(|a, b| {
        a.iter().map(|&i| &candidates[i]).cmp(b.iter().map(|&i| &candidates[i]))
    });

    let set_suffix = if num_seats == 1 { "" } else { " set" };
    if winners.len() == 1 {
        println!("Winner{}:", set_suffix);
    } else {
        println!("Tied winner{}s:", set_suffix);
    }
    for set in winners.iter() {
        println!("  {}",
                 set.iter().map(|&c| &candidates[c][..]).collect::<Vec<_>>().join(", "));
    }
}
<commit_msg>Support --version<commit_after>extern crate getopts;
extern crate gmp;
extern crate vote;

use getopts::Options;
use gmp::mpq::Mpq;
use gmp::mpz::Mpz;
use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader, Read, Write, stdin, stderr};
use std::process::exit;
use std::str::FromStr;
use vote::schulze_stv::schulze_stv;

fn main() {
    let args = env::args().collect::<Vec<_>>();
    let program = &args[0];

    let mut opts = Options::new();
    opts.optopt("w",
                "winners",
                "elect an N-winner committee (default: 1)",
                "N");
    opts.optflag("", "help", "show this help message and exit");
    opts.optflag("", "version", "show the program version and exit");
    let matches = match opts.parse(&args[1..]) {
        Err(fail) => {
            writeln!(&mut stderr(), "{}: {}", program, fail).unwrap();
            exit(1)
        }
        Ok(matches) => matches,
    };

    let usage = || opts.usage(&format!(
        "Usage: {} [-w N|--winners N] BALLOTFILE...

Each BALLOTFILE has one ballot description per line, with candidate
names separated by > or = to indicate strict and equal preference.
Prefixing a ballot with WEIGHT: makes WEIGHT copies of it.

  Chocolate > Vanilla > Strawberry > Cookie Dough
  Cookie Dough > Chocolate > Strawberry
  2: Strawberry = Chocolate > Vanilla

Candidate names are case-sensitive, and may include whitespace but may
not include > or =.  Whitespace around operators is ignored.
Candidates not listed in a ballot will be treated as tied for least
preferred.

Pass - to read ballots from stdin.",
        program));

    if matches.opt_present("help") {
        print!("{}", usage());
        return;
    }

    if matches.opt_present("version") {
        println!("elect {}", env!("CARGO_PKG_VERSION"));
        return;
    }

    if matches.free.is_empty() {
        write!(&mut stderr(), "{}", usage()).unwrap();
        exit(1)
    }

    let num_seats = matches.opt_str("w").map(|s| s.parse().unwrap()).unwrap_or(1);

    let mut candidates = Vec::new();
    let mut candidate_index = HashMap::new();

    let ballots = matches.free
        .iter()
        .flat_map(|filename| {
            let file: Box<Read> = if filename == "-" {
                Box::new(stdin())
            } else {
                Box::new(File::open(filename).unwrap())
            };
            let buf = BufReader::new(file);
            buf.lines()
        })
        .map(|line| line.unwrap())
        .filter(|line| !line.trim().is_empty())
        .map(|line| {
            let (w, groups) = match line.find(':') {
                Some(i) => {
                    (Mpq::ratio(&Mpz::from_str(&line[..i]).unwrap(), &Mpz::one()), &line[i + 1..])
                }
                None => (Mpq::one(), &line[..]),
            };
            (groups.split('>')
                 .map(|group| {
                    group.split('=')
                        .map(|name| {
                            let name = name.trim();
                            match candidate_index.entry(name.to_string()) {
                                Entry::Occupied(e) => *e.get(),
                                Entry::Vacant(e) => {
                                    let n = candidates.len();
                                    e.insert(n);
                                    candidates.push(name.to_string());
                                    n
                                }
                            }
                        })
                        .collect::<Vec<_>>()
                        .into_boxed_slice()
                })
                 .collect::<Vec<_>>()
                 .into_boxed_slice(),
             w)
        })
        .collect::<Vec<_>>()
        .into_boxed_slice();

    if ballots.is_empty() {
        writeln!(&mut stderr(), "error: No ballots found").unwrap();
        exit(1);
    }

    println!("Tallying Schulze STV election.");
    println!("");

    println!("Candidates ({}):", candidates.len());
    let mut candidates_sorted = candidates.clone();
    candidates_sorted.sort();
    for candidate in &candidates_sorted {
        println!("  {}", candidate);
    }
    println!("");

    let total_weight = ballots.iter().map(|&(_, ref w)| w).fold(Mpq::zero(), |acc, x| acc + x);
    println!("Ballots ({:?}):", total_weight);
    for &(ref groups, ref w) in ballots.iter() {
        println!("  {:?}: {}",
                 w,
                 groups.iter()
                     .map(|group| {
                         group.iter().map(|&c| &candidates[c][..]).collect::<Vec<_>>().join(" = ")
                     })
                     .collect::<Vec<_>>()
                     .join(" > "));
    }
    println!("");

    let mut winners = schulze_stv(candidates.len(), num_seats, &ballots);

    for set in winners.iter_mut() {
        set.sort_by(|&a, &b| candidates[a].cmp(&candidates[b]));
    }
    winners.sort_by(|a, b| {
        a.iter().map(|&i| &candidates[i]).cmp(b.iter().map(|&i| &candidates[i]))
    });

    let set_suffix = if num_seats == 1 { "" } else { " set" };
    if winners.len() == 1 {
        println!("Winner{}:", set_suffix);
    } else {
        println!("Tied winner{}s:", set_suffix);
    }
    for set in winners.iter() {
        println!("  {}",
                 set.iter().map(|&c| &candidates[c][..]).collect::<Vec<_>>().join(", "));
    }
}
<|endoftext|>


<commit_before>extern crate yaml_rust;
extern crate regex;

use std::fs::File;
use std::io::prelude::*;
use std::net::TcpListener;
use std::time::Duration;
use std::sync::Arc;
use std::thread;
use std::process::exit;
use yaml_rust::YamlLoader;
use regex::bytes::RegexSetBuilder;

#[derive(Copy, Clone)]
struct App {
  print_ascii: bool,
  print_binary: bool
}

fn main() {
  let mut app = App { print_ascii: false, print_binary: false };
  let binary_matches = [
    ("SSL3.0 Record Protocol", r"^\x16\x03\x00..\x01"),
    ("TLS1.0 Record Protocol", r"^\x16\x03\x01..\x01"),
    ("TLS1.1 Record Protocol", r"^\x16\x03\x02..\x01"),
    ("TLS1.2 Record Protocol", r"^\x16\x03\x03..\x01"),
    ("SSL3.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x00"),
    ("TLS1.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x01"),
    ("TLS1.1 CLIENT_HELLO", r"^\x16....\x01...\x03\x02"),
    ("TLS1.2 CLIENT_HELLO", r"^\x16....\x01...\x03\x03"),
    ("SMB1 COMMAND NEGOTIATE", r"^....\xffSMB\x72"),
    ("SMB1 NT_STATUS Success", r"^....\xffSMB.[\x00-\x0f]"),
    ("SMB1 NT_STATUS Information", r"^....\xffSMB.[\x40-\x4f]"),
    ("SMB1 NT_STATUS Warning", r"^....\xffSMB.[\x80-\x8f]"),
    ("SMB1 NT_STATUS Error", r"^....\xffSMB.[\xc0-\xcf]")
  ];
  let io_timeout = Duration::new(300, 0); // 5 minutes

  let mut file = File::open("config.yml").unwrap();
  let mut config_str = String::new();
  file.read_to_string(&mut config_str).unwrap();
  let docs = YamlLoader::load_from_str(&config_str).unwrap();
  let config = &docs[0];
  //println!("{:?}", config);
  if config["general"].is_badvalue() {
    println!("No 'general' section found in configuration file");
    exit(-1);
  }
  if config["ports"].is_badvalue() {
    println!("No 'ports' section found in configuration file");
    exit(-1);
  }
  if !config["general"]["print_ascii"].is_badvalue() {
    if config["general"]["print_ascii"].as_bool().unwrap() {
      app.print_ascii = true;
      println!("Printing ascii");
    }
  }
  if !config["general"]["print_binary"].is_badvalue() {
    if config["general"]["print_binary"].as_bool().unwrap() {
      app.print_binary = true;
      println!("Printing binary");
    }
  }
  let app = app; // Revert to immutable

  let mut patterns = Vec::with_capacity(binary_matches.len());
  for &(_, pattern) in binary_matches.into_iter() {
    patterns.push(pattern);
  }
  let regexset = RegexSetBuilder::new(patterns)
    .unicode(false)
    .dot_matches_new_line(false)
    .build().unwrap();

  for port in config["ports"].as_vec().unwrap() {
    if !port["tcp"].is_badvalue() {
      let portno = port["tcp"].as_i64().unwrap();
      println!("TCP port {}", portno);
      let mut banner = Arc::new(String::new());
      if let Some(x) = port["banner"].as_str() {
        Arc::get_mut(& mut banner).unwrap().push_str(x);
        println!("  with banner: {}", *banner);
      }
      let regexset = regexset.clone();
      thread::spawn(move || {
        let server = TcpListener::bind(("0.0.0.0", portno as u16)).unwrap();
        for res in server.incoming() {
          let mut stream = res.unwrap();
          stream.set_read_timeout(Some(io_timeout)).expect("Failed to set read timeout on TcpStream");
          stream.set_write_timeout(Some(io_timeout)).expect("Failed to set write timeout on TcpStream");
          let addr = stream.peer_addr().unwrap();
          println!("CONNECT TCP {} from {}", portno, addr);
          let regexset = regexset.clone();
          let banner = banner.clone();
          thread::spawn(move || {
            if banner.len() > 0 {
              match stream.write((*banner).as_bytes()) {
                Ok(_) => {
                  for line in (*banner).lines() {
                    println!("> {}", line);
                  }
                }
                Err(e) => {
                  println!("WRITE ERROR TCP {} from {}: {}", portno, addr, e.to_string());
                  return;
                }
              }
            }
            let mut buf: [u8; 2048] = [0; 2048];
            loop {
              match stream.read(&mut buf) {
                Ok(c) => {
                  if c == 0 {
                    println!("CLOSE TCP {} from {}", portno, addr);
                    break;
                  }
                  let mut printables = Vec::new();
                  let mut found = false;
                  let mut start = 0;
                  for i in 0..buf.len() {
                    if (buf[i] > 31 && buf[i] < 127) || buf[i] == 10 || buf[i] == 13 {
                      if !found {
                        start = i;
                        found = true;
                      }
                    }
                    else {
                      if found {
                        printables.push(&buf[start..i]);
                        found = false;
                      }
                    }
                  }
                  if printables.len() == 1 && printables[0].len() == c {
                    if app.print_ascii {
                      let data = String::from_utf8_lossy(printables[0]);
                      for line in data.lines() {
                        println!("| {}", line);
                      }
                    }
                    else { println!("! Read {} bytes of printable ascii", c); }
                    if app.print_binary { println!("! {:?}", &buf[..c]); }
                  }
                  else {
                    println!("! Read {} bytes of binary", c);
                    if app.print_binary { println!("! {:?}", &buf[..c]); }
                    for id in regexset.matches(&buf[..c]).into_iter() {
                      println!("! Matches pattern {}", binary_matches[id].0);
                    }
                    for printable in printables {
                      if printable.len() > 3 {
                        let data = String::from_utf8_lossy(printable);
                        for line in data.lines() {
                          println!("$ {}", line);
                        }
                      }
                    }
                  }
                }
                Err(e) => {
                  println!("READ ERROR TCP {} from {}: {}", portno, addr, e.to_string());
                  break;
                }
              }
              match stream.take_error() {
                Ok(opt) => {
                  if opt.is_some() {
                    println!("ERROR TCP {} from {}: {}", portno, addr, opt.unwrap().to_string());
                    break;
                  }
                }
                Err(_) => {
                  println!("This shouldn't happen...");
                  break;
                }
              }
            }
          });
        }
      });
    }
    else if !port["udp"].is_badvalue() {
      println!("UDP port {}", port["udp"].as_i64().unwrap());
    }
    else {
      println!("Invalid port specification in configuration file");
    }
  }

  loop { thread::sleep(Duration::new(60, 0)); }
}
<commit_msg>Also show the last line of decoded hex<commit_after>extern crate yaml_rust;
extern crate regex;

use std::fs::File;
use std::io::prelude::*;
use std::net::TcpListener;
use std::time::Duration;
use std::sync::Arc;
use std::thread;
use std::process::exit;
use yaml_rust::YamlLoader;
use regex::bytes::RegexSetBuilder;

#[derive(Copy, Clone)]
struct App {
  print_ascii: bool,
  print_binary: bool
}

fn to_hex(bytes: &[u8]) -> String {
  let mut count = 0;
  let mut result = String::with_capacity(66);
  let mut dotline = String::with_capacity(18);

  for byte in bytes.iter() {
    if count != 0 && count%8 == 0 {
      if count%16 == 0 {
        dotline.push('\n');
        result.push_str(&dotline);
        result.reserve(33);
        dotline.truncate(0);
      }
      else {
        result.push(' ');
        dotline.push(' ');
      }
    }
    result.push_str(&format!("{:02X} ", byte));
    if *byte > 31 && *byte < 127 { dotline.push(*byte as char) }
    else if *byte == 0 { dotline.push('-'); }
    else { dotline.push('.'); }
    count += 1;
  }
  while count%16 != 0 {
    if count%8 == 0 { result.push(' '); }
    result.push_str("   ");
    count += 1;
  }
  if dotline.len() != 0 { result.push_str(&dotline); }
  result
}

fn main() {
  let mut app = App { print_ascii: false, print_binary: false };
  let binary_matches = [
    ("SSL3.0 Record Protocol", r"^\x16\x03\x00..\x01"),
    ("TLS1.0 Record Protocol", r"^\x16\x03\x01..\x01"),
    ("TLS1.1 Record Protocol", r"^\x16\x03\x02..\x01"),
    ("TLS1.2 Record Protocol", r"^\x16\x03\x03..\x01"),
    ("SSL3.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x00"),
    ("TLS1.0 CLIENT_HELLO", r"^\x16....\x01...\x03\x01"),
    ("TLS1.1 CLIENT_HELLO", r"^\x16....\x01...\x03\x02"),
    ("TLS1.2 CLIENT_HELLO", r"^\x16....\x01...\x03\x03"),
    ("SMB1 COMMAND NEGOTIATE", r"^....\xffSMB\x72"),
    ("SMB1 NT_STATUS Success", r"^....\xffSMB.[\x00-\x0f]"),
    ("SMB1 NT_STATUS Information", r"^....\xffSMB.[\x40-\x4f]"),
    ("SMB1 NT_STATUS Warning", r"^....\xffSMB.[\x80-\x8f]"),
    ("SMB1 NT_STATUS Error", r"^....\xffSMB.[\xc0-\xcf]")
  ];
  let io_timeout = Duration::new(300, 0); // 5 minutes

  let mut file = File::open("config.yml").unwrap();
  let mut config_str = String::new();
  file.read_to_string(&mut config_str).unwrap();
  let docs = YamlLoader::load_from_str(&config_str).unwrap();
  let config = &docs[0];
  //println!("{:?}", config);
  if config["general"].is_badvalue() {
    println!("No 'general' section found in configuration file");
    exit(-1);
  }
  if config["ports"].is_badvalue() {
    println!("No 'ports' section found in configuration file");
    exit(-1);
  }
  if !config["general"]["print_ascii"].is_badvalue() {
    if config["general"]["print_ascii"].as_bool().unwrap() {
      app.print_ascii = true;
      println!("Printing ascii");
    }
  }
  if !config["general"]["print_binary"].is_badvalue() {
    if config["general"]["print_binary"].as_bool().unwrap() {
      app.print_binary = true;
      println!("Printing binary in hexadecimal");
    }
  }
  let app = app; // Revert to immutable

  let mut patterns = Vec::with_capacity(binary_matches.len());
  for &(_, pattern) in binary_matches.into_iter() {
    patterns.push(pattern);
  }
  let regexset = RegexSetBuilder::new(patterns)
    .unicode(false)
    .dot_matches_new_line(false)
    .build().unwrap();

  for port in config["ports"].as_vec().unwrap() {
    if !port["tcp"].is_badvalue() {
      let portno = port["tcp"].as_i64().unwrap();
      println!("TCP port {}", portno);
      let mut banner = Arc::new(String::new());
      if let Some(x) = port["banner"].as_str() {
        Arc::get_mut(& mut banner).unwrap().push_str(x);
        println!("  with banner: {}", *banner);
      }
      let regexset = regexset.clone();
      thread::spawn(move || {
        let server = TcpListener::bind(("0.0.0.0", portno as u16)).unwrap();
        for res in server.incoming() {
          let mut stream = res.unwrap();
          stream.set_read_timeout(Some(io_timeout)).expect("Failed to set read timeout on TcpStream");
          stream.set_write_timeout(Some(io_timeout)).expect("Failed to set write timeout on TcpStream");
          let addr = stream.peer_addr().unwrap();
          println!("CONNECT TCP {} from {}", portno, addr);
          let regexset = regexset.clone();
          let banner = banner.clone();
          thread::spawn(move || {
            if banner.len() > 0 {
              match stream.write((*banner).as_bytes()) {
                Ok(_) => {
                  for line in (*banner).lines() {
                    println!("> {}", line);
                  }
                }
                Err(e) => {
                  println!("WRITE ERROR TCP {} from {}: {}", portno, addr, e.to_string());
                  return;
                }
              }
            }
            let mut buf: [u8; 2048] = [0; 2048];
            loop {
              match stream.read(&mut buf) {
                Ok(c) => {
                  if c == 0 {
                    println!("CLOSE TCP {} from {}", portno, addr);
                    break;
                  }
                  let mut printables = Vec::new();
                  let mut found = false;
                  let mut start = 0;
                  for i in 0..buf.len() {
                    if (buf[i] > 31 && buf[i] < 127) || buf[i] == 10 || buf[i] == 13 {
                      if !found {
                        start = i;
                        found = true;
                      }
                    }
                    else {
                      if found {
                        printables.push(&buf[start..i]);
                        found = false;
                      }
                    }
                  }
                  if printables.len() == 1 && printables[0].len() == c {
                    if app.print_ascii {
                      let data = String::from_utf8_lossy(printables[0]);
                      for line in data.lines() {
                        println!("| {}", line);
                      }
                    }
                    else { println!("! Read {} bytes of printable ascii", c); }
                  }
                  else {
                    println!("! Read {} bytes of binary", c);
                    for id in regexset.matches(&buf[..c]).into_iter() {
                      println!("^ Matches pattern {}", binary_matches[id].0);
                    }
                    for printable in printables {
                      if printable.len() > 3 {
                        let data = String::from_utf8_lossy(printable);
                        for line in data.lines() {
                          println!("$ {}", line);
                        }
                      }
                    }
                    if app.print_binary {
                      let hex = to_hex(&buf[..c]);
                      for line in hex.lines() { println!(". {}", line); }
                    }
                  }
                }
                Err(e) => {
                  println!("READ ERROR TCP {} from {}: {}", portno, addr, e.to_string());
                  break;
                }
              }
              match stream.take_error() {
                Ok(opt) => {
                  if opt.is_some() {
                    println!("ERROR TCP {} from {}: {}", portno, addr, opt.unwrap().to_string());
                    break;
                  }
                }
                Err(_) => {
                  println!("This shouldn't happen...");
                  break;
                }
              }
            }
          });
        }
      });
    }
    else if !port["udp"].is_badvalue() {
      println!("UDP port {}", port["udp"].as_i64().unwrap());
    }
    else {
      println!("Invalid port specification in configuration file");
    }
  }

  loop { thread::sleep(Duration::new(60, 0)); }
}
<|endoftext|>


<commit_before>use std::env;
use std::str;
use std::path::Path;
use std::char;

/*
vector: 10101010
key:    0111111101

byte 1: 00000001  -> 11110100
byte 2: 00100011  -> 00001011

plain                cipher
00000001 00100011 -> 11110100 00001011

% cargo run [-d] <init_key> <init_vector> <original_file> <result_file>
cargo run -d 0111111101 10101010 file1 file2 //decrypts

*/

struct Crypto {
    flag: char,
    init_key: u16,
    init_vec: u8,
    init_key_str: String,
    init_vec_str: String,
    key_one: u8,
    key_two: u8,
    original_file: String,
    output_file: String
}

fn check_flag(index: usize) -> bool
{
    let flag = env::args().nth(index).unwrap();
    match flag.as_ref() {
        "d" => true,
        _ => {
            println!("incorrect flag");
            false
        }
    }
}

fn check_key(index: usize) -> bool
{
    let key = env::args().nth(index).unwrap();
    let key_len = key.len();
    let mut count = 0;

    println!("init_key: {:?}", key);

    match key_len {
        10 => {
            for c in key.chars()
            {
                match c {
                    '0' => continue,
                    '1' => continue,
                    _ =>
                    {
                        println!("init key must be binary (0s and 1s only)");
                        count = count + 1;
                    }
                }
            }

            match count {
                0 => true,
                _ => false
            }
        },
        _ => {
            println!("init key must be 10 bits long!");
            false
        }
    }
}

fn check_vector(index: usize) -> bool
{
    let vector = env::args().nth(index).unwrap();
    let vector_len = vector.len();
    let mut count = 0;

    println!("init_vec: {:?}", vector);

    match vector_len {
        8 => {
            for c in vector.chars()
            {
                match c {
                    '0' => continue,
                    '1' => continue,
                    _ =>
                    {
                        println!("vector must be binary (0s and 1s only)");
                        count = count + 1;
                    }
                }
            }

            match count {
                0 => true,
                _ => false
            }
        },
        _ => {
            println!("init key must be 8 bits long!");
            false
        }
    }
}

fn check_file(index: usize) -> bool
{
    let mut path = String::from("./");
    let file_name = String::from(env::args().nth(index).unwrap());
    path.push_str(&file_name);
    let check = Path::new(&path).is_file();
    match check
    {
        true => {
            println!("file    : {:?}", file_name);
            true
        },
        _ => {
            println!("file not found");
            false
        }
    }
}

fn check_arguments() -> bool
{
    let args_amount = env::args().len() - 1;
    match args_amount {
        4 => {
            println!("encryption mode");
            match check_key(1) //key is arg #1
            {
                true => {
                    match check_vector(2)
                    {
                        true => {
                            match check_file(3)
                            {
                                true => true,
                                _ => false
                            }
                        },
                        _ => false
                    }
                },
                _ => false
            }
        },
        5 => {
            println!("decryption mode");
            match check_flag(1) //flag is arg #1
            {
                true => {
                    match check_key(2)
                    {
                        true => match check_vector(3)
                        {
                            true => {
                                match check_file(4)
                                {
                                    true => true,
                                    _ => false
                                }
                            },
                            _ => false
                        },
                        _ => false
                    }
                },
                _ => false
            }

        },
        _ => {
            println!("incorrect amount of arguments");
            println!("cargo run [d] <init_key> <init_vector> <original_file> <result_file>");
            false
        },
    }
}

fn key_to_bits(key_string: &String) -> u16
{
    let text_key = key_string;
    let mut sixteen_bit: u16 = 0b0000_0000_0000_0000;

    for c in text_key.chars()
    {
        match c {
            '0' => {
                sixteen_bit = sixteen_bit.rotate_left(1);
            }
            '1' => {
                sixteen_bit |= 0b1000_0000_0000_0000;
                sixteen_bit = sixteen_bit.rotate_left(1);
            }
            _ => println!("failed to convert key to bits"),
        }
    }
    //sixteen_bit.leading_zeros());
    println!("{:?} -> {:010b}_bin", text_key, sixteen_bit);
    sixteen_bit
}

fn vec_to_bits(vec_string: &String) -> u8
{
    // u8 = 0b0000_0000;
    let text_vec = vec_string;
    let mut eight_bit: u8 = 0b0000_0000;

    for c in text_vec.chars()
    {
        match c {
            '0' => {
                eight_bit = eight_bit.rotate_left(1);
            },
            '1' => {
                eight_bit |= 0b1000_0000; //set first bit
                eight_bit = eight_bit.rotate_left(1);
            },
            _ => println!("failed to convert vector to bits"),
        }
    }
    println!("{:?}   -> {:08b}_bin", text_vec, eight_bit);
    eight_bit
}

fn permute_ten(init_key_str: String) -> String
{
    let mut permuted_chars: Vec<char> = Vec::new();
    let mut permuted_string = String::with_capacity(10);
    let p_ten: [usize;10] = [3,5,2,7,4,10,1,9,8,6];

    for x in 0..10 {
        permuted_chars.push(init_key_str.chars().nth(p_ten[x]-1).unwrap() as char);
    }

    for c in &permuted_chars // to avoid 'move' errors, we pass a reference
    {                        // as '&permuted_chars' and dereference '*c'
        permuted_string.push(*c);
    }

    println!("{:?} ==P10=> {:?}", init_key_str, permuted_string);
    permuted_string
}

fn circular_left_shift(init_key_str: &String, half: usize) -> u8
{
    let mut first_half_str = init_key_str.clone();
    let second_half_str = first_half_str.split_off(5);

    let mut first_half_bits  = 0b0000_0000;
    let mut second_half_bits = 0b0000_0000;

    //catch the half we want to work on
    match half {
        1 => {
            println!("performing shift on: {:?}", first_half_str);
            first_half_bits = vec_to_bits(&first_half_str);
            first_half_bits = first_half_bits.rotate_left(4);
            println!("fuck me: {:05b}_bin", first_half_bits);
            return first_half_bits
        },
        2 => {
            println!("performing shift on: {:?}", second_half_str);
        },
        _ => println!("invalid half")
    }
    162
}

fn main() {

    if check_arguments() == false
    {
        std::process::exit(1);
    }

    let mut cr = Crypto {
        flag: ' ',
        init_key: 0b0000000000000000,
        init_vec: 0b00000000,
        init_key_str: String::new(),
        init_vec_str: String::new(),
        key_one: 0b00000000,
        key_two: 0b00000000,
        original_file: String::new(),
        output_file: String::new()
    };

    let args_amount = env::args().len() - 1;
    match args_amount {
        4 => {
            cr.flag='e';
            cr.init_key_str = String::from(env::args().nth(1).unwrap());
            cr.init_vec_str = String::from(env::args().nth(2).unwrap());
            cr.init_key = key_to_bits(&cr.init_key_str);
            cr.init_vec = vec_to_bits(&cr.init_vec_str);
            cr.original_file = env::args().nth(3).unwrap();
            cr.output_file = env::args().nth(4).unwrap();
        },
        5 => {
            cr.flag = 'd';
            cr.init_key_str = String::from(env::args().nth(2).unwrap());
            cr.init_vec_str = String::from(env::args().nth(3).unwrap());
            cr.init_key = key_to_bits(&cr.init_key_str);
            cr.init_vec = vec_to_bits(&cr.init_vec_str);
            cr.original_file = env::args().nth(4).unwrap();
            cr.output_file = env::args().nth(5).unwrap();
        }
        _ => std::process::exit(1)
    }

    println!("cr: {:?} {:010b} {:08b} {:?} {:?}", cr.flag,
                                                  cr.init_key,
                                                  cr.init_vec,
                                                  cr.original_file,
                                                  cr.output_file);

    /* * * * * * * * * *
     * KEY GENERATION *
     * * * * * * * * */

    println!("key generation:");
    //P10
    cr.init_key_str = permute_ten(cr.init_key_str);

    //Circular Left Shift (LS-1) on first 5 bits of P10
    circular_left_shift(&cr.init_key_str, 1);

    //Circular Left Shift (LS-1) on last 5 bits of P10
    //circular_left_shift(&cr.init_key_str, 2);
    //P8 (picks and permutes 8 out of 10 bits) = K1

}
<commit_msg>LS1 implemented<commit_after>use std::env;
use std::str;
use std::path::Path;
use std::char;

/*
vector: 10101010
key:    0111111101

byte 1: 00000001  -> 11110100
byte 2: 00100011  -> 00001011

plain                cipher
00000001 00100011 -> 11110100 00001011

% cargo run [-d] <init_key> <init_vector> <original_file> <result_file>
cargo run d 0111111101 10101010 file1 file2 //decrypts
cargo run d 1010000010 10101010 file1 file2

key: 01111_11101
01111_11101 =p10=> 11111_10011
[1: 11111] [2: 10011]
LS1(11111) => 11111
LS1(10011) => 00111
*/

struct Crypto {
    flag: char,
    init_key: u16,
    init_vec: u8,
    init_key_str: String,
    init_vec_str: String,
    key_one: u8,
    key_two: u8,
    original_file: String,
    output_file: String
}

fn check_flag(index: usize) -> bool
{
    let flag = env::args().nth(index).unwrap();
    match flag.as_ref() {
        "d" => true,
        _ => {
            println!("incorrect flag");
            false
        }
    }
}

fn check_key(index: usize) -> bool
{
    let key = env::args().nth(index).unwrap();
    let key_len = key.len();
    let mut count = 0;

    println!("init_key: {:?}", key);

    match key_len {
        10 => {
            for c in key.chars()
            {
                match c {
                    '0' => continue,
                    '1' => continue,
                    _ =>
                    {
                        println!("init key must be binary (0s and 1s only)");
                        count = count + 1;
                    }
                }
            }

            match count {
                0 => true,
                _ => false
            }
        },
        _ => {
            println!("init key must be 10 bits long!");
            false
        }
    }
}

fn check_vector(index: usize) -> bool
{
    let vector = env::args().nth(index).unwrap();
    let vector_len = vector.len();
    let mut count = 0;

    println!("init_vec: {:?}", vector);

    match vector_len {
        8 => {
            for c in vector.chars()
            {
                match c {
                    '0' => continue,
                    '1' => continue,
                    _ =>
                    {
                        println!("vector must be binary (0s and 1s only)");
                        count = count + 1;
                    }
                }
            }

            match count {
                0 => true,
                _ => false
            }
        },
        _ => {
            println!("init key must be 8 bits long!");
            false
        }
    }
}

fn check_file(index: usize) -> bool
{
    let mut path = String::from("./");
    let file_name = String::from(env::args().nth(index).unwrap());
    path.push_str(&file_name);
    let check = Path::new(&path).is_file();
    match check
    {
        true => {
            println!("file    : {:?}", file_name);
            true
        },
        _ => {
            println!("file not found");
            false
        }
    }
}

fn check_arguments() -> bool
{
    let args_amount = env::args().len() - 1;
    match args_amount {
        4 => {
            println!("encryption mode");
            match check_key(1) //key is arg #1
            {
                true => {
                    match check_vector(2)
                    {
                        true => {
                            match check_file(3)
                            {
                                true => true,
                                _ => false
                            }
                        },
                        _ => false
                    }
                },
                _ => false
            }
        },
        5 => {
            println!("decryption mode");
            match check_flag(1) //flag is arg #1
            {
                true => {
                    match check_key(2)
                    {
                        true => match check_vector(3)
                        {
                            true => {
                                match check_file(4)
                                {
                                    true => true,
                                    _ => false
                                }
                            },
                            _ => false
                        },
                        _ => false
                    }
                },
                _ => false
            }

        },
        _ => {
            println!("incorrect amount of arguments");
            println!("cargo run [d] <init_key> <init_vector> <original_file> <result_file>");
            false
        },
    }
}

fn key_to_bits(key_string: &String) -> u16
{
    let text_key = key_string;
    let mut sixteen_bit: u16 = 0b0000_0000_0000_0000;

    for c in text_key.chars()
    {
        match c {
            '0' => {
                sixteen_bit = sixteen_bit.rotate_left(1);
            }
            '1' => {
                sixteen_bit |= 0b1000_0000_0000_0000;
                sixteen_bit = sixteen_bit.rotate_left(1);
            }
            _ => println!("failed to convert key to bits"),
        }
    }
    //sixteen_bit.leading_zeros());
    //println!("{:?} -> {:010b}_bin", text_key, sixteen_bit);
    sixteen_bit
}

fn vec_to_bits(vec_string: &String) -> u8
{
    // u8 = 0b0000_0000;
    let text_vec = vec_string;
    let mut eight_bit: u8 = 0b0000_0000;

    for c in text_vec.chars()
    {
        match c {
            '0' => {
                eight_bit = eight_bit.rotate_left(1);
            },
            '1' => {
                eight_bit |= 0b1000_0000; //set first bit
                eight_bit = eight_bit.rotate_left(1);
            },
            _ => println!("failed to convert vector to bits"),
        }
    }
    //println!("{:?}   -> {:08b}_bin", text_vec, eight_bit);
    eight_bit
}

fn permute_ten(init_key_str: String) -> String
{
    let mut permuted_chars: Vec<char> = Vec::new();
    let mut permuted_string = String::with_capacity(10);
    let p_ten: [usize;10] = [3,5,2,7,4,10,1,9,8,6];

    for x in 0..10 {
        permuted_chars.push(init_key_str.chars().nth(p_ten[x]-1).unwrap() as char);
    }

    for c in &permuted_chars // to avoid 'move' errors, we pass a reference
    {                        // as '&permuted_chars' and dereference '*c'
        permuted_string.push(*c);
    }

    println!("{:?} ==P10=> {:?}", init_key_str, permuted_string);
    permuted_string
}

fn left_shift_one(value: u8) -> u8
{
    let mut mask: u8 = 31; //0001 1111
    let side = (value <<1) | (value >> (5 - 1));

    return mask & side;
}

fn circular_left_shift(init_key_str: &String) -> u8
{
    let mut first_half_str = init_key_str.clone();
    let second_half_str = first_half_str.split_off(5);

    let mut first_half_bits: u8 =  0b0000_0000;
    let mut second_half_bits: u8 = 0b0000_0000;

    // e.g.: 10000 01100

    //LS1 on first half: 10000 -> 00001
    first_half_bits = vec_to_bits(&first_half_str);
    let first_rotated_bits = left_shift_one(first_half_bits);
    println!("{:05b} =LS1=> {:05b}_bin", first_half_bits, first_rotated_bits);

    //LS1 on second half: 01100 -> 11000
    second_half_bits = vec_to_bits(&second_half_str);
    let second_rotated_bits = left_shift_one(second_half_bits);
    println!("{:05b} =LS1=> {:05b}_bin", second_half_bits, second_rotated_bits);

    //reassemble
    let assembled: u16 = 0b0000_0000_0000_0000;

    12
}

fn main() {

    if check_arguments() == false
    {
        std::process::exit(1);
    }

    let mut cr = Crypto {
        flag: ' ',
        init_key: 0b0000000000000000,
        init_vec: 0b00000000,
        init_key_str: String::new(),
        init_vec_str: String::new(),
        key_one: 0b00000000,
        key_two: 0b00000000,
        original_file: String::new(),
        output_file: String::new()
    };

    let args_amount = env::args().len() - 1;
    match args_amount {
        4 => {
            cr.flag='e';
            cr.init_key_str = String::from(env::args().nth(1).unwrap());
            cr.init_vec_str = String::from(env::args().nth(2).unwrap());
            cr.init_key = key_to_bits(&cr.init_key_str);
            cr.init_vec = vec_to_bits(&cr.init_vec_str);
            cr.original_file = env::args().nth(3).unwrap();
            cr.output_file = env::args().nth(4).unwrap();
        },
        5 => {
            cr.flag = 'd';
            cr.init_key_str = String::from(env::args().nth(2).unwrap());
            cr.init_vec_str = String::from(env::args().nth(3).unwrap());
            cr.init_key = key_to_bits(&cr.init_key_str);
            cr.init_vec = vec_to_bits(&cr.init_vec_str);
            cr.original_file = env::args().nth(4).unwrap();
            cr.output_file = env::args().nth(5).unwrap();
        }
        _ => std::process::exit(1)
    }

    println!("cr: {:?} {:010b} {:08b} {:?} {:?}", cr.flag,
                                                  cr.init_key,
                                                  cr.init_vec,
                                                  cr.original_file,
                                                  cr.output_file);

    /* * * * * * * * * *
     * KEY GENERATION *
     * * * * * * * * */

    println!("key generation:");
    //P10
    cr.init_key_str = permute_ten(cr.init_key_str);

    //Circular Left Shift (LS-1) on both bit halves of P10
    circular_left_shift(&cr.init_key_str);

    //P8 (picks and permutes 8 out of 10 bits) = K1

}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
#[macro_use]
extern crate lazy_static;

extern crate libc;
extern crate scmp;
extern crate tempdir;

use std::fs;
use std::env;
use std::ffi::OsStr;
use std::ffi::CString;
use std::io::Error;
use std::os::raw::c_void;
use std::os::unix::process::CommandExt;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use scmp::*;

unsafe fn allow_syscall(ctx : *mut c_void, nr : u32) {
    assert!(seccomp_rule_add_array(ctx, SCMP_ACT_ALLOW, nr as i32, 0, std::ptr::null()) == 0);
}

fn setup_seccomp() -> Result<(), Error> {
    unsafe {
        let ctx0 = seccomp_init(SCMP_ACT_TRAP);
        assert!(!ctx0.is_null());
        allow_syscall(ctx0, __NR_execve);
        allow_syscall(ctx0, __NR_brk);
        allow_syscall(ctx0, __NR_access);
        allow_syscall(ctx0, __NR_mmap);
        allow_syscall(ctx0, __NR_open);
        allow_syscall(ctx0, __NR_read);
        allow_syscall(ctx0, __NR_write);
        allow_syscall(ctx0, __NR_stat);
        allow_syscall(ctx0, __NR_fstat);
        allow_syscall(ctx0, __NR_close);
        allow_syscall(ctx0, __NR_mprotect);
        allow_syscall(ctx0, __NR_arch_prctl);
        allow_syscall(ctx0, __NR_munmap);
        allow_syscall(ctx0, __NR_set_tid_address);
        allow_syscall(ctx0, __NR_set_robust_list);
        allow_syscall(ctx0, __NR_rt_sigaction);
        allow_syscall(ctx0, __NR_rt_sigprocmask);
        allow_syscall(ctx0, __NR_getrlimit);
        allow_syscall(ctx0, __NR_statfs);
        allow_syscall(ctx0, __NR_fcntl);
        allow_syscall(ctx0, __NR_geteuid);
        allow_syscall(ctx0, __NR_umask);
        allow_syscall(ctx0, __NR_pipe);
        allow_syscall(ctx0, __NR_clone);
        allow_syscall(ctx0, __NR_wait4);
        allow_syscall(ctx0, __NR_exit_group);
        allow_syscall(ctx0, __NR_dup);
        allow_syscall(ctx0, __NR_ioctl);
        allow_syscall(ctx0, __NR_getpid);
        allow_syscall(ctx0, __NR_gettid);
        allow_syscall(ctx0, __NR_tgkill);
        allow_syscall(ctx0, __NR_rt_sigreturn);
        allow_syscall(ctx0, __NR_socket);
        allow_syscall(ctx0, __NR_connect);
        allow_syscall(ctx0, __NR_lseek);
        allow_syscall(ctx0, __NR_openat);
        allow_syscall(ctx0, __NR_unlinkat);
        allow_syscall(ctx0, __NR_utimensat);
        allow_syscall(ctx0, __NR_lstat);
        allow_syscall(ctx0, __NR_fchmod);
        allow_syscall(ctx0, __NR_unlink);
        allow_syscall(ctx0, __NR_utime);
        allow_syscall(ctx0, __NR_futex);
        allow_syscall(ctx0, __NR_chmod);
        assert!(seccomp_load(ctx0) == 0);
    }
    return Ok(());
}

const RENAME_NOREPLACE : u64 = 1;

fn path_to_cstring(path : &Path) -> CString {
    return CString::new(path.as_os_str().as_bytes()).unwrap();
}

fn rename_noreplace(path0 : &Path, path1 : &Path) -> Result<(), Error> {
    unsafe {
        if libc::syscall(__NR_renameat2 as i64, libc::AT_FDCWD, path_to_cstring(path0).as_ptr(), libc::AT_FDCWD, path_to_cstring(path1).as_ptr(), RENAME_NOREPLACE, 0) == 0 {
            return Ok(());
        } else {
            return Err(Error::last_os_error());
        }
    }
}

fn rename_or_suffix(path0 : &Path, path1 : &Path) -> Result<PathBuf, Error> {
    let rv = rename_noreplace(path0, path1);
    if let Err(err) = rv {
        if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
            return Err(err);
        }
        for suffix in 1.. {
            let mut builder = path1.as_os_str().to_os_string();
            builder.push(format!(".{}", suffix));
            let rv = rename_noreplace(path0, Path::new(&builder));
            if let Err(err) = rv {
                if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
                    return Err(err);
                }
                continue;
            }
            return Ok(Path::new(&builder).to_path_buf());
        }
        return Ok(PathBuf::new()); // XXX Unreachable
    } else {
        return Ok(path1.to_path_buf());
    }
}

struct ArchiveType {
    extensions: Vec<&'static str>,
    extract_cmd: Vec<&'static str>,
}

lazy_static! {
    static ref ARCHIVE_TYPES : Vec<ArchiveType> = vec![
        ArchiveType {
            extensions: vec![
                ".tgz",
                ".tar.gz",
                ".tar.Z",
                ".tbz2",
                ".tar.bz2",
                ".tlz",
                ".tar.lz",
                ".tar.lzma",
                ".tar.lzo",
                ".tar.xz",
            ],
            extract_cmd: vec!["tar", "-xf"],
        },
        ArchiveType {
            extensions: vec![
                ".zip",
            ],
            extract_cmd: vec!["unzip", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".rar",
            ],
            extract_cmd: vec!["unrar", "x", "--"],
        },
    ];
}

fn main() {
    let matches = clap_app!(myapp =>
        (@arg ARCHIVE: +required ... "Archives to extract")
    ).get_matches();

    let mut found = false;

    for arch in matches.values_of_os("ARCHIVE").unwrap() {
        let arch = Path::new(arch);
        println!("Extract {:?}", arch);
        for at in ARCHIVE_TYPES.iter() {
            for &ext in &at.extensions {
                if !arch.as_os_str().as_bytes().ends_with(ext.as_bytes()) {
                    continue;
                }
                found = true;

                let noext : &OsStr = OsStrExt::from_bytes(&arch.as_os_str().as_bytes()[0..arch.as_os_str().as_bytes().len()-ext.as_bytes().len()]);
                let stripped =
                    if let Some(noext) = Path::new(noext).file_name() {
                        noext
                    } else {
                        OsStr::new("extracted")
                    };
                let cmd = at.extract_cmd[0];
                let tmpdir = tempdir::TempDir::new_in(
                    env::current_dir().expect("Unable to get the current directory"),
                    stripped.to_string_lossy().to_mut().as_str()).expect("Unable to create temporary directory");
                let status = Command::new(cmd)
                    .args(&at.extract_cmd[1..])
                    .arg(&arch)
                    .current_dir(&tmpdir)
                    .before_exec(setup_seccomp)
                    .status()
                    .expect(format!("Failed to launch {}", cmd).as_str());
                assert!(status.success(), format!("{} wasn't successful", cmd));
                let extracted_path = tmpdir.into_path();
                let mut dir_list = fs::read_dir(&extracted_path).expect("Unable to read the extraction directory");
                if let Some(path) = dir_list.next() {
                    let path = path.expect("Unable to iterate the extraction directory");
                    if let Some(path1) = dir_list.next() {
                        path1.expect("Unable to iterate the extraction directory");
                        let newname = rename_or_suffix(&extracted_path, Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                    } else {
                        let newname = rename_or_suffix(&path.path(), Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                        fs::remove_dir(&extracted_path).expect("Failed to remove empty extraction directory");
                    }
                } else {
                    println!("No files were extracted");
                }
                break;
            }
        }
        if !found {
            println!("Can't handle {:?}", arch);
        }
    }
}

<commit_msg>7z support<commit_after>#[macro_use]
extern crate clap;
#[macro_use]
extern crate lazy_static;

extern crate libc;
extern crate scmp;
extern crate tempdir;

use std::fs;
use std::env;
use std::ffi::OsStr;
use std::ffi::CString;
use std::io::Error;
use std::os::raw::c_void;
use std::os::unix::process::CommandExt;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;
use scmp::*;

unsafe fn allow_syscall(ctx : *mut c_void, nr : u32) {
    assert!(seccomp_rule_add_array(ctx, SCMP_ACT_ALLOW, nr as i32, 0, std::ptr::null()) == 0);
}

fn setup_seccomp() -> Result<(), Error> {
    unsafe {
        let ctx0 = seccomp_init(SCMP_ACT_TRAP);
        assert!(!ctx0.is_null());
        allow_syscall(ctx0, __NR_execve);
        allow_syscall(ctx0, __NR_brk);
        allow_syscall(ctx0, __NR_access);
        allow_syscall(ctx0, __NR_mmap);
        allow_syscall(ctx0, __NR_open);
        allow_syscall(ctx0, __NR_read);
        allow_syscall(ctx0, __NR_write);
        allow_syscall(ctx0, __NR_stat);
        allow_syscall(ctx0, __NR_fstat);
        allow_syscall(ctx0, __NR_close);
        allow_syscall(ctx0, __NR_mprotect);
        allow_syscall(ctx0, __NR_arch_prctl);
        allow_syscall(ctx0, __NR_munmap);
        allow_syscall(ctx0, __NR_set_tid_address);
        allow_syscall(ctx0, __NR_set_robust_list);
        allow_syscall(ctx0, __NR_rt_sigaction);
        allow_syscall(ctx0, __NR_rt_sigprocmask);
        allow_syscall(ctx0, __NR_getrlimit);
        allow_syscall(ctx0, __NR_statfs);
        allow_syscall(ctx0, __NR_fcntl);
        allow_syscall(ctx0, __NR_geteuid);
        allow_syscall(ctx0, __NR_umask);
        allow_syscall(ctx0, __NR_pipe);
        allow_syscall(ctx0, __NR_clone);
        allow_syscall(ctx0, __NR_wait4);
        allow_syscall(ctx0, __NR_exit_group);
        allow_syscall(ctx0, __NR_dup);
        allow_syscall(ctx0, __NR_ioctl);
        allow_syscall(ctx0, __NR_getpid);
        allow_syscall(ctx0, __NR_gettid);
        allow_syscall(ctx0, __NR_tgkill);
        allow_syscall(ctx0, __NR_rt_sigreturn);
        allow_syscall(ctx0, __NR_socket);
        allow_syscall(ctx0, __NR_connect);
        allow_syscall(ctx0, __NR_lseek);
        allow_syscall(ctx0, __NR_openat);
        allow_syscall(ctx0, __NR_unlinkat);
        allow_syscall(ctx0, __NR_utimensat);
        allow_syscall(ctx0, __NR_lstat);
        allow_syscall(ctx0, __NR_fchmod);
        allow_syscall(ctx0, __NR_unlink);
        allow_syscall(ctx0, __NR_utime);
        allow_syscall(ctx0, __NR_futex);
        allow_syscall(ctx0, __NR_chmod);
        allow_syscall(ctx0, __NR_getuid);
        allow_syscall(ctx0, __NR_getgid);
        allow_syscall(ctx0, __NR_getppid);
        allow_syscall(ctx0, __NR_getcwd);
        allow_syscall(ctx0, __NR_getegid);
        allow_syscall(ctx0, __NR_getdents);
        allow_syscall(ctx0, __NR_readlink);
        assert!(seccomp_load(ctx0) == 0);
    }
    return Ok(());
}

const RENAME_NOREPLACE : u64 = 1;

fn path_to_cstring(path : &Path) -> CString {
    return CString::new(path.as_os_str().as_bytes()).unwrap();
}

fn rename_noreplace(path0 : &Path, path1 : &Path) -> Result<(), Error> {
    unsafe {
        if libc::syscall(__NR_renameat2 as i64, libc::AT_FDCWD, path_to_cstring(path0).as_ptr(), libc::AT_FDCWD, path_to_cstring(path1).as_ptr(), RENAME_NOREPLACE, 0) == 0 {
            return Ok(());
        } else {
            return Err(Error::last_os_error());
        }
    }
}

fn rename_or_suffix(path0 : &Path, path1 : &Path) -> Result<PathBuf, Error> {
    let rv = rename_noreplace(path0, path1);
    if let Err(err) = rv {
        if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
            return Err(err);
        }
        for suffix in 1.. {
            let mut builder = path1.as_os_str().to_os_string();
            builder.push(format!(".{}", suffix));
            let rv = rename_noreplace(path0, Path::new(&builder));
            if let Err(err) = rv {
                if err.raw_os_error().expect("Error fails to wrap errno") != libc::EEXIST {
                    return Err(err);
                }
                continue;
            }
            return Ok(Path::new(&builder).to_path_buf());
        }
        return Ok(PathBuf::new()); // XXX Unreachable
    } else {
        return Ok(path1.to_path_buf());
    }
}

struct ArchiveType {
    extensions: Vec<&'static str>,
    extract_cmd: Vec<&'static str>,
}

lazy_static! {
    static ref ARCHIVE_TYPES : Vec<ArchiveType> = vec![
        ArchiveType {
            extensions: vec![
                ".tgz",
                ".tar.gz",
                ".tar.Z",
                ".tbz2",
                ".tar.bz2",
                ".tlz",
                ".tar.lz",
                ".tar.lzma",
                ".tar.lzo",
                ".tar.xz",
            ],
            extract_cmd: vec!["tar", "-xf"],
        },
        ArchiveType {
            extensions: vec![
                ".zip",
            ],
            extract_cmd: vec!["unzip", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".rar",
            ],
            extract_cmd: vec!["unrar", "x", "--"],
        },
        ArchiveType {
            extensions: vec![
                ".7z",
            ],
            extract_cmd: vec!["7z", "x", "--"],
        },
    ];
}

fn main() {
    let matches = clap_app!(myapp =>
        (@arg ARCHIVE: +required ... "Archives to extract")
    ).get_matches();

    let mut found = false;

    for arch in matches.values_of_os("ARCHIVE").unwrap() {
        let arch = Path::new(arch);
        println!("Extract {:?}", arch);
        for at in ARCHIVE_TYPES.iter() {
            for &ext in &at.extensions {
                if !arch.as_os_str().as_bytes().ends_with(ext.as_bytes()) {
                    continue;
                }
                found = true;

                let noext : &OsStr = OsStrExt::from_bytes(&arch.as_os_str().as_bytes()[0..arch.as_os_str().as_bytes().len()-ext.as_bytes().len()]);
                let stripped =
                    if let Some(noext) = Path::new(noext).file_name() {
                        noext
                    } else {
                        OsStr::new("extracted")
                    };
                let cmd = at.extract_cmd[0];
                let tmpdir = tempdir::TempDir::new_in(
                    env::current_dir().expect("Unable to get the current directory"),
                    stripped.to_string_lossy().to_mut().as_str()).expect("Unable to create temporary directory");
                let status = Command::new(cmd)
                    .args(&at.extract_cmd[1..])
                    .arg(&arch)
                    .current_dir(&tmpdir)
                    .before_exec(setup_seccomp)
                    .status()
                    .expect(format!("Failed to launch {}", cmd).as_str());
                assert!(status.success(), format!("{} wasn't successful", cmd));
                let extracted_path = tmpdir.into_path();
                let mut dir_list = fs::read_dir(&extracted_path).expect("Unable to read the extraction directory");
                if let Some(path) = dir_list.next() {
                    let path = path.expect("Unable to iterate the extraction directory");
                    if let Some(path1) = dir_list.next() {
                        path1.expect("Unable to iterate the extraction directory");
                        let newname = rename_or_suffix(&extracted_path, Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                    } else {
                        let newname = rename_or_suffix(&path.path(), Path::new(stripped)).expect("Failed to rename");
                        println!("Extracted to {:?}", newname);
                        fs::remove_dir(&extracted_path).expect("Failed to remove empty extraction directory");
                    }
                } else {
                    println!("No files were extracted");
                }
                break;
            }
        }
        if !found {
            println!("Can't handle {:?}", arch);
        }
    }
}

<|endoftext|>