<commit_before>use core::{Algorithm, Predictor, Parameter, Trace, Shared};
use domains::Transition;
use fa::{Approximator, VFunction, Parameterised, Projector, Projection, SimpleLFA};
use geometry::{Space, Vector, Matrix};
use ndarray::Axis;
use ndarray_linalg::solve::Solve;
use std::marker::PhantomData;
use utils::{argmaxima, pinv};

pub struct LSTD<S, P: Projector<S>> {
    pub fa_theta: Shared<SimpleLFA<S, P>>,
    pub gamma: Parameter,

    a: Matrix<f64>,
    b: Vector<f64>,

    phantom: PhantomData<S>,
}

impl<S, P: Projector<S>> LSTD<S, P> {
    pub fn new<T: Into<Parameter>>(fa_theta: Shared<SimpleLFA<S, P>>, gamma: T) -> Self {
        let n_features = fa_theta.borrow().projector.dim();

        LSTD {
            fa_theta,
            gamma: gamma.into(),

            a: Matrix::zeros((n_features, n_features)),
            b: Vector::zeros((n_features,)),

            phantom: PhantomData,
        }
    }
}

impl<S, P: Projector<S>> LSTD<S, P> {
    #[inline(always)]
    fn compute_dense_fv(&self, s: &S) -> Vector<f64> {
        let dim = self.a.rows();

        self.fa_theta.borrow().projector.project(s).expanded(dim)
    }

    #[inline(always)]
    fn do_update(&mut self, phi_s: Vector<f64>, pd: Vector<f64>, reward: f64) {
        self.b.scaled_add(reward, &phi_s);
        self.a += &phi_s.insert_axis(Axis(1)).dot(&(pd.insert_axis(Axis(0))));
    }
}

impl<S, A, P: Projector<S>> Algorithm<S, A> for LSTD<S, P> {
    fn handle_sample(&mut self, t: &Transition<S, A>) {
        let (s, ns) = (t.from.state(), t.to.state());

        // (D x 1)
        let phi_s = self.compute_dense_fv(s);
        let phi_ns = self.compute_dense_fv(ns);

        // (1 x D)
        let pd = phi_s.clone() - self.gamma.value()*phi_ns;

        self.do_update(phi_s, pd, t.reward);
    }

    fn handle_terminal(&mut self, t: &Transition<S, A>) {
        {
            let s = t.from.state();
            let phi_s = self.compute_dense_fv(s);

            self.do_update(phi_s.clone(), phi_s, t.reward);

            // First try the clean approach:
            if let Ok(theta) = self.a.solve(&self.b) {
                self.fa_theta.borrow_mut().approximator.weights.assign(&theta);

            // Otherwise solve via SVD:
            } else if let Ok(ainv) = pinv(&self.a) {
                let theta = ainv.dot(&self.b);

                self.fa_theta.borrow_mut().approximator.weights.assign(&theta);
            }
        }

        self.gamma = self.gamma.step();
    }
}

impl<S, A, P: Projector<S>> Predictor<S, A> for LSTD<S, P> {
    fn predict_v(&mut self, s: &S) -> f64 {
        self.fa_theta.borrow().evaluate(s).unwrap()
    }
}

impl<S, P: Projector<S>> Parameterised for LSTD<S, P> {
    fn weights(&self) -> Matrix<f64> {
        self.fa_theta.borrow().weights()
    }
}
<commit_msg>feat(prediction): add LSTD::solve method for manual updates<commit_after>use core::{Algorithm, Predictor, Parameter, Trace, Shared};
use domains::Transition;
use fa::{Approximator, VFunction, Parameterised, Projector, Projection, SimpleLFA};
use geometry::{Space, Vector, Matrix};
use ndarray::Axis;
use ndarray_linalg::solve::Solve;
use std::marker::PhantomData;
use utils::{argmaxima, pinv};

pub struct LSTD<S, P: Projector<S>> {
    pub fa_theta: Shared<SimpleLFA<S, P>>,
    pub gamma: Parameter,

    a: Matrix<f64>,
    b: Vector<f64>,

    phantom: PhantomData<S>,
}

impl<S, P: Projector<S>> LSTD<S, P> {
    pub fn new<T: Into<Parameter>>(fa_theta: Shared<SimpleLFA<S, P>>, gamma: T) -> Self {
        let n_features = fa_theta.borrow().projector.dim();

        LSTD {
            fa_theta,
            gamma: gamma.into(),

            a: Matrix::zeros((n_features, n_features)),
            b: Vector::zeros((n_features,)),

            phantom: PhantomData,
        }
    }
}

impl<S, P: Projector<S>> LSTD<S, P> {
    #[inline(always)]
    fn compute_dense_fv(&self, s: &S) -> Vector<f64> {
        let dim = self.a.rows();

        self.fa_theta.borrow().projector.project(s).expanded(dim)
    }

    #[inline(always)]
    fn do_update(&mut self, phi_s: Vector<f64>, pd: Vector<f64>, reward: f64) {
        self.b.scaled_add(reward, &phi_s);
        self.a += &phi_s.insert_axis(Axis(1)).dot(&(pd.insert_axis(Axis(0))));
    }

    pub fn solve(&mut self) {
        // First try the clean approach:
        if let Ok(theta) = self.a.solve(&self.b) {
            self.fa_theta.borrow_mut().approximator.weights.assign(&theta);

        // Otherwise solve via SVD:
        } else if let Ok(ainv) = pinv(&self.a) {
            let theta = ainv.dot(&self.b);

            self.fa_theta.borrow_mut().approximator.weights.assign(&theta);
        }
    }
}

impl<S, A, P: Projector<S>> Algorithm<S, A> for LSTD<S, P> {
    fn handle_sample(&mut self, t: &Transition<S, A>) {
        let (s, ns) = (t.from.state(), t.to.state());

        // (D x 1)
        let phi_s = self.compute_dense_fv(s);
        let phi_ns = self.compute_dense_fv(ns);

        // (1 x D)
        let pd = phi_s.clone() - self.gamma.value()*phi_ns;

        self.do_update(phi_s, pd, t.reward);
    }

    fn handle_terminal(&mut self, t: &Transition<S, A>) {
        {
            let s = t.from.state();
            let phi_s = self.compute_dense_fv(s);

            self.do_update(phi_s.clone(), phi_s, t.reward);
            self.solve();
        }

        self.gamma = self.gamma.step();
    }
}

impl<S, A, P: Projector<S>> Predictor<S, A> for LSTD<S, P> {
    fn predict_v(&mut self, s: &S) -> f64 {
        self.fa_theta.borrow().evaluate(s).unwrap()
    }
}

impl<S, P: Projector<S>> Parameterised for LSTD<S, P> {
    fn weights(&self) -> Matrix<f64> {
        self.fa_theta.borrow().weights()
    }
}
<|endoftext|>


<commit_before>//! sans-server – Libreflip sans server daemon
//!
//! The design principle for this software is taken from Aouglas Adams:
//!
//! > Don't Panic!
//!
//! Also something about towels.
//!
//! The daemon should never just stop. Every possible error needs to be wrapped
//! into a Result<_> and communicate them to the user interface. Any actual panic
//! is a condition in the operation that prevents communication with the UI. These
//! should however still be logged.
#![feature(plugin, decl_macro)]
#![plugin(rocket_codegen)]

extern crate rocket;
extern crate rocket_contrib;
extern crate sans_core;
extern crate sans_types;

use std::io::stdin;
use sans_core::{Camera, CameraTrait, CameraType};

fn main() {
    let left = Camera::new("/dev/video0".into(), CameraType::Left).unwrap();
    let right = Camera::new("/dev/video1".into(), CameraType::Right).unwrap();

    println!("Press <enter> to take two pictures – reload your browser after");
    loop {
        let mut _s = String::new();
        stdin()
            .read_line(&mut _s)
            .expect("Failed to read user input!");

        left.capture_image().unwrap();
        right.capture_image().unwrap();
        println!("*click*");
    }
}
<commit_msg>Finding out which camera we're using<commit_after>//! sans-server – Libreflip sans server daemon
//!
//! The design principle for this software is taken from Aouglas Adams:
//!
//! > Don't Panic!
//!
//! Also something about towels.
//!
//! The daemon should never just stop. Every possible error needs to be wrapped
//! into a Result<_> and communicate them to the user interface. Any actual panic
//! is a condition in the operation that prevents communication with the UI. These
//! should however still be logged.
#![feature(plugin, decl_macro)]
#![plugin(rocket_codegen)]

extern crate rocket;
extern crate rocket_contrib;
extern crate sans_core;
extern crate sans_types;

use std::io::stdin;
use sans_core::{Camera, CameraTrait, CameraType};

fn main() {

    for n in &[0..=11] {
        let left = Camera::new(format!("/dev/video{}", n), CameraType::Left).unwrap();
        print!("Camera: {}", n);
        match left.capture_image() {
            Ok(n) => println!("OK!"),
            Err(_) => println!("FAILED"),
        };
    }

    // let right = Camera::new("/dev/video1".into(), CameraType::Right).unwrap();

    // println!("Press <enter> to take two pictures – reload your browser after");
    // loop {
    //     let mut _s = String::new();
    //     stdin()
    //         .read_line(&mut _s)
    //         .expect("Failed to read user input!");

    //     right.capture_image().unwrap();
    //     println!("*click*");
    }
}
<|endoftext|>


<commit_before>use std::path::PathBuf;

use anyhow::Result;
use async_std::task;
use portpicker::pick_unused_port;
use serde_cbor::de::from_slice;
use serde_cbor::ser::to_vec;
use tempdir::TempDir;

use pueue_lib::network::certificate::create_certificates;
use pueue_lib::network::message::*;
use pueue_lib::network::protocol::*;
use pueue_lib::settings::Shared;

#[async_std::test]
/// This tests whether we can create a listener and client, that communicate via TLS sockets.
async fn test_tls_socket() -> Result<()> {
    // Create a temporary directory used for testing.
    let temp_dir = TempDir::new("pueue_lib")?;
    let temp_dir_path = temp_dir.path().to_path_buf();

    let shared_settings = Shared {
        pueue_directory: temp_dir_path.clone(),
        use_unix_socket: false,
        unix_socket_path: PathBuf::new(),
        host: "localhost".to_string(),
        port: pick_unused_port()
            .expect("There should be a free port")
            .to_string(),
        daemon_cert: temp_dir_path.clone().join("certs").join("daemon.cert"),
        daemon_key: temp_dir_path.clone().join("certs").join("daemon.key"),
        shared_secret_path: temp_dir.path().to_path_buf().join("secret"),
    };

    // Create new stub tls certificates/keys in our temp directory
    create_certificates(&shared_settings)?;

    let listener = get_listener(&shared_settings).await?;
    let message = create_success_message("This is a test");
    let original_bytes = to_vec(&message).expect("Failed to serialize message.");

    // Spawn a sub thread that:
    // 1. Accepts a new connection
    // 2. Reads a message
    // 3. Sends the same message back
    task::spawn(async move {
        let mut stream = listener.accept().await.unwrap();
        let message_bytes = receive_bytes(&mut stream).await.unwrap();

        let message: Message = from_slice(&message_bytes).unwrap();

        send_message(message, &mut stream).await.unwrap();
    });

    let mut client = get_client_stream(&shared_settings).await?;

    // Create a client that sends a message and instantly receives it
    send_message(message, &mut client).await?;
    let response_bytes = receive_bytes(&mut client).await?;
    let _message: Message = from_slice(&response_bytes)?;

    assert_eq!(response_bytes, original_bytes);

    Ok(())
}
<commit_msg>Fix tls socket tests for windows<commit_after>use std::path::PathBuf;

use anyhow::Result;
use async_std::task;
use portpicker::pick_unused_port;
use serde_cbor::de::from_slice;
use serde_cbor::ser::to_vec;
use tempdir::TempDir;

use pueue_lib::network::certificate::create_certificates;
use pueue_lib::network::message::*;
use pueue_lib::network::protocol::*;
use pueue_lib::settings::Shared;

#[async_std::test]
/// This tests whether we can create a listener and client, that communicate via TLS sockets.
async fn test_tls_socket() -> Result<()> {
    // Create a temporary directory used for testing.
    let temp_dir = TempDir::new("pueue_lib")?;
    let temp_dir_path = temp_dir.path().to_path_buf();

    let shared_settings = Shared {
        pueue_directory: temp_dir_path.clone(),
        #[cfg(not(target_os = "windows"))]
        use_unix_socket: false,
        #[cfg(not(target_os = "windows"))]
        unix_socket_path: PathBuf::new(),
        host: "localhost".to_string(),
        port: pick_unused_port()
            .expect("There should be a free port")
            .to_string(),
        daemon_cert: temp_dir_path.clone().join("certs").join("daemon.cert"),
        daemon_key: temp_dir_path.clone().join("certs").join("daemon.key"),
        shared_secret_path: temp_dir.path().to_path_buf().join("secret"),
    };

    // Create new stub tls certificates/keys in our temp directory
    create_certificates(&shared_settings)?;

    let listener = get_listener(&shared_settings).await?;
    let message = create_success_message("This is a test");
    let original_bytes = to_vec(&message).expect("Failed to serialize message.");

    // Spawn a sub thread that:
    // 1. Accepts a new connection
    // 2. Reads a message
    // 3. Sends the same message back
    task::spawn(async move {
        let mut stream = listener.accept().await.unwrap();
        let message_bytes = receive_bytes(&mut stream).await.unwrap();

        let message: Message = from_slice(&message_bytes).unwrap();

        send_message(message, &mut stream).await.unwrap();
    });

    let mut client = get_client_stream(&shared_settings).await?;

    // Create a client that sends a message and instantly receives it
    send_message(message, &mut client).await?;
    let response_bytes = receive_bytes(&mut client).await?;
    let _message: Message = from_slice(&response_bytes)?;

    assert_eq!(response_bytes, original_bytes);

    Ok(())
}
<|endoftext|>


<commit_before>use std::{io::Cursor, path::Path};

use rocksdb::{
    merge_operator::MergeFn, BlockBasedIndexType, BlockBasedOptions, ColumnFamily,
    ColumnFamilyDescriptor, DBWithThreadMode, IteratorMode, MergeOperands, Options, ReadOptions,
    SliceTransform, WriteBatch, DB,
};

use crate::model::{
    GameId, GameInfo, Key, KeyPrefix, LichessEntry, MasterEntry, MasterGame, Month, PersonalEntry,
    PersonalStatus, UserId, Year,
};

#[derive(Debug)]
pub struct Database {
    inner: DB,
}

fn column_family(
    name: &str,
    merge: Option<&str>,
    merge_fn: impl MergeFn + Clone,
    prefix: Option<usize>,
    block_size: usize,
    bloom_filter: i32,
) -> ColumnFamilyDescriptor {
    let mut opts = Options::default();
    if let Some(merge) = merge {
        opts.set_merge_operator_associative(merge, merge_fn);
    }
    opts.set_prefix_extractor(match prefix {
        Some(prefix) => SliceTransform::create_fixed_prefix(prefix),
        None => SliceTransform::create_noop(),
    });
    let mut block_opts = BlockBasedOptions::default();
    block_opts.set_index_type(BlockBasedIndexType::HashSearch);
    block_opts.set_block_size(block_size);
    if bloom_filter > 0 {
        block_opts.set_bloom_filter(bloom_filter, true);
    }
    opts.set_block_based_table_factory(&block_opts);
    ColumnFamilyDescriptor::new(name, opts)
}

impl Database {
    pub fn open<P: AsRef<Path>>(path: P) -> Result<Database, rocksdb::Error> {
        let mut db_opts = Options::default();
        db_opts.create_if_missing(true);
        db_opts.create_missing_column_families(true);

        let inner = DBWithThreadMode::open_cf_descriptors(
            &db_opts,
            path,
            vec![
                column_family(
                    "lichess",
                    Some("lichess merge"),
                    lichess_merge,
                    Some(KeyPrefix::SIZE),
                    4 * 1024,
                    5,
                ),
                column_family(
                    "personal",
                    Some("personal merge"),
                    personal_merge,
                    Some(KeyPrefix::SIZE),
                    4 * 1024,
                    6,
                ),
                column_family("game", Some("game merge"), game_merge, None, 1024, 0),
                column_family("player", None, void_merge, None, 1024, 0),
                column_family(
                    "master",
                    Some("master merge"),
                    master_merge,
                    Some(KeyPrefix::SIZE),
                    4 * 1024,
                    6,
                ),
                column_family("master_game", None, void_merge, None, 4 * 1024, 0),
            ],
        )?;

        Ok(Database { inner })
    }

    pub fn queryable(&self) -> QueryableDatabase<'_> {
        QueryableDatabase {
            db: &self.inner,
            cf_lichess: self.inner.cf_handle("lichess").expect("cf lichess"),
            cf_personal: self.inner.cf_handle("personal").expect("cf personal"),
            cf_game: self.inner.cf_handle("game").expect("cf game"),
            cf_player: self.inner.cf_handle("player").expect("cf player"),
            cf_master: self.inner.cf_handle("master").expect("cf master"),
            cf_master_game: self.inner.cf_handle("master_game").expect("cf master_game"),
        }
    }
}

pub struct QueryableDatabase<'a> {
    db: &'a DB,
    cf_lichess: &'a ColumnFamily,
    cf_personal: &'a ColumnFamily,
    cf_game: &'a ColumnFamily,
    cf_player: &'a ColumnFamily,
    cf_master: &'a ColumnFamily,
    cf_master_game: &'a ColumnFamily,
}

impl QueryableDatabase<'_> {
    pub fn db_property(&self, name: &str) -> Result<Option<String>, rocksdb::Error> {
        self.db.property_value(name)
    }

    pub fn game_property(&self, name: &str) -> Result<Option<String>, rocksdb::Error> {
        self.db.property_value_cf(self.cf_game, name)
    }

    pub fn personal_property(&self, name: &str) -> Result<Option<String>, rocksdb::Error> {
        self.db.property_value_cf(self.cf_personal, name)
    }

    pub fn get_game_info(&self, id: GameId) -> Result<Option<GameInfo>, rocksdb::Error> {
        Ok(self.db.get_cf(self.cf_game, id.to_bytes())?.map(|buf| {
            let mut cursor = Cursor::new(buf);
            GameInfo::read(&mut cursor).expect("deserialize game info")
        }))
    }

    pub fn get_personal(
        &self,
        key: &KeyPrefix,
        since: Month,
        until: Month,
    ) -> Result<PersonalEntry, rocksdb::Error> {
        let mut opt = ReadOptions::default();
        opt.set_prefix_same_as_start(true);
        opt.set_iterate_lower_bound(key.with_month(since).into_bytes());
        opt.set_iterate_upper_bound(key.with_month(until.add_months_saturating(1)).into_bytes());

        let iterator = self
            .db
            .iterator_cf_opt(self.cf_personal, opt, IteratorMode::Start);

        let mut entry = PersonalEntry::default();
        for (_key, value) in iterator {
            let mut cursor = Cursor::new(value);
            entry
                .extend_from_reader(&mut cursor)
                .expect("deserialize personal entry");
        }

        Ok(entry)
    }

    pub fn get_player_status(&self, id: &UserId) -> Result<Option<PersonalStatus>, rocksdb::Error> {
        Ok(self.db.get_cf(self.cf_player, id.as_str())?.map(|buf| {
            let mut cursor = Cursor::new(buf);
            PersonalStatus::read(&mut cursor).expect("deserialize status")
        }))
    }

    pub fn put_player_status(
        &self,
        id: &UserId,
        status: &PersonalStatus,
    ) -> Result<(), rocksdb::Error> {
        let mut cursor = Cursor::new(Vec::with_capacity(PersonalStatus::SIZE_HINT));
        status.write(&mut cursor).expect("serialize status");
        self.db
            .put_cf(self.cf_player, id.as_str(), cursor.into_inner())
    }

    pub fn has_master_game(&self, id: GameId) -> Result<bool, rocksdb::Error> {
        self.db
            .get_cf(self.cf_master_game, id.to_bytes())
            .map(|maybe_entry| maybe_entry.is_some())
    }

    pub fn get_master_game(&self, id: GameId) -> Result<Option<MasterGame>, rocksdb::Error> {
        Ok(self
            .db
            .get_cf(self.cf_master_game, id.to_bytes())?
            .map(|buf| serde_json::from_slice(&buf).expect("deserialize master game")))
    }

    pub fn has_master(&self, key: Key) -> Result<bool, rocksdb::Error> {
        self.db
            .get_cf(self.cf_master, key.into_bytes())
            .map(|maybe_entry| maybe_entry.is_some())
    }

    pub fn get_master(
        &self,
        key: KeyPrefix,
        since: Year,
        until: Year,
    ) -> Result<MasterEntry, rocksdb::Error> {
        let mut opt = ReadOptions::default();
        opt.set_prefix_same_as_start(true);
        opt.set_iterate_lower_bound(key.with_year(since).into_bytes());
        opt.set_iterate_upper_bound(key.with_year(until.add_years_saturating(1)).into_bytes());

        let iterator = self
            .db
            .iterator_cf_opt(self.cf_master, opt, IteratorMode::Start);

        let mut entry = MasterEntry::default();
        for (_key, value) in iterator {
            let mut cursor = Cursor::new(value);
            entry
                .extend_from_reader(&mut cursor)
                .expect("deserialize master entry");
        }

        Ok(entry)
    }

    pub fn batch(&self) -> Batch<'_> {
        Batch {
            queryable: self,
            batch: WriteBatch::default(),
        }
    }
}

pub struct Batch<'a> {
    queryable: &'a QueryableDatabase<'a>,
    batch: WriteBatch,
}

impl Batch<'_> {
    pub fn merge_lichess(&mut self, key: Key, entry: LichessEntry) {
        let mut cursor = Cursor::new(Vec::with_capacity(LichessEntry::SIZE_HINT));
        entry.write(&mut cursor).expect("serialize lichess entry");
        self.batch.merge_cf(
            self.queryable.cf_lichess,
            key.into_bytes(),
            cursor.into_inner(),
        );
    }

    pub fn merge_personal(&mut self, key: Key, entry: PersonalEntry) {
        let mut cursor = Cursor::new(Vec::with_capacity(PersonalEntry::SIZE_HINT));
        entry.write(&mut cursor).expect("serialize personal entry");
        self.batch.merge_cf(
            self.queryable.cf_personal,
            key.into_bytes(),
            cursor.into_inner(),
        );
    }

    pub fn merge_game_info(&mut self, id: GameId, info: GameInfo) {
        let mut cursor = Cursor::new(Vec::with_capacity(GameInfo::SIZE_HINT));
        info.write(&mut cursor).expect("serialize game info");
        self.batch
            .merge_cf(self.queryable.cf_game, id.to_bytes(), cursor.into_inner());
    }

    pub fn merge_master(&mut self, key: Key, entry: MasterEntry) {
        let mut cursor = Cursor::new(Vec::with_capacity(MasterEntry::SIZE_HINT));
        entry.write(&mut cursor).expect("serialize master entry");
        self.batch.merge_cf(
            self.queryable.cf_master,
            key.into_bytes(),
            cursor.into_inner(),
        );
    }

    pub fn put_master_game(&mut self, id: GameId, game: &MasterGame) {
        self.batch.put_cf(
            self.queryable.cf_master_game,
            id.to_bytes(),
            serde_json::to_vec(game).expect("serialize master game"),
        );
    }

    pub fn write(self) -> Result<(), rocksdb::Error> {
        self.queryable.db.write(self.batch)
    }
}

fn lichess_merge(
    _key: &[u8],
    existing: Option<&[u8]>,
    operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    let mut entry = LichessEntry::default();
    let mut size_hint = 0;
    for op in existing.into_iter().chain(operands.into_iter()) {
        let mut cursor = Cursor::new(op);
        entry
            .extend_from_reader(&mut cursor)
            .expect("deserialize for lichess merge");
        size_hint += op.len();
    }
    let mut cursor = Cursor::new(Vec::with_capacity(size_hint));
    entry.write(&mut cursor).expect("write lichess entry");
    Some(cursor.into_inner())
}

fn game_merge(
    _key: &[u8],
    existing: Option<&[u8]>,
    operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    // Take latest game info, but merge index status.
    let mut info: Option<GameInfo> = None;
    let mut size_hint = 0;
    for op in existing.into_iter().chain(operands.into_iter()) {
        let mut cursor = Cursor::new(op);
        let mut new_info = GameInfo::read(&mut cursor).expect("read for game merge");
        if let Some(old_info) = info {
            new_info.indexed.white |= old_info.indexed.white;
            new_info.indexed.black |= old_info.indexed.black;
        }
        info = Some(new_info);
        size_hint = op.len();
    }
    info.map(|info| {
        let mut cursor = Cursor::new(Vec::with_capacity(size_hint));
        info.write(&mut cursor).expect("write game");
        cursor.into_inner()
    })
}

fn personal_merge(
    _key: &[u8],
    existing: Option<&[u8]>,
    operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    let mut entry = PersonalEntry::default();
    let mut size_hint = 0;
    for op in existing.into_iter().chain(operands.into_iter()) {
        let mut cursor = Cursor::new(op);
        entry
            .extend_from_reader(&mut cursor)
            .expect("deserialize for personal merge");
        size_hint += op.len();
    }
    let mut cursor = Cursor::new(Vec::with_capacity(size_hint));
    entry.write(&mut cursor).expect("write personal entry");
    Some(cursor.into_inner())
}

fn master_merge(
    _key: &[u8],
    existing: Option<&[u8]>,
    operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    let mut entry = MasterEntry::default();
    let mut size_hint = 0;
    for op in existing.into_iter().chain(operands.into_iter()) {
        let mut cursor = Cursor::new(op);
        entry
            .extend_from_reader(&mut cursor)
            .expect("deserialize for master merge");
        size_hint += op.len();
    }
    let mut cursor = Cursor::new(Vec::with_capacity(size_hint));
    entry.write(&mut cursor).expect("write master entry");
    Some(cursor.into_inner())
}

fn void_merge(
    _key: &[u8],
    _existing: Option<&[u8]>,
    _operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    unreachable!("void merge operator only used to satisfy type checker")
}
<commit_msg>add db.get_lichess<commit_after>use std::{io::Cursor, path::Path};

use rocksdb::{
    merge_operator::MergeFn, BlockBasedIndexType, BlockBasedOptions, ColumnFamily,
    ColumnFamilyDescriptor, DBWithThreadMode, IteratorMode, MergeOperands, Options, ReadOptions,
    SliceTransform, WriteBatch, DB,
};

use crate::model::{
    GameId, GameInfo, Key, KeyPrefix, LichessEntry, MasterEntry, MasterGame, Month, PersonalEntry,
    PersonalStatus, UserId, Year,
};

#[derive(Debug)]
pub struct Database {
    inner: DB,
}

fn column_family(
    name: &str,
    merge: Option<&str>,
    merge_fn: impl MergeFn + Clone,
    prefix: Option<usize>,
    block_size: usize,
    bloom_filter: i32,
) -> ColumnFamilyDescriptor {
    let mut opts = Options::default();
    if let Some(merge) = merge {
        opts.set_merge_operator_associative(merge, merge_fn);
    }
    opts.set_prefix_extractor(match prefix {
        Some(prefix) => SliceTransform::create_fixed_prefix(prefix),
        None => SliceTransform::create_noop(),
    });
    let mut block_opts = BlockBasedOptions::default();
    block_opts.set_index_type(BlockBasedIndexType::HashSearch);
    block_opts.set_block_size(block_size);
    if bloom_filter > 0 {
        block_opts.set_bloom_filter(bloom_filter, true);
    }
    opts.set_block_based_table_factory(&block_opts);
    ColumnFamilyDescriptor::new(name, opts)
}

impl Database {
    pub fn open<P: AsRef<Path>>(path: P) -> Result<Database, rocksdb::Error> {
        let mut db_opts = Options::default();
        db_opts.create_if_missing(true);
        db_opts.create_missing_column_families(true);

        let inner = DBWithThreadMode::open_cf_descriptors(
            &db_opts,
            path,
            vec![
                column_family(
                    "lichess",
                    Some("lichess merge"),
                    lichess_merge,
                    Some(KeyPrefix::SIZE),
                    4 * 1024,
                    5,
                ),
                column_family(
                    "personal",
                    Some("personal merge"),
                    personal_merge,
                    Some(KeyPrefix::SIZE),
                    4 * 1024,
                    6,
                ),
                column_family("game", Some("game merge"), game_merge, None, 1024, 0),
                column_family("player", None, void_merge, None, 1024, 0),
                column_family(
                    "master",
                    Some("master merge"),
                    master_merge,
                    Some(KeyPrefix::SIZE),
                    4 * 1024,
                    6,
                ),
                column_family("master_game", None, void_merge, None, 4 * 1024, 0),
            ],
        )?;

        Ok(Database { inner })
    }

    pub fn queryable(&self) -> QueryableDatabase<'_> {
        QueryableDatabase {
            db: &self.inner,
            cf_lichess: self.inner.cf_handle("lichess").expect("cf lichess"),
            cf_personal: self.inner.cf_handle("personal").expect("cf personal"),
            cf_game: self.inner.cf_handle("game").expect("cf game"),
            cf_player: self.inner.cf_handle("player").expect("cf player"),
            cf_master: self.inner.cf_handle("master").expect("cf master"),
            cf_master_game: self.inner.cf_handle("master_game").expect("cf master_game"),
        }
    }
}

pub struct QueryableDatabase<'a> {
    db: &'a DB,
    cf_lichess: &'a ColumnFamily,
    cf_personal: &'a ColumnFamily,
    cf_game: &'a ColumnFamily,
    cf_player: &'a ColumnFamily,
    cf_master: &'a ColumnFamily,
    cf_master_game: &'a ColumnFamily,
}

impl QueryableDatabase<'_> {
    pub fn db_property(&self, name: &str) -> Result<Option<String>, rocksdb::Error> {
        self.db.property_value(name)
    }

    pub fn game_property(&self, name: &str) -> Result<Option<String>, rocksdb::Error> {
        self.db.property_value_cf(self.cf_game, name)
    }

    pub fn personal_property(&self, name: &str) -> Result<Option<String>, rocksdb::Error> {
        self.db.property_value_cf(self.cf_personal, name)
    }

    pub fn get_game_info(&self, id: GameId) -> Result<Option<GameInfo>, rocksdb::Error> {
        Ok(self.db.get_cf(self.cf_game, id.to_bytes())?.map(|buf| {
            let mut cursor = Cursor::new(buf);
            GameInfo::read(&mut cursor).expect("deserialize game info")
        }))
    }

    pub fn get_lichess(
        &self,
        key: &KeyPrefix,
        since: Month,
        until: Month,
    ) -> Result<LichessEntry, rocksdb::Error> {
        let mut opt = ReadOptions::default();
        opt.set_prefix_same_as_start(true);
        opt.set_iterate_lower_bound(key.with_month(since).into_bytes());
        opt.set_iterate_upper_bound(key.with_month(until.add_months_saturating(1)).into_bytes());

        let iterator = self
            .db
            .iterator_cf_opt(self.cf_lichess, opt, IteratorMode::Start);

        let mut entry = LichessEntry::default();
        for (_key, value) in iterator {
            let mut cursor = Cursor::new(value);
            entry
                .extend_from_reader(&mut cursor)
                .expect("deserialize lichess entry");
        }

        Ok(entry)
    }

    pub fn get_personal(
        &self,
        key: &KeyPrefix,
        since: Month,
        until: Month,
    ) -> Result<PersonalEntry, rocksdb::Error> {
        let mut opt = ReadOptions::default();
        opt.set_prefix_same_as_start(true);
        opt.set_iterate_lower_bound(key.with_month(since).into_bytes());
        opt.set_iterate_upper_bound(key.with_month(until.add_months_saturating(1)).into_bytes());

        let iterator = self
            .db
            .iterator_cf_opt(self.cf_personal, opt, IteratorMode::Start);

        let mut entry = PersonalEntry::default();
        for (_key, value) in iterator {
            let mut cursor = Cursor::new(value);
            entry
                .extend_from_reader(&mut cursor)
                .expect("deserialize personal entry");
        }

        Ok(entry)
    }

    pub fn get_player_status(&self, id: &UserId) -> Result<Option<PersonalStatus>, rocksdb::Error> {
        Ok(self.db.get_cf(self.cf_player, id.as_str())?.map(|buf| {
            let mut cursor = Cursor::new(buf);
            PersonalStatus::read(&mut cursor).expect("deserialize status")
        }))
    }

    pub fn put_player_status(
        &self,
        id: &UserId,
        status: &PersonalStatus,
    ) -> Result<(), rocksdb::Error> {
        let mut cursor = Cursor::new(Vec::with_capacity(PersonalStatus::SIZE_HINT));
        status.write(&mut cursor).expect("serialize status");
        self.db
            .put_cf(self.cf_player, id.as_str(), cursor.into_inner())
    }

    pub fn has_master_game(&self, id: GameId) -> Result<bool, rocksdb::Error> {
        self.db
            .get_cf(self.cf_master_game, id.to_bytes())
            .map(|maybe_entry| maybe_entry.is_some())
    }

    pub fn get_master_game(&self, id: GameId) -> Result<Option<MasterGame>, rocksdb::Error> {
        Ok(self
            .db
            .get_cf(self.cf_master_game, id.to_bytes())?
            .map(|buf| serde_json::from_slice(&buf).expect("deserialize master game")))
    }

    pub fn has_master(&self, key: Key) -> Result<bool, rocksdb::Error> {
        self.db
            .get_cf(self.cf_master, key.into_bytes())
            .map(|maybe_entry| maybe_entry.is_some())
    }

    pub fn get_master(
        &self,
        key: KeyPrefix,
        since: Year,
        until: Year,
    ) -> Result<MasterEntry, rocksdb::Error> {
        let mut opt = ReadOptions::default();
        opt.set_prefix_same_as_start(true);
        opt.set_iterate_lower_bound(key.with_year(since).into_bytes());
        opt.set_iterate_upper_bound(key.with_year(until.add_years_saturating(1)).into_bytes());

        let iterator = self
            .db
            .iterator_cf_opt(self.cf_master, opt, IteratorMode::Start);

        let mut entry = MasterEntry::default();
        for (_key, value) in iterator {
            let mut cursor = Cursor::new(value);
            entry
                .extend_from_reader(&mut cursor)
                .expect("deserialize master entry");
        }

        Ok(entry)
    }

    pub fn batch(&self) -> Batch<'_> {
        Batch {
            queryable: self,
            batch: WriteBatch::default(),
        }
    }
}

pub struct Batch<'a> {
    queryable: &'a QueryableDatabase<'a>,
    batch: WriteBatch,
}

impl Batch<'_> {
    pub fn merge_lichess(&mut self, key: Key, entry: LichessEntry) {
        let mut cursor = Cursor::new(Vec::with_capacity(LichessEntry::SIZE_HINT));
        entry.write(&mut cursor).expect("serialize lichess entry");
        self.batch.merge_cf(
            self.queryable.cf_lichess,
            key.into_bytes(),
            cursor.into_inner(),
        );
    }

    pub fn merge_personal(&mut self, key: Key, entry: PersonalEntry) {
        let mut cursor = Cursor::new(Vec::with_capacity(PersonalEntry::SIZE_HINT));
        entry.write(&mut cursor).expect("serialize personal entry");
        self.batch.merge_cf(
            self.queryable.cf_personal,
            key.into_bytes(),
            cursor.into_inner(),
        );
    }

    pub fn merge_game_info(&mut self, id: GameId, info: GameInfo) {
        let mut cursor = Cursor::new(Vec::with_capacity(GameInfo::SIZE_HINT));
        info.write(&mut cursor).expect("serialize game info");
        self.batch
            .merge_cf(self.queryable.cf_game, id.to_bytes(), cursor.into_inner());
    }

    pub fn merge_master(&mut self, key: Key, entry: MasterEntry) {
        let mut cursor = Cursor::new(Vec::with_capacity(MasterEntry::SIZE_HINT));
        entry.write(&mut cursor).expect("serialize master entry");
        self.batch.merge_cf(
            self.queryable.cf_master,
            key.into_bytes(),
            cursor.into_inner(),
        );
    }

    pub fn put_master_game(&mut self, id: GameId, game: &MasterGame) {
        self.batch.put_cf(
            self.queryable.cf_master_game,
            id.to_bytes(),
            serde_json::to_vec(game).expect("serialize master game"),
        );
    }

    pub fn write(self) -> Result<(), rocksdb::Error> {
        self.queryable.db.write(self.batch)
    }
}

fn lichess_merge(
    _key: &[u8],
    existing: Option<&[u8]>,
    operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    let mut entry = LichessEntry::default();
    let mut size_hint = 0;
    for op in existing.into_iter().chain(operands.into_iter()) {
        let mut cursor = Cursor::new(op);
        entry
            .extend_from_reader(&mut cursor)
            .expect("deserialize for lichess merge");
        size_hint += op.len();
    }
    let mut cursor = Cursor::new(Vec::with_capacity(size_hint));
    entry.write(&mut cursor).expect("write lichess entry");
    Some(cursor.into_inner())
}

fn game_merge(
    _key: &[u8],
    existing: Option<&[u8]>,
    operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    // Take latest game info, but merge index status.
    let mut info: Option<GameInfo> = None;
    let mut size_hint = 0;
    for op in existing.into_iter().chain(operands.into_iter()) {
        let mut cursor = Cursor::new(op);
        let mut new_info = GameInfo::read(&mut cursor).expect("read for game merge");
        if let Some(old_info) = info {
            new_info.indexed.white |= old_info.indexed.white;
            new_info.indexed.black |= old_info.indexed.black;
        }
        info = Some(new_info);
        size_hint = op.len();
    }
    info.map(|info| {
        let mut cursor = Cursor::new(Vec::with_capacity(size_hint));
        info.write(&mut cursor).expect("write game");
        cursor.into_inner()
    })
}

fn personal_merge(
    _key: &[u8],
    existing: Option<&[u8]>,
    operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    let mut entry = PersonalEntry::default();
    let mut size_hint = 0;
    for op in existing.into_iter().chain(operands.into_iter()) {
        let mut cursor = Cursor::new(op);
        entry
            .extend_from_reader(&mut cursor)
            .expect("deserialize for personal merge");
        size_hint += op.len();
    }
    let mut cursor = Cursor::new(Vec::with_capacity(size_hint));
    entry.write(&mut cursor).expect("write personal entry");
    Some(cursor.into_inner())
}

fn master_merge(
    _key: &[u8],
    existing: Option<&[u8]>,
    operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    let mut entry = MasterEntry::default();
    let mut size_hint = 0;
    for op in existing.into_iter().chain(operands.into_iter()) {
        let mut cursor = Cursor::new(op);
        entry
            .extend_from_reader(&mut cursor)
            .expect("deserialize for master merge");
        size_hint += op.len();
    }
    let mut cursor = Cursor::new(Vec::with_capacity(size_hint));
    entry.write(&mut cursor).expect("write master entry");
    Some(cursor.into_inner())
}

fn void_merge(
    _key: &[u8],
    _existing: Option<&[u8]>,
    _operands: &mut MergeOperands,
) -> Option<Vec<u8>> {
    unreachable!("void merge operator only used to satisfy type checker")
}
<|endoftext|>


<commit_before>extern crate tinyrsh;

use std::collections::HashMap;
use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd};
use tinyrsh::select as select;
use tinyrsh::select::FdSet;
use std::process::{Command, Stdio};

fn greet_client(mut stream: &TcpStream) {
    let remote = stream.peer_addr().unwrap();
    println!("connected: {}", remote);

    match stream.write(b"hello") {
        Err(e) => println!("{}", e),
        Ok(n) => println!("wrote {} bytes", n),
    };
}

fn read_client(mut stream: &TcpStream) -> bool {
    let remote = stream.peer_addr().unwrap();

    let mut buffer = [0; 10];
    let cont = match stream.read(&mut buffer) {
        Err(e) => {
                println!("{}", e);
                false
            },
        Ok(n) => {
                println!("{}: {:?} ({} bytes)", remote, buffer, n);
                n != 0
            },
    };
    cont
}

fn debug_fdset(fdset: &FdSet) {
    let maxfds = select::FD_SETSIZE;
    for i in 0 .. maxfds {
        if fdset.contains(i) {
            println!("contains {}", i);
        }
    }
}

fn read_child<T: Read>(readt: &mut T) {
    let mut buffer = [0; 10];
    let n = readt.read(&mut buffer).expect("read_child");
    println!("{:?} ({} bytes)", buffer, n);
}

fn main() {
    println!("Hello, world!");

    let child = Command::new("../py-ptysh/ptysh.py")
            //.arg("-a")
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
            .expect("failed to execute process");
    println!("spawned child with pid {}", child.id());

    let child_stdin  = child.stdin.unwrap();
    let mut child_stdout = child.stdout.unwrap();
    let mut child_stderr = child.stderr.unwrap();

        // test read output!!! not linebuffered??
        let mut buffer = [0; 10];
        let n = child_stdout.read(&mut buffer).expect("child stdout read");
        println!("childstdout: {:?} ({} bytes)", buffer, n);

    let listener = TcpListener::bind("127.0.0.1:6699").unwrap();

    let mut all_fdset = FdSet::new();
    let srv_fd = listener.as_raw_fd(); // not consumed

    //high fd for select() call
    let mut high_fd = 0;

    for fd in [srv_fd, child_stdout.as_raw_fd(), child_stderr.as_raw_fd()].iter() {
        println!("inserting fd {}", fd);
        all_fdset.insert(*fd);
        high_fd = std::cmp::max(high_fd, *fd);
    };

    let mut clients = HashMap::new(); //could also use FromRawFd

    fn add_client(all_fdset: &mut FdSet, clients: &mut HashMap<RawFd, TcpStream>, stream: TcpStream) -> RawFd {
        let stream_fd: RawFd = stream.as_raw_fd(); //not consume
        println!("inserted fd {}", stream_fd);
        clients.insert(stream_fd, stream);
        all_fdset.insert(stream_fd);
        stream_fd
    };
    fn del_client(all_fdset: &mut FdSet, clients: &mut HashMap<RawFd, TcpStream>, stream_fd: RawFd) {
        assert!(clients.contains_key(&stream_fd));
        //let stream = clients.get(&stream_fd);
        println!("removing fd {}", stream_fd);
        assert!(all_fdset.contains(stream_fd));
        all_fdset.remove(stream_fd);
        assert!(clients.contains_key(&stream_fd));
        clients.remove(&stream_fd);
    };

    for stream in listener.incoming() {
        match stream {
            Ok(mut stream) => {
                greet_client(&mut stream);
                high_fd = std::cmp::max(high_fd, add_client(&mut all_fdset, &mut clients, stream));
                println!("new high fd: {}", high_fd);
            }
            Err(e) => { /* connection failed */ }
        }
        println!("selecting");
        loop {
            let mut fdset = all_fdset.clone();
            let res = select::select(high_fd + 1, Some(&mut fdset), None, None, None);
            assert!(res > 0);
            println!("selected returned {}", res);
            debug_fdset(&fdset);

            let mut accept_new = false;

            let mut handled_fds = 0;
            for i in 0 .. high_fd + 1 {
                if fdset.contains(i) {
                    if i == srv_fd {
                        println!("need to accept new connection");
                        accept_new = true;
                    } else if i == child_stdout.as_raw_fd() {
                        println!("child fd {} (stdout) got active", i);
                        read_child(&mut child_stdout);
                    } else if i == child_stderr.as_raw_fd() {
                        println!("child fd {} (stderr) got active", i);
                        read_child(&mut child_stderr);
                    } else {
                        assert!(clients.contains_key(&i));
                        let cont = {
                            let ref stream = clients[&i];
                            read_client(&stream)
                        };
                        if !cont {
                            del_client(&mut all_fdset, &mut clients, i);
                        };
                    }
                    handled_fds += 1;
                }
            }
            assert_eq!(handled_fds, res);
            if accept_new {break}
        }
    }
}
<commit_msg>copying<commit_after>extern crate tinyrsh;

use std::collections::HashMap;
use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
use std::os::unix::io::{RawFd, AsRawFd, IntoRawFd};
use tinyrsh::select as select;
use tinyrsh::select::FdSet;
use std::process::{Command, Stdio};

fn greet_client(mut stream: &TcpStream) {
    let remote = stream.peer_addr().unwrap();
    println!("connected: {}", remote);

    match stream.write(b"hello") {
        Err(e) => println!("{}", e),
        Ok(n) => println!("wrote {} bytes", n),
    };
}

//what the develry! mut stream as parameter??
fn read_client(mut stream: &TcpStream) -> bool {
    let remote = stream.peer_addr().unwrap();

    let mut buffer = [0; 10];
    let cont = match stream.read(&mut buffer) {
        Err(e) => {
                println!("{}", e);
                false
            },
        Ok(n) => {
                println!("{}: {:?} ({} bytes)", remote, buffer, n);
                n != 0
            },
    };
    cont
}

fn debug_fdset(fdset: &FdSet) {
    let maxfds = select::FD_SETSIZE;
    for i in 0 .. maxfds {
        if fdset.contains(i) {
            println!("contains {}", i);
        }
    }
}

fn read_child<T: Read>(readt: &mut T) {
    let mut buf = [0; 10];
    let n = readt.read(&mut buf).expect("read_child");
    println!("{:?} ({} bytes) `{}'", buf, n, String::from_utf8_lossy(&buf[..n]));
}

fn copy_to<T: Read, U: Write>(from: &mut T, to: &mut U) -> bool {
    let mut buf = [0; 10];
    let n = from.read(&mut buf).expect("copy_to read");
    println!("copy_to read {:?} ({} bytes) `{}'", buf, n, String::from_utf8_lossy(&buf[..n]));
    let written = to.write(&buf[..n]).expect("copy_to write");
    to.flush();
    assert_eq!(n, written);

    n != 0
}

fn main() {
    println!("Hello, world!");

    let child = Command::new("../py-ptysh/ptysh.py")
            //.arg("-a")
            .stdin(Stdio::piped())
            .stdout(Stdio::piped())
            .stderr(Stdio::piped())
            .spawn()
            .expect("failed to execute process");
    println!("spawned child with pid {}", child.id());

    let mut child_stdin  = child.stdin.unwrap();
    let mut child_stdout = child.stdout.unwrap();
    let mut child_stderr = child.stderr.unwrap();

        // test read output!!! not linebuffered??
        let mut buffer = [0; 10];
        let n = child_stdout.read(&mut buffer).expect("child stdout read");
        println!("childstdout: {:?} ({} bytes)", buffer, n);

    let listener = TcpListener::bind("127.0.0.1:6699").unwrap();

    let mut all_fdset = FdSet::new();
    let srv_fd = listener.as_raw_fd(); // not consumed

    //high fd for select() call
    let mut high_fd = 0;

    for fd in [srv_fd, child_stdout.as_raw_fd(), child_stderr.as_raw_fd()].iter() {
        println!("inserting fd {}", fd);
        all_fdset.insert(*fd);
        high_fd = std::cmp::max(high_fd, *fd);
    };

    let mut clients: HashMap<RawFd, TcpStream> = HashMap::new(); //could also use FromRawFd

    fn add_client(all_fdset: &mut FdSet, clients: &mut HashMap<RawFd, TcpStream>, stream: TcpStream) -> RawFd {
        let stream_fd: RawFd = stream.as_raw_fd(); //not consume
        println!("inserted fd {}", stream_fd);
        clients.insert(stream_fd, stream);
        all_fdset.insert(stream_fd);
        stream_fd
    };
    fn del_client(all_fdset: &mut FdSet, clients: &mut HashMap<RawFd, TcpStream>, stream_fd: RawFd) {
        assert!(clients.contains_key(&stream_fd));
        //let stream = clients.get(&stream_fd);
        println!("removing fd {}", stream_fd);
        assert!(all_fdset.contains(stream_fd));
        all_fdset.remove(stream_fd);
        assert!(clients.contains_key(&stream_fd));
        clients.remove(&stream_fd);
    };

    for stream in listener.incoming() {
        match stream {
            Ok(mut stream) => {
                greet_client(&mut stream);
                high_fd = std::cmp::max(high_fd, add_client(&mut all_fdset, &mut clients, stream));
                println!("new high fd: {}", high_fd);
            }
            Err(e) => { /* connection failed */ }
        }
        println!("selecting");
        loop {
            let mut fdset = all_fdset.clone();
            let res = select::select(high_fd + 1, Some(&mut fdset), None, None, None);
            assert!(res > 0);
            println!("selected returned {}", res);
            debug_fdset(&fdset);

            let mut accept_new = false;

            let mut handled_fds = 0;
            for i in 0 .. high_fd + 1 {
                if fdset.contains(i) {
                    if i == srv_fd {
                        println!("need to accept new connection");
                        accept_new = true;
                    } else if i == child_stdout.as_raw_fd() {
                        println!("child fd {} (stdout) got active", i);
                        read_child(&mut child_stdout);
                    } else if i == child_stderr.as_raw_fd() {
                        println!("child fd {} (stderr) got active", i);
                        read_child(&mut child_stderr);
                    } else {
                        assert!(clients.contains_key(&i));
                        let cont = {
                            //let ref stream = clients[&i];
                            let stream: &mut TcpStream= clients.get_mut(&i).unwrap();
                            //read_client(stream)
                            copy_to(stream, &mut child_stdin)
                        };
                        if !cont {
                            del_client(&mut all_fdset, &mut clients, i);
                        };
                    }
                    handled_fds += 1;
                }
            }
            assert_eq!(handled_fds, res);
            if accept_new {break}
        }
    }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

use cgmath::vector::{
    Vec3,
    Vec2,
};
use gl_helpers::{
    Shader,
    uniform_mat4f,
    set_clear_color,
    clear_screen,
    get_vec2_from_pixel,
};
use map::MapPosIter;
use camera::Camera;
use geom::Geom;
use mesh::Mesh;
use core_types::{
    Int,
    Size2,
    MapPos,
};
use gl_types::{
    VertexCoord,
    Color3,
    Float,
    MatId,
};

fn build_hex_map_mesh(
    geom: &Geom,
    map_size: Size2<Int>
) -> (~[VertexCoord], ~[Color3]) {
    let mut c_data = ~[];
    let mut v_data = ~[];
    for tile_pos in MapPosIter::new(map_size) {
        let pos3d = geom.map_pos_to_world_pos(tile_pos);
        for num in range(0 as Int, 6) {
            let vertex = geom.index_to_hex_vertex(num);
            let next_vertex = geom.index_to_hex_vertex(num + 1);
            let col_x = tile_pos.x as Float / 255.0;
            let col_y = tile_pos.y as Float / 255.0;
            let color = Color3{r: col_x, g: col_y, b: 1.0};
            v_data.push(pos3d + vertex);
            c_data.push(color);
            v_data.push(pos3d + next_vertex);
            c_data.push(color);
            v_data.push(pos3d + Vec3::zero());
            c_data.push(color);
        }
    }
    (v_data, c_data)
}

pub struct TilePicker {
    shader: Shader,
    map_mesh: Mesh,
    mat_id: MatId,
    win_size: Size2<Int>,
}

impl TilePicker {
    pub fn new(
        win_size: Size2<Int>,
        geom: &Geom,
        map_size: Size2<Int>
    ) -> ~TilePicker {
        let mut picker = ~TilePicker {
            shader: Shader::new("pick.vs.glsl", "pick.fs.glsl"),
            map_mesh: Mesh::new(),
            mat_id: MatId(0),
            win_size: win_size,
        };
        picker.init(geom, map_size);
        picker
    }

    pub fn set_win_size(&mut self, win_size: Size2<Int>) {
        self.win_size = win_size;
    }

    fn init(&mut self, geom: &Geom, map_size: Size2<Int>) {
        let (vertex_data, color_data) = build_hex_map_mesh(geom, map_size);
        self.map_mesh.set_vertex_coords(vertex_data);
        self.map_mesh.set_color(color_data);
        self.map_mesh.prepare(&self.shader);
        self.mat_id = MatId(self.shader.get_uniform("mvp_mat"));
    }

    pub fn pick_tile(
        &mut self,
        camera: &Camera,
        mouse_pos: Vec2<Int>
    ) -> Option<MapPos> {
        self.shader.activate();
        uniform_mat4f(self.mat_id, &camera.mat());
        set_clear_color(0.0, 0.0, 0.0);
        clear_screen();
        self.map_mesh.draw(&self.shader);
        get_vec2_from_pixel(self.win_size, mouse_pos)
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>TilePicker: Removed init method<commit_after>// See LICENSE file for copyright and license details.

use cgmath::vector::{
    Vec3,
    Vec2,
};
use gl_helpers::{
    Shader,
    uniform_mat4f,
    set_clear_color,
    clear_screen,
    get_vec2_from_pixel,
};
use map::MapPosIter;
use camera::Camera;
use geom::Geom;
use mesh::Mesh;
use core_types::{
    Int,
    Size2,
    MapPos,
};
use gl_types::{
    VertexCoord,
    Color3,
    Float,
    MatId,
};

fn build_hex_map_mesh(
    geom: &Geom,
    map_size: Size2<Int>
) -> (~[VertexCoord], ~[Color3]) {
    let mut c_data = ~[];
    let mut v_data = ~[];
    for tile_pos in MapPosIter::new(map_size) {
        let pos3d = geom.map_pos_to_world_pos(tile_pos);
        for num in range(0 as Int, 6) {
            let vertex = geom.index_to_hex_vertex(num);
            let next_vertex = geom.index_to_hex_vertex(num + 1);
            let col_x = tile_pos.x as Float / 255.0;
            let col_y = tile_pos.y as Float / 255.0;
            let color = Color3{r: col_x, g: col_y, b: 1.0};
            v_data.push(pos3d + vertex);
            c_data.push(color);
            v_data.push(pos3d + next_vertex);
            c_data.push(color);
            v_data.push(pos3d + Vec3::zero());
            c_data.push(color);
        }
    }
    (v_data, c_data)
}

fn get_mesh(geom: &Geom, map_size: Size2<Int>, shader: &Shader) -> Mesh {
    let mut mesh = Mesh::new();
    let (vertex_data, color_data) = build_hex_map_mesh(geom, map_size);
    mesh.set_vertex_coords(vertex_data);
    mesh.set_color(color_data);
    mesh.prepare(shader);
    mesh
}

pub struct TilePicker {
    shader: Shader,
    map_mesh: Mesh,
    mat_id: MatId,
    win_size: Size2<Int>,
}

impl TilePicker {
    pub fn new(
        win_size: Size2<Int>,
        geom: &Geom,
        map_size: Size2<Int>
    ) -> ~TilePicker {
        let shader = Shader::new("pick.vs.glsl", "pick.fs.glsl");
        let mat_id = MatId(shader.get_uniform("mvp_mat"));
        let map_mesh = get_mesh(geom, map_size, &shader);
        let picker = ~TilePicker {
            map_mesh: map_mesh,
            shader: shader,
            mat_id: mat_id,
            win_size: win_size,
        };
        picker
    }

    pub fn set_win_size(&mut self, win_size: Size2<Int>) {
        self.win_size = win_size;
    }

    pub fn pick_tile(
        &mut self,
        camera: &Camera,
        mouse_pos: Vec2<Int>
    ) -> Option<MapPos> {
        self.shader.activate();
        uniform_mat4f(self.mat_id, &camera.mat());
        set_clear_color(0.0, 0.0, 0.0);
        clear_screen();
        self.map_mesh.draw(&self.shader);
        get_vec2_from_pixel(self.win_size, mouse_pos)
    }
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Asynchronous input and output.

use std::rc::Rc;
use std::cell::RefCell;
use std::ops::{DerefMut, Deref};
use handle_table::{HandleTable, Handle};
use {EventPort, Promise, PromiseFulfiller, Result, new_promise_and_fulfiller};
use private::{with_current_event_loop};

/// A nonblocking input bytestream.
pub trait AsyncRead : 'static {

    /// Attempts to read `buf.len()` bytes from the stream, writing them into `buf`.
    /// Returns `self`, the modified `buf`, and the number of bytes actually read.
    /// Returns as soon as `min_bytes` are read or EOF is encountered.
    fn try_read<T>(self: Self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize)>
        where T: DerefMut<Target=[u8]>;

    /// Like `try_read()`, but returns an error if EOF is encountered before `min_bytes`
    /// can be read.
    fn read<T>(self: Self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize)>
        where T: DerefMut<Target=[u8]>, Self: Sized
    {
        return self.try_read(buf, min_bytes).map(move |(s, buf, n)| {
            if n < min_bytes {
                return Err(Box::new(::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF")))
            } else {
                return Ok((s, buf, n));
            }
        });
    }
}

/// A nonblocking output bytestream.
pub trait AsyncWrite : 'static {
    /// Attempts to write all `buf.len()` bytes from `buf` into the stream. Returns `self` and `buf`
    /// once all of the bytes have been written.
    fn write<T>(self: Self, buf: T) -> Promise<(Self, T)> where T: Deref<Target=[u8]>;
}

pub struct Slice<T> where T: Deref<Target=[u8]> {
    pub buf: T,
    pub end: usize,
}

impl <T> Slice<T> where T: Deref<Target=[u8]> {
    pub fn new(buf: T, end: usize) -> Slice<T> {
        Slice { buf: buf, end: end }
    }
}

impl <T> Deref for Slice<T> where T: Deref<Target=[u8]> {
    type Target=[u8];
    fn deref<'a>(&'a self) -> &'a [u8] {
        &self.buf[0..self.end]
    }
}

#[derive(Copy, Clone)]
pub struct NetworkAddress {
    address: ::std::net::SocketAddr,
}

impl NetworkAddress {
    pub fn new<T : ::std::net::ToSocketAddrs>(address: T) -> Result<NetworkAddress> {
        match try!(address.to_socket_addrs()).next() {
            Some(addr) => return Ok(NetworkAddress { address: addr }),
            None => unimplemented!(),
        }
    }

    pub fn listen(self) -> Result<ConnectionReceiver> {
        let socket = try!(::mio::tcp::TcpSocket::v4());
        try!(socket.set_reuseaddr(true));
        try!(socket.bind(&self.address));
        let handle = FdObserver::new();
        let listener = try!(socket.listen(256));

        return with_current_event_loop(move |event_loop| {
            try!(event_loop.event_port.borrow_mut().reactor.register_opt(&listener, ::mio::Token(handle.val),
                                                                         ::mio::Interest::readable(),
                                                                         ::mio::PollOpt::edge()));
            Ok(ConnectionReceiver { listener: listener,
                                    handle: handle })
        });
    }

    pub fn connect(self) -> Promise<(AsyncOutputStream, AsyncInputStream)> {
        let socket = ::mio::tcp::TcpSocket::v4().unwrap();
        let handle = FdObserver::new();
        let token = ::mio::Token(handle.val);
        let (stream, _) = socket.connect(&self.address).unwrap();
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().reactor.register_opt(&stream, token,
                                                                    ::mio::Interest::writable(),
                                                                    ::mio::PollOpt::edge()).unwrap();
            let promise =
                event_loop.event_port.borrow_mut().handler.observers[handle].when_becomes_writable();
            return promise.map(move |()| {
                // TODO check for error.

                return with_current_event_loop(move |event_loop| {
                    try!(event_loop.event_port.borrow_mut().reactor.reregister(
                        &stream, token,
                        ::mio::Interest::writable() | ::mio::Interest::readable(),
                        ::mio::PollOpt::edge()));
                    return Ok(AsyncIo::new(stream, handle));
                });

            });
        })
    }
}

pub struct ConnectionReceiver {
    listener: ::mio::tcp::TcpListener,
    handle: Handle,
}

impl Drop for ConnectionReceiver {
    fn drop(&mut self) {
        // deregister the token
    }
}

impl ConnectionReceiver {

    fn accept_internal(self) -> Result<Promise<(ConnectionReceiver, (AsyncOutputStream, AsyncInputStream))>> {
        let accept_result = try!(self.listener.accept());
        match accept_result {
            Some(stream) => {
                let handle = FdObserver::new();
                return with_current_event_loop(move |event_loop| {
                    try!(event_loop.event_port.borrow_mut().reactor.register_opt(
                        &stream, ::mio::Token(handle.val),
                        ::mio::Interest::writable() | ::mio::Interest::readable(),
                        ::mio::PollOpt::edge()));
                    return Ok(Promise::fulfilled((self, AsyncIo::new(stream, handle))));
                });
            }
            None => {
                return with_current_event_loop(move |event_loop| {
                    let promise =
                        event_loop.event_port.borrow_mut().handler.observers[self.handle].when_becomes_readable();
                    return Ok(promise.then(move |()| {
                        return self.accept_internal();
                    }));
                });
            }
        }
    }

    pub fn accept(self) -> Promise<(ConnectionReceiver, (AsyncOutputStream, AsyncInputStream))> {
        return Promise::fulfilled(()).then(move |()| {return self.accept_internal(); });
    }
}

pub struct AsyncInputStream {
    hub: Rc<RefCell<AsyncIo>>
}

pub struct AsyncOutputStream {
    hub: Rc<RefCell<AsyncIo>>
}

struct AsyncIo {
    stream: ::mio::tcp::TcpStream,
    handle: Handle,
}

impl Drop for AsyncIo {
    fn drop(&mut self) {
        return with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
            let _ = event_loop.event_port.borrow_mut().reactor.deregister(&self.stream);
        });
    }
}

impl AsyncIo {
    fn new(stream: ::mio::tcp::TcpStream, handle: Handle) -> (AsyncOutputStream, AsyncInputStream) {
        let hub = Rc::new(RefCell::new(AsyncIo { stream: stream, handle: handle }));

        (AsyncOutputStream { hub: hub.clone() }, AsyncInputStream { hub: hub } )
    }
}

impl AsyncInputStream {
    fn try_read_internal<T>(self,
                            mut buf: T,
                            mut already_read: usize,
                            min_bytes: usize) -> Result<Promise<(Self, T, usize)>> where T: DerefMut<Target=[u8]> {
        use mio::TryRead;

        while already_read < min_bytes {
            let read_result = try!(self.hub.borrow_mut().stream.read_slice(&mut buf[already_read..]));
            match read_result {
                Some(0) => {
                    // EOF
                    return Ok(Promise::fulfilled((self, buf, already_read)));
                }
                Some(n) => {
                    already_read += n;
                }
                None => { // would block
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[self.hub.borrow().handle].when_becomes_readable();
                        return Ok(promise.then(move |()| {
                            return self.try_read_internal(buf, already_read, min_bytes);
                        }));
                    });
                }
            }
        }

        return Ok(Promise::fulfilled((self, buf, already_read)));
    }
}

impl AsyncOutputStream {
    fn write_internal<T>(self,
                         buf: T,
                         mut already_written: usize) -> Result<Promise<(Self, T)>> where T: Deref<Target=[u8]> {
        use mio::TryWrite;

        while already_written < buf.len() {
            let write_result = try!(self.hub.borrow_mut().stream.write_slice(&buf[already_written..]));
            match write_result {
                Some(n) => {
                    already_written += n;
                }
                None => { // would block
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[self.hub.borrow().handle].when_becomes_writable();
                        return Ok(promise.then(move |()| {
                            return self.write_internal(buf, already_written);
                        }));
                    });
                }
            }
        }

        return Ok(Promise::fulfilled((self, buf)));
    }
}

impl AsyncRead for AsyncInputStream {
    fn try_read<T>(self, buf: T,
               min_bytes: usize) -> Promise<(Self, T, usize)> where T: DerefMut<Target=[u8]> {
        return Promise::fulfilled(()).then(move |()| {
            return self.try_read_internal(buf, 0, min_bytes);
        });
    }
}

impl AsyncWrite for AsyncOutputStream {
    fn write<T>(self, buf: T) -> Promise<(Self, T)> where T: Deref<Target=[u8]> {
        return Promise::fulfilled(()).then(move |()| {
            return self.write_internal(buf, 0);
        });
    }
}

struct FdObserver {
    read_fulfiller: Option<Box<PromiseFulfiller<()>>>,
    write_fulfiller: Option<Box<PromiseFulfiller<()>>>,
}

impl FdObserver {
    pub fn new() -> Handle {
        with_current_event_loop(move |event_loop| {

            let observer = FdObserver { read_fulfiller: None, write_fulfiller: None };
            let event_port = &mut *event_loop.event_port.borrow_mut();
            return event_port.handler.observers.push(observer);
        })
    }

    pub fn when_becomes_readable(&mut self) -> Promise<()> {
        let (promise, fulfiller) = new_promise_and_fulfiller();
        self.read_fulfiller = Some(fulfiller);
        return promise;
    }

    pub fn when_becomes_writable(&mut self) -> Promise<()> {
        let (promise, fulfiller) = new_promise_and_fulfiller();
        self.write_fulfiller = Some(fulfiller);
        return promise;
    }
}

pub struct MioEventPort {
    handler: Handler,
    reactor: ::mio::EventLoop<Handler>,
}

struct Handler {
    observers: HandleTable<FdObserver>,
}

impl MioEventPort {
    pub fn new() -> Result<MioEventPort> {
        Ok(MioEventPort {
            handler: Handler { observers: HandleTable::new() },
            reactor: try!(::mio::EventLoop::new()),
        })
    }
}

impl ::mio::Handler for Handler {
    type Timeout = Timeout;
    type Message = ();
    fn readable(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>,
                token: ::mio::Token, _hint: ::mio::ReadHint) {
        match ::std::mem::replace(&mut self.observers[Handle {val: token.0}].read_fulfiller, None) {
            Some(fulfiller) => {
                fulfiller.fulfill(())
            }
            None => {
                ()
            }
        }
    }
    fn writable(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>, token: ::mio::Token) {
        match ::std::mem::replace(&mut self.observers[Handle { val: token.0}].write_fulfiller, None) {
            Some(fulfiller) => fulfiller.fulfill(()),
            None => (),
        }
    }
    fn timeout(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>, timeout: Timeout) {
        timeout.fulfiller.fulfill(());
    }
}

impl EventPort for MioEventPort {
    fn wait(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler).unwrap();
        return false;
    }

    fn poll(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler).unwrap();
        return false;
    }
}

pub struct Timer;

impl Timer {
    pub fn after_delay_ms(&self, delay: u64) -> Promise<()> {
        let (promise, fulfiller) = new_promise_and_fulfiller();
        let timeout = Timeout { fulfiller: fulfiller };
        return with_current_event_loop(move |event_loop| {
            let handle = event_loop.event_port.borrow_mut().reactor.timeout_ms(timeout, delay).unwrap();
            return
                Promise {
                    node: Box::new(
                        ::private::promise_node::Wrapper::new(promise.node,
                                                              TimeoutDropper { handle: handle })) };
        });
    }

    pub fn timeout_after_ms<T>(&self, delay: u64, promise: Promise<T>) -> Promise<T> {
        promise.exclusive_join(self.after_delay_ms(delay).map(|()| {
            return Err(Box::new(::std::io::Error::new(::std::io::ErrorKind::Other, "operation timed out")))
        }))
    }
}

struct TimeoutDropper {
    handle: ::mio::Timeout,
}

impl Drop for TimeoutDropper {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().reactor.clear_timeout(self.handle);
        });
    }
}

struct Timeout {
    fulfiller: Box<PromiseFulfiller<()>>,
}
<commit_msg>Better error handling.<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Asynchronous input and output.

use std::rc::Rc;
use std::cell::RefCell;
use std::ops::{DerefMut, Deref};
use handle_table::{HandleTable, Handle};
use {EventPort, Promise, PromiseFulfiller, Result, new_promise_and_fulfiller};
use private::{with_current_event_loop};

/// A nonblocking input bytestream.
pub trait AsyncRead : 'static {

    /// Attempts to read `buf.len()` bytes from the stream, writing them into `buf`.
    /// Returns `self`, the modified `buf`, and the number of bytes actually read.
    /// Returns as soon as `min_bytes` are read or EOF is encountered.
    fn try_read<T>(self: Self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize)>
        where T: DerefMut<Target=[u8]>;

    /// Like `try_read()`, but returns an error if EOF is encountered before `min_bytes`
    /// can be read.
    fn read<T>(self: Self, buf: T, min_bytes: usize) -> Promise<(Self, T, usize)>
        where T: DerefMut<Target=[u8]>, Self: Sized
    {
        return self.try_read(buf, min_bytes).map(move |(s, buf, n)| {
            if n < min_bytes {
                return Err(Box::new(::std::io::Error::new(::std::io::ErrorKind::Other, "Premature EOF")))
            } else {
                return Ok((s, buf, n));
            }
        });
    }
}

/// A nonblocking output bytestream.
pub trait AsyncWrite : 'static {
    /// Attempts to write all `buf.len()` bytes from `buf` into the stream. Returns `self` and `buf`
    /// once all of the bytes have been written.
    fn write<T>(self: Self, buf: T) -> Promise<(Self, T)> where T: Deref<Target=[u8]>;
}

pub struct Slice<T> where T: Deref<Target=[u8]> {
    pub buf: T,
    pub end: usize,
}

impl <T> Slice<T> where T: Deref<Target=[u8]> {
    pub fn new(buf: T, end: usize) -> Slice<T> {
        Slice { buf: buf, end: end }
    }
}

impl <T> Deref for Slice<T> where T: Deref<Target=[u8]> {
    type Target=[u8];
    fn deref<'a>(&'a self) -> &'a [u8] {
        &self.buf[0..self.end]
    }
}

#[derive(Copy, Clone)]
pub struct NetworkAddress {
    address: ::std::net::SocketAddr,
}

impl NetworkAddress {
    pub fn new<T : ::std::net::ToSocketAddrs>(address: T) -> Result<NetworkAddress> {
        match try!(address.to_socket_addrs()).next() {
            Some(addr) => return Ok(NetworkAddress { address: addr }),
            None => unimplemented!(),
        }
    }

    pub fn listen(self) -> Result<ConnectionReceiver> {
        let socket = try!(::mio::tcp::TcpSocket::v4());
        try!(socket.set_reuseaddr(true));
        try!(socket.bind(&self.address));
        let handle = FdObserver::new();
        let listener = try!(socket.listen(256));

        return with_current_event_loop(move |event_loop| {
            try!(event_loop.event_port.borrow_mut().reactor.register_opt(&listener, ::mio::Token(handle.val),
                                                                         ::mio::Interest::readable(),
                                                                         ::mio::PollOpt::edge()));
            Ok(ConnectionReceiver { listener: listener,
                                    handle: handle })
        });
    }

    pub fn connect(self) -> Promise<(AsyncOutputStream, AsyncInputStream)> {
        return Promise::fulfilled(()).then(move |()| {
            let socket = try!(::mio::tcp::TcpSocket::v4());
            let handle = FdObserver::new();
            let token = ::mio::Token(handle.val);
            let (stream, _) = try!(socket.connect(&self.address));
            with_current_event_loop(move |event_loop| {
                try!(event_loop.event_port.borrow_mut().reactor.register_opt(&stream, token,
                                                                             ::mio::Interest::writable(),
                                                                             ::mio::PollOpt::edge()));
                let promise =
                    event_loop.event_port.borrow_mut().handler.observers[handle].when_becomes_writable();
                return Ok(promise.map(move |()| {
                    // TODO check for error.

                    return with_current_event_loop(move |event_loop| {
                        try!(event_loop.event_port.borrow_mut().reactor.reregister(
                            &stream, token,
                            ::mio::Interest::writable() | ::mio::Interest::readable(),
                            ::mio::PollOpt::edge()));
                        return Ok(AsyncIo::new(stream, handle));
                    });

                }));
            })
        });
    }
}

pub struct ConnectionReceiver {
    listener: ::mio::tcp::TcpListener,
    handle: Handle,
}

impl Drop for ConnectionReceiver {
    fn drop(&mut self) {
        // deregister the token
    }
}

impl ConnectionReceiver {

    fn accept_internal(self) -> Result<Promise<(ConnectionReceiver, (AsyncOutputStream, AsyncInputStream))>> {
        let accept_result = try!(self.listener.accept());
        match accept_result {
            Some(stream) => {
                let handle = FdObserver::new();
                return with_current_event_loop(move |event_loop| {
                    try!(event_loop.event_port.borrow_mut().reactor.register_opt(
                        &stream, ::mio::Token(handle.val),
                        ::mio::Interest::writable() | ::mio::Interest::readable(),
                        ::mio::PollOpt::edge()));
                    return Ok(Promise::fulfilled((self, AsyncIo::new(stream, handle))));
                });
            }
            None => {
                return with_current_event_loop(move |event_loop| {
                    let promise =
                        event_loop.event_port.borrow_mut().handler.observers[self.handle].when_becomes_readable();
                    return Ok(promise.then(move |()| {
                        return self.accept_internal();
                    }));
                });
            }
        }
    }

    pub fn accept(self) -> Promise<(ConnectionReceiver, (AsyncOutputStream, AsyncInputStream))> {
        return Promise::fulfilled(()).then(move |()| {return self.accept_internal(); });
    }
}

pub struct AsyncInputStream {
    hub: Rc<RefCell<AsyncIo>>
}

pub struct AsyncOutputStream {
    hub: Rc<RefCell<AsyncIo>>
}

struct AsyncIo {
    stream: ::mio::tcp::TcpStream,
    handle: Handle,
}

impl Drop for AsyncIo {
    fn drop(&mut self) {
        return with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().handler.observers.remove(self.handle);
            let _ = event_loop.event_port.borrow_mut().reactor.deregister(&self.stream);
        });
    }
}

impl AsyncIo {
    fn new(stream: ::mio::tcp::TcpStream, handle: Handle) -> (AsyncOutputStream, AsyncInputStream) {
        let hub = Rc::new(RefCell::new(AsyncIo { stream: stream, handle: handle }));

        (AsyncOutputStream { hub: hub.clone() }, AsyncInputStream { hub: hub } )
    }
}

impl AsyncInputStream {
    fn try_read_internal<T>(self,
                            mut buf: T,
                            mut already_read: usize,
                            min_bytes: usize) -> Result<Promise<(Self, T, usize)>> where T: DerefMut<Target=[u8]> {
        use mio::TryRead;

        while already_read < min_bytes {
            let read_result = try!(self.hub.borrow_mut().stream.read_slice(&mut buf[already_read..]));
            match read_result {
                Some(0) => {
                    // EOF
                    return Ok(Promise::fulfilled((self, buf, already_read)));
                }
                Some(n) => {
                    already_read += n;
                }
                None => { // would block
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[self.hub.borrow().handle].when_becomes_readable();
                        return Ok(promise.then(move |()| {
                            return self.try_read_internal(buf, already_read, min_bytes);
                        }));
                    });
                }
            }
        }

        return Ok(Promise::fulfilled((self, buf, already_read)));
    }
}

impl AsyncOutputStream {
    fn write_internal<T>(self,
                         buf: T,
                         mut already_written: usize) -> Result<Promise<(Self, T)>> where T: Deref<Target=[u8]> {
        use mio::TryWrite;

        while already_written < buf.len() {
            let write_result = try!(self.hub.borrow_mut().stream.write_slice(&buf[already_written..]));
            match write_result {
                Some(n) => {
                    already_written += n;
                }
                None => { // would block
                    return with_current_event_loop(move |event_loop| {
                        let promise =
                            event_loop.event_port.borrow_mut()
                            .handler.observers[self.hub.borrow().handle].when_becomes_writable();
                        return Ok(promise.then(move |()| {
                            return self.write_internal(buf, already_written);
                        }));
                    });
                }
            }
        }

        return Ok(Promise::fulfilled((self, buf)));
    }
}

impl AsyncRead for AsyncInputStream {
    fn try_read<T>(self, buf: T,
               min_bytes: usize) -> Promise<(Self, T, usize)> where T: DerefMut<Target=[u8]> {
        return Promise::fulfilled(()).then(move |()| {
            return self.try_read_internal(buf, 0, min_bytes);
        });
    }
}

impl AsyncWrite for AsyncOutputStream {
    fn write<T>(self, buf: T) -> Promise<(Self, T)> where T: Deref<Target=[u8]> {
        return Promise::fulfilled(()).then(move |()| {
            return self.write_internal(buf, 0);
        });
    }
}

struct FdObserver {
    read_fulfiller: Option<Box<PromiseFulfiller<()>>>,
    write_fulfiller: Option<Box<PromiseFulfiller<()>>>,
}

impl FdObserver {
    pub fn new() -> Handle {
        with_current_event_loop(move |event_loop| {

            let observer = FdObserver { read_fulfiller: None, write_fulfiller: None };
            let event_port = &mut *event_loop.event_port.borrow_mut();
            return event_port.handler.observers.push(observer);
        })
    }

    pub fn when_becomes_readable(&mut self) -> Promise<()> {
        let (promise, fulfiller) = new_promise_and_fulfiller();
        self.read_fulfiller = Some(fulfiller);
        return promise;
    }

    pub fn when_becomes_writable(&mut self) -> Promise<()> {
        let (promise, fulfiller) = new_promise_and_fulfiller();
        self.write_fulfiller = Some(fulfiller);
        return promise;
    }
}

pub struct MioEventPort {
    handler: Handler,
    reactor: ::mio::EventLoop<Handler>,
}

struct Handler {
    observers: HandleTable<FdObserver>,
}

impl MioEventPort {
    pub fn new() -> Result<MioEventPort> {
        Ok(MioEventPort {
            handler: Handler { observers: HandleTable::new() },
            reactor: try!(::mio::EventLoop::new()),
        })
    }
}

impl ::mio::Handler for Handler {
    type Timeout = Timeout;
    type Message = ();
    fn readable(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>,
                token: ::mio::Token, _hint: ::mio::ReadHint) {
        match ::std::mem::replace(&mut self.observers[Handle {val: token.0}].read_fulfiller, None) {
            Some(fulfiller) => {
                fulfiller.fulfill(())
            }
            None => {
                ()
            }
        }
    }
    fn writable(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>, token: ::mio::Token) {
        match ::std::mem::replace(&mut self.observers[Handle { val: token.0}].write_fulfiller, None) {
            Some(fulfiller) => fulfiller.fulfill(()),
            None => (),
        }
    }
    fn timeout(&mut self, _event_loop: &mut ::mio::EventLoop<Handler>, timeout: Timeout) {
        timeout.fulfiller.fulfill(());
    }
}

impl EventPort for MioEventPort {
    fn wait(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler).unwrap();
        return false;
    }

    fn poll(&mut self) -> bool {
        self.reactor.run_once(&mut self.handler).unwrap();
        return false;
    }
}

pub struct Timer;

impl Timer {
    pub fn after_delay_ms(&self, delay: u64) -> Promise<()> {
        let (promise, fulfiller) = new_promise_and_fulfiller();
        let timeout = Timeout { fulfiller: fulfiller };
        return with_current_event_loop(move |event_loop| {
            let handle = event_loop.event_port.borrow_mut().reactor.timeout_ms(timeout, delay).unwrap();
            return
                Promise {
                    node: Box::new(
                        ::private::promise_node::Wrapper::new(promise.node,
                                                              TimeoutDropper { handle: handle })) };
        });
    }

    pub fn timeout_after_ms<T>(&self, delay: u64, promise: Promise<T>) -> Promise<T> {
        promise.exclusive_join(self.after_delay_ms(delay).map(|()| {
            return Err(Box::new(::std::io::Error::new(::std::io::ErrorKind::Other, "operation timed out")))
        }))
    }
}

struct TimeoutDropper {
    handle: ::mio::Timeout,
}

impl Drop for TimeoutDropper {
    fn drop(&mut self) {
        with_current_event_loop(move |event_loop| {
            event_loop.event_port.borrow_mut().reactor.clear_timeout(self.handle);
        });
    }
}

struct Timeout {
    fulfiller: Box<PromiseFulfiller<()>>,
}
<|endoftext|>


<commit_before><commit_msg>rustfmt: Fix vhdl/score/lower_hir.rs<commit_after><|endoftext|>


<commit_before>use std::fmt;
use instructions::Instruction;
const STACK_SIZE: usize = 256;
const REG_SIZE: usize = 16;

#[derive(Debug,PartialEq)]
enum VMErrorKind {
	StackError,
	ZeroDivision,
}
impl fmt::Debug for VM {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Registers: \n {:?} \nStack Contents:\n {:?}", self.registers, self.stack)
	}
}

pub struct VM {
	stack: Vec<i32>,
	registers: [i32; REG_SIZE],
	ip: usize,
	running: bool,
	debug: bool,
}

impl VM {
	pub fn new() -> VM {
		VM { stack: Vec::with_capacity(STACK_SIZE), registers: [0; REG_SIZE], ip: 0, running: true, debug: true}
	}
	pub fn run(&mut self, program: Vec<Instruction>) {

		while self.running {
			let instruction = &program[self.ip];

			match self.eval(instruction) {
				Ok(_) => {},
				Err(e) => {
					println!("Registers: \n {:?}",self.registers);
					println!("Stack Contents:\n {:?}",self.stack);
					panic!("VMError: {:?} on ip {:?}", e, self.ip + 1);
				}
			}
			self.ip += 1;
		}
	}
	fn eval(&mut self, instruction: &Instruction) -> Result<(), VMErrorKind> {
		match instruction {
			&Instruction::OUT => {
				println!("{:?}", self.stack.last().unwrap() );
				Ok(())
			}
			&Instruction::PSH(value) => {
				self.stack.push(value);
				Ok(())
			}
			&Instruction::POP => {
				match self.stack.pop() {
					Some(val) => Ok(()),
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::ADD => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a + b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::SUB => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a - b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}

			}
			&Instruction::MUL => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a * b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::DIV => {

				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						if b == 0 {
							return Err(VMErrorKind::ZeroDivision)
						} else {
							self.stack.push(a / b);
						}
						Ok(())

					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::SET(register, value) => {
				self.registers[register as usize] = value;
				Ok(())
			}
			&Instruction::MOV(register1, register2) => {
				self.registers[register2 as usize] = self.registers[register1 as usize];
				Ok(())
			}
			&Instruction::LDR(register) => {
				self.stack.push(self.registers[register as usize] as i32 );
				Ok(())
			}
			&Instruction::STR(register) => {
				match self.stack.pop() {
					Some(value) => {
						self.registers[register as usize] = value;
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::JMP => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::JZ => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::JNZ => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::HLT => {
				self.running = false;
				Ok(())
			}
			&Instruction::NOP => {
				Ok(())
			}
		}
	}
}

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

	#[test]
	fn add() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::ADD, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &15);
	}
	#[test]
	fn sub() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::SUB, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &5);
	}
	#[test]
	fn mul() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::MUL, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &50);
	}
	#[test]
	fn div() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::DIV, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &2);
	}

	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn add_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::ADD, Instruction::HLT];
		vm.run(program);
	}
	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn sub_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::SUB, Instruction::HLT];
		vm.run(program);
	}
	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn mul_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::MUL, Instruction::HLT];
		vm.run(program);
	}
	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn div_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::DIV, Instruction::HLT];
		vm.run(program);
	}
	#[test]
	#[should_panic(expected = "VMError: ZeroDivision on ip 3")]
	fn zerodivision() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(0),Instruction::PSH(10),Instruction::DIV, Instruction::HLT];
		vm.run(program);
	}
	#[test]
	fn set() {
		let mut vm = VM::new();
		let program = vec![Instruction::SET(1, 15), Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.registers[1], 15);
	}
	#[test]
	fn mov() {
		let mut vm = VM::new();
		let program = vec![Instruction::SET(1, 15), Instruction::MOV(1, 2), Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.registers[2], 15);
	}
	#[test]
	fn ldr() {
		let mut vm = VM::new();
		let program = vec![Instruction::SET(1, 15), Instruction::LDR(1), Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &15);
	}
	#[test]
	fn str() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::STR(1), Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.registers[1], 5);
	}
	#[test]
	#[should_panic(expected = "VMError: StackError on ip 1")]
	fn str_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::STR(1), Instruction::HLT];
		vm.run(program);

	}
}

<commit_msg>stack op tests<commit_after>use std::fmt;
use instructions::Instruction;
const STACK_SIZE: usize = 256;
const REG_SIZE: usize = 16;

#[derive(Debug,PartialEq)]
enum VMErrorKind {
	StackError,
	ZeroDivision,
}
impl fmt::Debug for VM {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		write!(f, "Registers: \n {:?} \nStack Contents:\n {:?}", self.registers, self.stack)
	}
}

pub struct VM {
	stack: Vec<i32>,
	registers: [i32; REG_SIZE],
	ip: usize,
	running: bool,
	debug: bool,
}

impl VM {
	pub fn new() -> VM {
		VM { stack: Vec::with_capacity(STACK_SIZE), registers: [0; REG_SIZE], ip: 0, running: true, debug: true}
	}
	pub fn run(&mut self, program: Vec<Instruction>) {

		while self.running {
			let instruction = &program[self.ip];

			match self.eval(instruction) {
				Ok(_) => {},
				Err(e) => {
					println!("Registers: \n {:?}",self.registers);
					println!("Stack Contents:\n {:?}",self.stack);
					panic!("VMError: {:?} on ip {:?}", e, self.ip + 1);
				}
			}
			self.ip += 1;
		}
	}
	fn eval(&mut self, instruction: &Instruction) -> Result<(), VMErrorKind> {
		match instruction {
			&Instruction::OUT => {
				println!("{:?}", self.stack.last().unwrap() );
				Ok(())
			}
			&Instruction::PSH(value) => {
				self.stack.push(value);
				Ok(())
			}
			&Instruction::POP => {
				match self.stack.pop() {
					Some(val) => Ok(()),
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::ADD => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a + b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::SUB => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a - b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}

			}
			&Instruction::MUL => {
				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						self.stack.push(a * b);
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::DIV => {

				match (self.stack.pop(), self.stack.pop()) {
					(Some(a), Some(b)) => {
						if b == 0 {
							return Err(VMErrorKind::ZeroDivision)
						} else {
							self.stack.push(a / b);
						}
						Ok(())

					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::SET(register, value) => {
				self.registers[register as usize] = value;
				Ok(())
			}
			&Instruction::MOV(register1, register2) => {
				self.registers[register2 as usize] = self.registers[register1 as usize];
				Ok(())
			}
			&Instruction::LDR(register) => {
				self.stack.push(self.registers[register as usize] as i32 );
				Ok(())
			}
			&Instruction::STR(register) => {
				match self.stack.pop() {
					Some(value) => {
						self.registers[register as usize] = value;
						Ok(())
					},
					_ => Err(VMErrorKind::StackError)
				}
			}
			&Instruction::JMP => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::JZ => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::JNZ => {
				unimplemented!()
				// Ok(())
			}
			&Instruction::HLT => {
				self.running = false;
				Ok(())
			}
			&Instruction::NOP => {
				Ok(())
			}
		}
	}
}

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

	#[test]
	fn psh() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &5);
	}
	#[test]
	fn pop() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::PSH(10), Instruction::POP, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &5);
	}
	#[test]
	fn add() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::ADD, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &15);
	}
	#[test]
	fn sub() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::SUB, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &5);
	}
	#[test]
	fn mul() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::MUL, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &50);
	}
	#[test]
	fn div() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::PSH(10),Instruction::DIV, Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &2);
	}

	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn add_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::ADD, Instruction::HLT];
		vm.run(program);
	}
	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn sub_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::SUB, Instruction::HLT];
		vm.run(program);
	}
	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn mul_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::MUL, Instruction::HLT];
		vm.run(program);
	}
	#[test]
	#[should_panic(expected = "VMError: StackError on ip 2")]
	fn div_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5),Instruction::DIV, Instruction::HLT];
		vm.run(program);
	}
	#[test]
	#[should_panic(expected = "VMError: ZeroDivision on ip 3")]
	fn zerodivision() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(0),Instruction::PSH(10),Instruction::DIV, Instruction::HLT];
		vm.run(program);
	}
	#[test]
	fn set() {
		let mut vm = VM::new();
		let program = vec![Instruction::SET(1, 15), Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.registers[1], 15);
	}
	#[test]
	fn mov() {
		let mut vm = VM::new();
		let program = vec![Instruction::SET(1, 15), Instruction::MOV(1, 2), Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.registers[2], 15);
	}
	#[test]
	fn ldr() {
		let mut vm = VM::new();
		let program = vec![Instruction::SET(1, 15), Instruction::LDR(1), Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.stack.last().unwrap(), &15);
	}
	#[test]
	fn str() {
		let mut vm = VM::new();
		let program = vec![Instruction::PSH(5), Instruction::STR(1), Instruction::HLT];
		vm.run(program);
		assert_eq!( vm.registers[1], 5);
	}
	#[test]
	#[should_panic(expected = "VMError: StackError on ip 1")]
	fn str_stackerror() {
		let mut vm = VM::new();
		let program = vec![Instruction::STR(1), Instruction::HLT];
		vm.run(program);

	}
}

<|endoftext|>