<commit_before>
use std::cmp::Ordering;
use std::path::{ Path, PathBuf };
use std::fs;
use std::fs::{ PathExt, File };
use std::io::{ Write };

use rustc_serialize::json;
use rustc_serialize::json::{ ToJson, Json };

use handlebars::Handlebars;

use ::file_type::{ create_parent_links, Link, read_file, FileType };

static TYPE_STR: &'static str = "dir";

pub struct DirFactory;

impl ::file_type::FileTypeFactory for DirFactory {
    fn try_create(&self, path: &Path) -> Option<Box<FileType>> {
        if path.is_dir() {
            Some(Box::new(Dir {
                path: PathBuf::from(path),
                type_str: TYPE_STR,
                file_type_manager: ::file_type::FileTypeManager::new()
            }))
        } else { None }
    }

    fn initialize(&self, source_root: &Path, handlebars: &mut Handlebars) -> Result<(), &'static str> {

        // Validate generic stuff
        let header_hbs_path = source_root.join("partials/header.hbs");
        if !header_hbs_path.exists() {
            return Err("Missing partials/header.hbs");
        }

        let footer_hbs_path = source_root.join("partials/footer.hbs");
        if !footer_hbs_path.exists() {
            return Err("Missing partials/footer.hbs");
        }

        // Validate Dir
        let dir_hbs_path = source_root.join("layouts/dir.hbs");
        if !dir_hbs_path.exists() {
            return Err("Missing /layouts/dir.hbs");
        }

        // Grab generic stuff
        let header_hbs_contents = try!(read_file(header_hbs_path));
        let footer_hbs_contents = try!(read_file(footer_hbs_path));

        // Create Dir
        let dir_template_name = TYPE_STR;
        let dir_hbs_contents = try!(read_file(&dir_hbs_path));

        handlebars.register_template_string(dir_template_name, format!("{}\n{}\n{}", header_hbs_contents, dir_hbs_contents, footer_hbs_contents))
            .ok().expect("Error registering header|dir|footer template");

        Ok(())
    }
}

pub struct Dir {
    path: PathBuf,
    type_str: &'static str
}

impl Dir {
    fn get_children(&self, context: &::AppContext) -> Vec<Child> {
        let mut result: Vec<Child> = Vec::new();

            match fs::read_dir(&self.path) {
                Ok(items) => {
                    for item in items {
                        let item = item.unwrap().path();
                        let child_opt = self.file_type_manager.create_file_type(&item)
                            .map(|ft| Child {
                                name: String::from_str(item.file_stem().unwrap().to_str().unwrap()),
                                url: ft.get_url(context),
                                file_type: String::from_str(ft.get_type_str())
                            });
                        if child_opt.is_some() { result.push(child_opt.unwrap()); }
                    }
                },
                Err(_) => ()
            }

        (&mut result).sort_by(|a, b| {
            if a.file_type == String::from_str(TYPE_STR) && b.file_type != String::from_str(TYPE_STR) {
                Ordering::Less
            } else {
                a.file_type.cmp(&b.file_type)
            }

        });

        result
    }
}

impl FileType for Dir {
    fn get_url(&self, context: &::AppContext) -> String {
        let relative = self.path.relative_from(&context.root_notes).expect("Problem parsing relative url");
        let relative = if relative.to_str().unwrap() == "." { String::new() } else {
            format!("{}/", relative.to_str().unwrap())
        };
        format!("{}{}", context.base_url, relative)
    }

    fn convert(&self, context: &::AppContext) {
        let relative = self.path.relative_from(&context.root_notes).expect("Problem parsing relative url");
        let new_dir = context.root_dest.join(&relative);
        let new_dir_index = new_dir.join("index.html");
        if !new_dir.exists() {
            fs::create_dir(&new_dir).ok().expect("Cannot create destination subdir");
        }
        let children = self.get_children(context);
        let name = match relative.file_name() {
            Some(_) => String::from_str(relative.file_name().unwrap().to_str().unwrap()),
            None => String::from_str("root")
        };
        let parents = create_parent_links(&context.base_url, &relative, true);
        let dir_model = DirModel {
            name: name,
            parents: parents,
            children: children,
            base_url: context.base_url.clone()
        };
        match context.handlebars.render(TYPE_STR, &dir_model) {
            Ok(rendered) => {
                // Create File
                let mut file = File::create(&new_dir_index).ok().expect("Could not create dir index.html file");
                //fs::chmod(&new_dir_index, USER_FILE).ok().expect("Couldn't chmod new file");
                file.write_all(rendered.as_bytes())
                    .ok().expect("Could not write html to file");
            },
            Err(why) => panic!("Error rendering markdown: {:?}", why)
        }
    }

    fn get_type_str(&self) -> &'static str {
        self.type_str
    }
}

#[derive(RustcEncodable, PartialEq)]
struct Child {
    name: String,
    url: String,
    file_type: String
}

#[derive(RustcEncodable)]
struct DirModel {
    name: String,
    parents: Vec<Link>,
    children: Vec<Child>,
    base_url: String
}

impl ToJson for DirModel {
    fn to_json(&self) -> Json {
        Json::from_str(&json::encode(&self).unwrap()).unwrap()
    }
}
<commit_msg>fixed bug<commit_after>
use std::cmp::Ordering;
use std::path::{ Path, PathBuf };
use std::fs;
use std::fs::{ PathExt, File };
use std::io::{ Write };

use rustc_serialize::json;
use rustc_serialize::json::{ ToJson, Json };

use handlebars::Handlebars;

use ::file_type::{ create_parent_links, Link, read_file, FileType };

static TYPE_STR: &'static str = "dir";

pub struct DirFactory;

impl ::file_type::FileTypeFactory for DirFactory {
    fn try_create(&self, path: &Path) -> Option<Box<FileType>> {
        if path.is_dir() {
            Some(Box::new(Dir {
                path: PathBuf::from(path),
                type_str: TYPE_STR,
                file_type_manager: ::file_type::FileTypeManager::new()
            }))
        } else { None }
    }

    fn initialize(&self, source_root: &Path, handlebars: &mut Handlebars) -> Result<(), &'static str> {

        // Validate generic stuff
        let header_hbs_path = source_root.join("partials/header.hbs");
        if !header_hbs_path.exists() {
            return Err("Missing partials/header.hbs");
        }

        let footer_hbs_path = source_root.join("partials/footer.hbs");
        if !footer_hbs_path.exists() {
            return Err("Missing partials/footer.hbs");
        }

        // Validate Dir
        let dir_hbs_path = source_root.join("layouts/dir.hbs");
        if !dir_hbs_path.exists() {
            return Err("Missing /layouts/dir.hbs");
        }

        // Grab generic stuff
        let header_hbs_contents = try!(read_file(header_hbs_path));
        let footer_hbs_contents = try!(read_file(footer_hbs_path));

        // Create Dir
        let dir_template_name = TYPE_STR;
        let dir_hbs_contents = try!(read_file(&dir_hbs_path));

        handlebars.register_template_string(dir_template_name, format!("{}\n{}\n{}", header_hbs_contents, dir_hbs_contents, footer_hbs_contents))
            .ok().expect("Error registering header|dir|footer template");

        Ok(())
    }
}

pub struct Dir {
    path: PathBuf,
    type_str: &'static str,
    file_type_manager: ::file_type::FileTypeManager
}

impl Dir {
    fn get_children(&self, context: &::AppContext) -> Vec<Child> {
        let mut result: Vec<Child> = Vec::new();

            match fs::read_dir(&self.path) {
                Ok(items) => {
                    for item in items {
                        let item = item.unwrap().path();
                        let child_opt = self.file_type_manager.create_file_type(&item)
                            .map(|ft| Child {
                                name: String::from_str(item.file_stem().unwrap().to_str().unwrap()),
                                url: ft.get_url(context),
                                file_type: String::from_str(ft.get_type_str())
                            });
                        if child_opt.is_some() { result.push(child_opt.unwrap()); }
                    }
                },
                Err(_) => ()
            }

        (&mut result).sort_by(|a, b| {
            if a.file_type == String::from_str(TYPE_STR) && b.file_type != String::from_str(TYPE_STR) {
                Ordering::Less
            } else {
                a.file_type.cmp(&b.file_type)
            }

        });

        result
    }
}

impl FileType for Dir {
    fn get_url(&self, context: &::AppContext) -> String {
        let relative = self.path.relative_from(&context.root_notes).expect("Problem parsing relative url");
        let relative = if relative.to_str().unwrap() == "." { String::new() } else {
            format!("{}/", relative.to_str().unwrap())
        };
        format!("{}{}", context.base_url, relative)
    }

    fn convert(&self, context: &::AppContext) {
        let relative = self.path.relative_from(&context.root_notes).expect("Problem parsing relative url");
        let new_dir = context.root_dest.join(&relative);
        let new_dir_index = new_dir.join("index.html");
        if !new_dir.exists() {
            fs::create_dir(&new_dir).ok().expect("Cannot create destination subdir");
        }
        let children = self.get_children(context);
        let name = match relative.file_name() {
            Some(_) => String::from_str(relative.file_name().unwrap().to_str().unwrap()),
            None => String::from_str("root")
        };
        let parents = create_parent_links(&context.base_url, &relative, true);
        let dir_model = DirModel {
            name: name,
            parents: parents,
            children: children,
            base_url: context.base_url.clone()
        };
        match context.handlebars.render(TYPE_STR, &dir_model) {
            Ok(rendered) => {
                // Create File
                let mut file = File::create(&new_dir_index).ok().expect("Could not create dir index.html file");
                //fs::chmod(&new_dir_index, USER_FILE).ok().expect("Couldn't chmod new file");
                file.write_all(rendered.as_bytes())
                    .ok().expect("Could not write html to file");
            },
            Err(why) => panic!("Error rendering markdown: {:?}", why)
        }
    }

    fn get_type_str(&self) -> &'static str {
        self.type_str
    }
}

#[derive(RustcEncodable, PartialEq)]
struct Child {
    name: String,
    url: String,
    file_type: String
}

#[derive(RustcEncodable)]
struct DirModel {
    name: String,
    parents: Vec<Link>,
    children: Vec<Child>,
    base_url: String
}

impl ToJson for DirModel {
    fn to_json(&self) -> Json {
        Json::from_str(&json::encode(&self).unwrap()).unwrap()
    }
}
<|endoftext|>


<commit_before>use super::super::request::Request;
use super::super::response::Response;
use super::super::middleware::{Middleware, Continue, Unwind, Status};
use super::super::alloy::Alloy;

use super::Chain;

/// The default `Chain` used by `Iron`.
/// `StackChain` runs each `Request` through all `Middleware` in its stack.
/// When it hits `Middleware` which returns `Unwind`, it passes
/// the `Request` back up through all `Middleware` it has hit so far.
pub struct StackChain {
    /// The storage used by `StackChain` to hold all `Middleware`
    /// that have been `linked` to it.
    stack: Vec<Box<Middleware + Send>>,
    exit_stack: Vec<Box<Middleware + Send>>
}

impl Clone for StackChain {
    fn clone(&self) -> StackChain {
        StackChain {
            stack: self.stack.clone(),
            exit_stack: self.exit_stack.clone()
        }
    }
}

/// `StackChain` is a `Chain`
impl Chain for StackChain {
    fn chain_enter(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // The `exit_stack` will hold all `Middleware` that are passed through
        // in the enter loop. This is so we know to take exactly the same
        // path through `Middleware` in reverse order than we did on the way in.
        self.exit_stack = vec![];

        'enter: for middleware in self.stack.mut_iter() {
            match middleware.enter(request, response, alloy) {
                Unwind   => return Unwind,
                // Mark the middleware for traversal on exit.
                Continue => self.exit_stack.push(middleware.clone_box())
            }
        }

        Continue
    }

    fn chain_exit(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // Reverse the stack so we go through in the reverse order.
        // i.e. LIFO.
        self.exit_stack.reverse();
        // Call each middleware's exit handler.
        'exit: for middleware in self.exit_stack.mut_iter() {
            let _ = middleware.exit(request, response, alloy);
        }

        Continue
    }

    /// Add `Middleware` to the `Chain`.
    fn link<M: Middleware>(&mut self, middleware: M) {
        self.stack.push(box middleware);
    }

    /// Create a new instance of `StackChain`.
    fn new() -> StackChain {
        StackChain {
            stack: vec![],
            exit_stack: vec![]
        }
    }
}

#[cfg(test)]
mod test {
    pub use super::*;
    pub use super::super::super::request::Request;
    pub use super::super::super::response::Response;
    pub use super::super::super::alloy::Alloy;
    pub use super::super::super::middleware::{Middleware, Status, Continue};
    pub use std::sync::{Arc, Mutex};

    #[deriving(Clone)]
    pub struct CallCount {
        enter: Arc<Mutex<u64>>,
        exit: Arc<Mutex<u64>>
    }

    impl Middleware for CallCount {
        fn enter(&mut self, _req: &mut Request,
                 _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut enter = self.enter.lock();
            *enter += 1;
            Continue
        }

        fn exit(&mut self, _req: &mut Request,
                _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut exit = self.exit.lock();
            *exit += 1;
            Continue
        }
    }

    mod dispatch {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn calls_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 1);
        }

        #[test]
        fn calls_all_middleware_enter_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter_exits: Vec<(Arc<Mutex<u64>>, Arc<Mutex<u64>>)> = vec![];

            for _ in range(0, 10) {
                let (enter, exit) = (Arc::new(Mutex::new(0)), Arc::new(Mutex::new(0)));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            }

            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }

            for (enter, exit) in enter_exits.move_iter() {
                assert_eq!(*enter.lock(), 1);
                assert_eq!(*exit.lock(), 1);
            }
        }
    }

    mod chain_enter {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn doesnt_call_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 0);
        }
    }
}

<commit_msg>(test) Tested chain_exit.<commit_after>use super::super::request::Request;
use super::super::response::Response;
use super::super::middleware::{Middleware, Continue, Unwind, Status};
use super::super::alloy::Alloy;

use super::Chain;

/// The default `Chain` used by `Iron`.
/// `StackChain` runs each `Request` through all `Middleware` in its stack.
/// When it hits `Middleware` which returns `Unwind`, it passes
/// the `Request` back up through all `Middleware` it has hit so far.
pub struct StackChain {
    /// The storage used by `StackChain` to hold all `Middleware`
    /// that have been `linked` to it.
    stack: Vec<Box<Middleware + Send>>,
    exit_stack: Vec<Box<Middleware + Send>>
}

impl Clone for StackChain {
    fn clone(&self) -> StackChain {
        StackChain {
            stack: self.stack.clone(),
            exit_stack: self.exit_stack.clone()
        }
    }
}

/// `StackChain` is a `Chain`
impl Chain for StackChain {
    fn chain_enter(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // The `exit_stack` will hold all `Middleware` that are passed through
        // in the enter loop. This is so we know to take exactly the same
        // path through `Middleware` in reverse order than we did on the way in.
        self.exit_stack = vec![];

        'enter: for middleware in self.stack.mut_iter() {
            match middleware.enter(request, response, alloy) {
                Unwind   => return Unwind,
                // Mark the middleware for traversal on exit.
                Continue => self.exit_stack.push(middleware.clone_box())
            }
        }

        Continue
    }

    fn chain_exit(&mut self,
             request: &mut Request,
             response: &mut Response,
             alloy: &mut Alloy) -> Status {
        // Reverse the stack so we go through in the reverse order.
        // i.e. LIFO.
        self.exit_stack.reverse();
        // Call each middleware's exit handler.
        'exit: for middleware in self.exit_stack.mut_iter() {
            let _ = middleware.exit(request, response, alloy);
        }

        Continue
    }

    /// Add `Middleware` to the `Chain`.
    fn link<M: Middleware>(&mut self, middleware: M) {
        self.stack.push(box middleware);
    }

    /// Create a new instance of `StackChain`.
    fn new() -> StackChain {
        StackChain {
            stack: vec![],
            exit_stack: vec![]
        }
    }
}

#[cfg(test)]
mod test {
    pub use super::*;
    pub use super::super::super::request::Request;
    pub use super::super::super::response::Response;
    pub use super::super::super::alloy::Alloy;
    pub use super::super::super::middleware::{Middleware, Status, Continue};
    pub use std::sync::{Arc, Mutex};

    #[deriving(Clone)]
    pub struct CallCount {
        enter: Arc<Mutex<u64>>,
        exit: Arc<Mutex<u64>>
    }

    impl Middleware for CallCount {
        fn enter(&mut self, _req: &mut Request,
                 _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut enter = self.enter.lock();
            *enter += 1;
            Continue
        }

        fn exit(&mut self, _req: &mut Request,
                _res: &mut Response, _alloy: &mut Alloy) -> Status {
            let mut exit = self.exit.lock();
            *exit += 1;
            Continue
        }
    }

    mod dispatch {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn calls_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 1);
        }

        #[test]
        fn calls_all_middleware_enter_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter_exits: Vec<(Arc<Mutex<u64>>, Arc<Mutex<u64>>)> = vec![];

            for _ in range(0, 10) {
                let (enter, exit) = (Arc::new(Mutex::new(0)), Arc::new(Mutex::new(0)));
                testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            }

            unsafe {
                let _ = testchain.dispatch(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }

            for (enter, exit) in enter_exits.move_iter() {
                assert_eq!(*enter.lock(), 1);
                assert_eq!(*exit.lock(), 1);
            }
        }
    }

    mod chain_enter {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 1);
        }

        #[test]
        fn doesnt_call_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.link(CallCount { enter: enter.clone(), exit: exit.clone() });
            unsafe {
                let _ = testchain.chain_enter(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 0);
        }
    }

    mod chain_exit {
        use super::{CallCount, Arc, Mutex};
        use super::super::StackChain;
        use super::super::super::Chain;
        use std::mem::{uninitialized};

        #[test]
        fn calls_middleware_exit() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.exit_stack.push(box CallCount {
                enter: enter.clone(), exit: exit.clone()
            });
            unsafe {
                let _  = testchain.chain_exit(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*exit.lock(), 1);
        }

        #[test]
        fn doesnt_call_middleware_enter() {
            let mut testchain: StackChain = Chain::new();
            let enter = Arc::new(Mutex::new(0));
            let exit = Arc::new(Mutex::new(0));
            testchain.exit_stack.push(box CallCount {
                enter: enter.clone(), exit: exit.clone()
            });
            unsafe {
                let _  = testchain.chain_exit(
                    uninitialized(),
                    uninitialized(),
                    uninitialized()
                );
            }
            assert_eq!(*enter.lock(), 0);
        }
    }
}

<|endoftext|>


<commit_before>extern crate collections;
extern crate sync;
extern crate rand;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};
use std::num::Zero;
use std::comm::{Data, Empty, Disconnected};
use sync::{Arc, RWLock};
use sync::Future;
use rand::task_rng;
use rand::distributions::{IndependentSample, Range};
use rand::distributions::range::SampleRange;

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	path: Path,
}

struct BufferEntry {
	frame: Arc<RWLock<BufferFrame>>,
}

#[deriving(Eq)]
enum Status {
	Free,
	Fixed(uint),
}

struct BufferFrame {
	page_id: u64,
	data: Vec<u8>,
	fixed: Status,
}

/* Destructor trait implementation */
impl Drop for BufferManager {
	fn drop(&mut self) {
		println!("Dropping");
		// TODO
	}
}

impl BufferManager {
	pub fn new(size: uint, path: Path) -> BufferManager {
		let h = HashMap::with_capacity(size);
		BufferManager {size: size, entries: h, path: path}
	}

	fn open_or_create(&self, page_id: u64) -> File {
		let file_path = self.path.join(page_id.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(_) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						match f.write([0_u8, ..4 * 1024]) {
							Ok(_) => (),
							Err(e) => fail!("writing page failed: {}", e),
						}
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}", e),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	/*
	 * returns true if page could be loaded
	 */
	fn load_page(&mut self, page_id: u64) -> bool {
		if self.entries.len() == self.size {
			if !self.evict_page() {
				return false;
			}
		}

		let mut file_handle = self.open_or_create(page_id);
		//let content = match file_handle.read_exact(4*1024) {
		let content = match file_handle.read_exact(10) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content, page_id: page_id, fixed: Free};
		let entry = BufferEntry {frame: Arc::new(RWLock::new(frame))};
		self.entries.insert(page_id, entry);
		true
	}

	/*
	 * return false if no page could be evicted
	 */
	fn evict_page(&mut self) -> bool {
		let random_key = {
			let mut iter = self.entries.keys();
			// TODO check if there is a free page
			sample(&mut iter).map(|v| v.clone())
		};

		match random_key {
			None => false,
			Some(key) => self.entries.remove(&key),
		}
	}

	pub fn fix_page(&mut self, page_id: u64) -> Option<Arc<RWLock<BufferFrame>>> {
		if !self.entries.contains_key(&page_id) {
			if !self.load_page(page_id) {
				return None;
			}
		}
		let entry = self.entries.get(&page_id);
		{
			let mut f = entry.frame.write();
			f.fixed = match f.fixed {
				Free => Fixed(1),
				Fixed(n) => Fixed(n+1),
			};
		}
		// Arcs can be cloned and they will all point to the same RWLock
		Some(entry.frame.clone())
	}

	pub fn unfix_page(&mut self, frame: Arc<RWLock<BufferFrame>>, is_dirty: bool) {
		{
			let mut frame = frame.write();
			frame.fixed = match frame.fixed {
				Fixed(1) => Free,
				Fixed(n) => Fixed(n-1),
				Free => fail!("Unfixing unfixed page"),
			};
		}

		if !is_dirty {
			return;
		}
		let frame = frame.read();
		if frame.fixed == Free {
			println!("writing back {}", frame.page_id);
			self.write_page(frame.page_id, frame.get_data());
		}
	}

	fn write_page(&mut self, page_id: u64, data: &[u8]) {
		let file_path = self.path.join(page_id.to_str());
		let mut handle = match File::open_mode(&file_path, Open, Write) {
			Ok(handle) => handle,
			Err(e) => fail!("Opening file for writing failed: {}", e),
		};

		match handle.write(data) {
			Ok(_) => (),
			Err(e) => fail!("Writing to file failed: {}", e),
		};
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * get_mut_data returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn get_mut_data<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

fn sample<'a, T, I:Iterator<T>>(from: &'a mut I) -> Option<T> {
	let from: ~[T] = from.collect();
	let l = from.len();
	if l == 0 {
		return None;
	}
	let index = randrange(l);
	Some(from[index])
}

fn randrange<X: SampleRange + Ord + Zero>(high: X) -> X {
	let between: Range<X> = Range::new(Zero::zero(), high);
	let mut rng = rand::task_rng();
	between.ind_sample(&mut rng)
}

#[test]
fn test_create() {
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};

	let mut bm = BufferManager::new(16, dir.path().clone());
	let pageref = match bm.fix_page(42) {
		Some(p) => p,
		None => fail!("Getting page failed"),
	};
	{
		let mut page = pageref.write();
		let data = page.get_mut_data();
		data[0] = 42;
		//println!("data: {}", Vec::from_slice(data));
	}
	bm.unfix_page(pageref, true);
	fail!("always");
}

#[test]
fn test_threads() {
	use rand::random;
	use std::task::spawn;

	let pages_in_ram = 1;
	let pages_on_disk: u64 = 20;
	let thread_count = 3;
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let p = dir.path();
	let p = Path::new(".");

	let mut buffermanager = BufferManager::new(pages_in_ram, p.clone());

	for i in range(0, pages_on_disk) {
		let bf = match buffermanager.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page {}", i),
		};
		{
			let mut lock = bf.write();
			lock.get_mut_data()[0] = 0;
		}
		buffermanager.unfix_page(bf, true);
	}
	let bm = Arc::new(RWLock::new(buffermanager));

	// start scan thread
	let (tx, rx) = channel();
	let bm_scan = bm.clone();
	let mut scan = Future::spawn(proc() {
		let mut counters = Vec::from_elem(pages_on_disk as uint, 0_u8);
		loop {
			println!("Running scan thread...");
			match rx.try_recv() {
				Empty => {
					let page_number = randrange(pages_on_disk);
					let mut bm = bm_scan.write();
					let bf = match bm.fix_page(page_number) {
						Some(frame) => frame,
						None => fail!("Couldn't scan/fix page"),
					};
					let current_val = {
						let lock = bf.read();
						lock.get_data()[0]
					};
					bm.unfix_page(bf, false);
					bm.downgrade();
					// check if the value is going up
					assert!(&current_val >= counters.get(page_number as uint));
					// set to the new value
					let v = counters.get_mut(page_number as uint);
					*v = current_val;

				},
				/*
				 * terminate on both disconnect and when any kind of
				 * data arrives
				 */
				Disconnected => break,
				Data(_) => break,
			};
		}
	});

	// start read/write threads
	let mut rw_threads: Vec<Future<int>> = Vec::new();
	for _ in range(0, thread_count) {
		let bm = bm.clone();
		rw_threads.push(Future::spawn(proc() {
			let is_write = random::<bool>();
			println!("Creating new {} task",
				if is_write {"write"} else {"read"});
			let page_number = randrange(pages_on_disk);
			let mut bm = bm.write();
			if is_write {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Couldn't fix page"),
				};
				{
					println!("Wrote to page");
					let mut lock = bf.write();
					let data = lock.get_mut_data();
					data[0] = data[0] + 1;
					println!("data: {}", Vec::from_slice(data));
				}
				bm.unfix_page(bf, is_write);
			} else {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Couldn't fix page"),
				};
				bm.unfix_page(bf, is_write);
			}
			// return whether we wrote (1) or read (0) as future
			if is_write {1} else {0}
		}));
	}

	// Rust does not have join, but we can wait on Futures which does the same
	let total_count = rw_threads.mut_iter().fold(0, |acc, val| acc + val.get());
	println!("total_count: {}", total_count);

	// terminate the scan thread and wait until it has completed
	tx.send("terminate");
	scan.get();

	// re-open the pages and check whether all numbers got saved
	let mut bm = BufferManager::new(pages_in_ram, p.clone());
	let mut total_count_on_disk = 0;
	for i in range(0, pages_on_disk) {
		let bf = match bm.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page")
		};
		let value = {
			let lock = bf.read();
			let data = lock.get_data();
			data[0]
		};
		bm.unfix_page(bf, false);
		// cast up from u8 to int
		total_count_on_disk += value as int;
	}
	println!("Total count on disk: {}", total_count_on_disk);
	assert_eq!(total_count, total_count_on_disk);

	fail!("always");
}
<commit_msg>Added code to find a free page to evict<commit_after>extern crate collections;
extern crate sync;
extern crate rand;
use collections::HashMap;
use std::io::{File, Open, Read, Write, TempDir};
use std::num::Zero;
use std::comm::{Data, Empty, Disconnected};
use sync::{Arc, RWLock};
use sync::Future;
use rand::task_rng;
use rand::distributions::{IndependentSample, Range};
use rand::distributions::range::SampleRange;

struct BufferManager {
	size: uint,
	entries: HashMap<u64, BufferEntry>,
	path: Path,
}

struct BufferEntry {
	frame: Arc<RWLock<BufferFrame>>,
}

#[deriving(Eq)]
enum Status {
	Free,
	Fixed(uint),
}

struct BufferFrame {
	page_id: u64,
	data: Vec<u8>,
	fixed: Status,
}

/* Destructor trait implementation */
impl Drop for BufferManager {
	fn drop(&mut self) {
		println!("Dropping");
		// TODO
	}
}

impl BufferManager {
	pub fn new(size: uint, path: Path) -> BufferManager {
		let h = HashMap::with_capacity(size);
		BufferManager {size: size, entries: h, path: path}
	}

	fn open_or_create(&self, page_id: u64) -> File {
		let file_path = self.path.join(page_id.to_str());
		match File::open_mode(&file_path, Open, Read) {
			Ok(f) => f,
			Err(_) => {
				match File::open_mode(&file_path, Open, Write) {
					Ok(mut f) => {
						match f.write([0_u8, ..4 * 1024]) {
							Ok(_) => (),
							Err(e) => fail!("writing page failed: {}", e),
						}
						match File::open_mode(&file_path, Open, Read) {
							Ok(f) => f,
							Err(e) => fail!("failed reading file: {}", e),
						}
					},
					Err(e) => fail!("Writing file failed: {}", e),
				}
			},
		}
	}

	/*
	 * returns true if page could be loaded
	 */
	fn load_page(&mut self, page_id: u64) -> bool {
		if self.entries.len() == self.size {
			if !self.evict_page() {
				return false;
			}
		}

		let mut file_handle = self.open_or_create(page_id);
		//let content = match file_handle.read_exact(4*1024) {
		let content = match file_handle.read_exact(10) {
			Ok(c) => Vec::from_slice(c),
			Err(e) => fail!("Couldn't read from page: {}", e),
		};

		let frame = BufferFrame {data: content, page_id: page_id, fixed: Free};
		let entry = BufferEntry {frame: Arc::new(RWLock::new(frame))};
		self.entries.insert(page_id, entry);
		true
	}

	/*
	 * return false if no page could be evicted
	 */
	fn evict_page(&mut self) -> bool {
		let random_key = {
			let mut free_keys = self.entries.iter().filter_map(|e| {
				// iterate over entries, check if they are free
				// and return the keys of the free entries
				let (k,v) = e;
				let frame = v.frame.read();
				if frame.fixed == Free {
					Some(k)
				} else {
					None
				}
			});
			// pick a random key
			sample(&mut free_keys).map(|v| v.clone())
		};

		match random_key {
			None => false,
			Some(key) => self.entries.remove(&key),
		}
	}

	pub fn fix_page(&mut self, page_id: u64) -> Option<Arc<RWLock<BufferFrame>>> {
		if !self.entries.contains_key(&page_id) {
			if !self.load_page(page_id) {
				return None;
			}
		}
		let entry = self.entries.get(&page_id);
		{
			let mut f = entry.frame.write();
			f.fixed = match f.fixed {
				Free => Fixed(1),
				Fixed(n) => Fixed(n+1),
			};
		}
		// Arcs can be cloned and they will all point to the same RWLock
		Some(entry.frame.clone())
	}

	pub fn unfix_page(&mut self, frame: Arc<RWLock<BufferFrame>>, is_dirty: bool) {
		{
			let mut frame = frame.write();
			frame.fixed = match frame.fixed {
				Fixed(1) => Free,
				Fixed(n) => Fixed(n-1),
				Free => fail!("Unfixing unfixed page"),
			};
		}

		if !is_dirty {
			return;
		}
		let frame = frame.read();
		if frame.fixed == Free {
			println!("writing back {}", frame.page_id);
			self.write_page(frame.page_id, frame.get_data());
		}
	}

	fn write_page(&mut self, page_id: u64, data: &[u8]) {
		let file_path = self.path.join(page_id.to_str());
		let mut handle = match File::open_mode(&file_path, Open, Write) {
			Ok(handle) => handle,
			Err(e) => fail!("Opening file for writing failed: {}", e),
		};

		match handle.write(data) {
			Ok(_) => (),
			Err(e) => fail!("Writing to file failed: {}", e),
		};
	}
}

/*
 * A buffer frame, the unit that gets the data
 */
impl BufferFrame {
	/*
	 * get_mut_data returns a borrowed reference to a mutable slice to the vector
	 * contents.
	 */
	pub fn get_mut_data<'a>(&'a mut self) -> &'a mut [u8] {
		self.data.as_mut_slice()
	}
	pub fn get_data<'a>(&'a self) -> &'a [u8] {
		self.data.as_slice()
	}
}

fn sample<'a, T, I:Iterator<T>>(from: &'a mut I) -> Option<T> {
	let from: ~[T] = from.collect();
	let l = from.len();
	if l == 0 {
		return None;
	}
	let index = randrange(l);
	Some(from[index])
}

fn randrange<X: SampleRange + Ord + Zero>(high: X) -> X {
	let between: Range<X> = Range::new(Zero::zero(), high);
	let mut rng = rand::task_rng();
	between.ind_sample(&mut rng)
}

#[test]
fn test_create() {
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};

	let mut bm = BufferManager::new(16, dir.path().clone());
	let pageref = match bm.fix_page(42) {
		Some(p) => p,
		None => fail!("Getting page failed"),
	};
	{
		let mut page = pageref.write();
		let data = page.get_mut_data();
		data[0] = 42;
		//println!("data: {}", Vec::from_slice(data));
	}
	bm.unfix_page(pageref, true);
	fail!("always");
}

#[test]
fn test_threads() {
	use rand::random;
	use std::task::spawn;

	let pages_in_ram = 1;
	let pages_on_disk: u64 = 20;
	let thread_count = 3;
	let dir = match TempDir::new("buffermanager") {
		Some(temp_dir) => temp_dir,
		None => fail!("creation of temporary directory"),
	};
	let p = dir.path();
	let p = Path::new(".");

	let mut buffermanager = BufferManager::new(pages_in_ram, p.clone());

	for i in range(0, pages_on_disk) {
		let bf = match buffermanager.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page {}", i),
		};
		{
			let mut lock = bf.write();
			lock.get_mut_data()[0] = 0;
		}
		buffermanager.unfix_page(bf, true);
	}
	let bm = Arc::new(RWLock::new(buffermanager));

	// start scan thread
	let (tx, rx) = channel();
	let bm_scan = bm.clone();
	let mut scan = Future::spawn(proc() {
		let mut counters = Vec::from_elem(pages_on_disk as uint, 0_u8);
		loop {
			println!("Running scan thread...");
			match rx.try_recv() {
				Empty => {
					let page_number = randrange(pages_on_disk);
					let mut bm = bm_scan.write();
					let bf = match bm.fix_page(page_number) {
						Some(frame) => frame,
						None => fail!("Couldn't scan/fix page"),
					};
					let current_val = {
						let lock = bf.read();
						lock.get_data()[0]
					};
					bm.unfix_page(bf, false);
					bm.downgrade();
					// check if the value is going up
					assert!(&current_val >= counters.get(page_number as uint));
					// set to the new value
					let v = counters.get_mut(page_number as uint);
					*v = current_val;

				},
				/*
				 * terminate on both disconnect and when any kind of
				 * data arrives
				 */
				Disconnected => break,
				Data(_) => break,
			};
		}
	});

	// start read/write threads
	let mut rw_threads: Vec<Future<int>> = Vec::new();
	for _ in range(0, thread_count) {
		let bm = bm.clone();
		rw_threads.push(Future::spawn(proc() {
			let is_write = random::<bool>();
			println!("Creating new {} task",
				if is_write {"write"} else {"read"});
			let page_number = randrange(pages_on_disk);
			let mut bm = bm.write();
			if is_write {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Couldn't fix page"),
				};
				{
					println!("Wrote to page");
					let mut lock = bf.write();
					let data = lock.get_mut_data();
					data[0] = data[0] + 1;
					println!("data: {}", Vec::from_slice(data));
				}
				bm.unfix_page(bf, is_write);
			} else {
				let bf = match bm.fix_page(page_number) {
					Some(frame) => frame,
					None => fail!("Couldn't fix page"),
				};
				bm.unfix_page(bf, is_write);
			}
			// return whether we wrote (1) or read (0) as future
			if is_write {1} else {0}
		}));
	}

	// Rust does not have join, but we can wait on Futures which does the same
	let total_count = rw_threads.mut_iter().fold(0, |acc, val| acc + val.get());
	println!("total_count: {}", total_count);

	// terminate the scan thread and wait until it has completed
	tx.send("terminate");
	scan.get();

	// re-open the pages and check whether all numbers got saved
	let mut bm = BufferManager::new(pages_in_ram, p.clone());
	let mut total_count_on_disk = 0;
	for i in range(0, pages_on_disk) {
		let bf = match bm.fix_page(i) {
			Some(frame) => frame,
			None => fail!("Couldn't fix page")
		};
		let value = {
			let lock = bf.read();
			let data = lock.get_data();
			data[0]
		};
		bm.unfix_page(bf, false);
		// cast up from u8 to int
		total_count_on_disk += value as int;
	}
	println!("Total count on disk: {}", total_count_on_disk);
	assert_eq!(total_count, total_count_on_disk);

	fail!("always");
}
<|endoftext|>


<commit_before>pub mod err;

pub use err::{Error, Result};

use anime::remote::SeriesInfo;
use once_cell::sync::Lazy;
use regex::Regex;
use snafu::{OptionExt, ResultExt};
use std::borrow::Cow;
use std::fs;
use std::path::{Path, PathBuf};

#[inline]
pub fn best_matching_title<'a, I, S>(titles: I, name: S) -> Option<usize>
where
    I: Iterator<Item = Cow<'a, str>>,
    S: AsRef<str>,
{
    const MIN_CONFIDENCE: f32 = 0.6;
    closest_str_match_idx(titles, name, MIN_CONFIDENCE, strsim::jaro)
}

pub fn best_matching_folder<S, P>(name: S, dir: P) -> Result<PathBuf>
where
    S: AsRef<str>,
    P: AsRef<Path>,
{
    let dir = dir.as_ref();
    let entries = fs::read_dir(dir).context(err::FileIO { path: dir })?;

    let mut dirs = Vec::new();

    for entry in entries {
        let entry = entry.context(err::EntryIO { dir })?;
        let etype = entry.file_type().context(err::EntryIO { dir })?;

        if !etype.is_dir() {
            continue;
        }

        dirs.push(entry);
    }

    let dir = {
        let dir_names = dirs
            .iter()
            .filter_map(|name| parse_folder_title(name.file_name().to_string_lossy()))
            .map(Cow::Owned);

        let dir_idx = best_matching_title(dir_names, &name).context(err::NoMatchingSeries {
            name: name.as_ref(),
        })?;

        dirs.swap_remove(dir_idx)
    };

    Ok(dir.path())
}

pub fn parse_folder_title<S>(item: S) -> Option<String>
where
    S: AsRef<str>,
{
    // This pattern parses titles out of strings like this:
    // [GroupName] Series Title (01-13) [1080p]
    static EXTRACT_SERIES_TITLE: Lazy<Regex> =
        Lazy::new(|| Regex::new(r"(?:\[.+?\]\s*)?(?P<title>.+?)(?:\(|\[|$)").unwrap());

    let caps = EXTRACT_SERIES_TITLE.captures(item.as_ref())?;
    let title = caps["title"].to_string();

    Some(title)
}

pub fn best_matching_info<S>(name: S, items: &[SeriesInfo]) -> Option<usize>
where
    S: AsRef<str>,
{
    let items = items
        .iter()
        .map(|info| Cow::Borrowed(info.title.romaji.as_ref()));

    best_matching_title(items, name)
}

/// Find the most similar string to `value` in `items` and return the index of it.
///
/// `min_confidence` should be a value between 0 and 1 representing the minimum similarity
/// needed in order to have a match.
///
/// `algo` is meant to take functions from the `strsim` crate. However, if implementing
/// manually, then it should return a value between 0 and 1, representing the similarity
/// of two strings.
pub fn closest_str_match_idx<'a, I, S, F>(
    items: I,
    value: S,
    min_confidence: f32,
    algo: F,
) -> Option<usize>
where
    I: Iterator<Item = Cow<'a, str>>,
    S: AsRef<str>,
    F: Fn(&str, &str) -> f64,
{
    let mut max_score = 0.0;
    let mut best_match = None;

    // Casing can really skew the similarity score, so we should match everything
    // in lowercase
    let value = value.as_ref().to_ascii_lowercase();

    for (i, item) in items.enumerate() {
        let item = {
            let mut item = item.into_owned();
            item.make_ascii_lowercase();
            item
        };

        let score = algo(&item, &value) as f32;

        if score > max_score {
            // We want the first item to hit a ~1.0 score rather than the last one
            if score > 0.99 {
                return Some(i);
            }

            best_match = Some(i);
            max_score = score;
        }
    }

    if max_score < min_confidence {
        return None;
    }

    best_match
}

/// Find and return the most similar string to `value` in `items`. Note that this
/// function attemps to move the found item out of the `items` slice. If that is
/// not desired, consider using `closest_str_match_idx` instead.
///
/// `min_confidence` should be a value between 0 and 1 representing the minimum similarity
/// needed in order to have a match.
///
/// `algo` is meant to take functions from the `strsim` crate. However, if implementing
/// manually, then it should return a value between 0 and 1, representing the similarity
/// of two strings.
pub fn closest_str_match<'a, S, F>(
    items: &[&'a str],
    value: S,
    min_confidence: f32,
    algo: F,
) -> Option<&'a str>
where
    S: AsRef<str>,
    F: Fn(&str, &str) -> f64,
{
    let idx = closest_str_match_idx(
        items.iter().map(|&x| Cow::Borrowed(x)),
        value,
        min_confidence,
        algo,
    )?;

    Some(items[idx])
}
<commit_msg>detect: remove closest_str_match function<commit_after>pub mod err;

pub use err::{Error, Result};

use anime::remote::SeriesInfo;
use once_cell::sync::Lazy;
use regex::Regex;
use snafu::{OptionExt, ResultExt};
use std::borrow::Cow;
use std::fs;
use std::path::{Path, PathBuf};

#[inline]
pub fn best_matching_title<'a, I, S>(titles: I, name: S) -> Option<usize>
where
    I: Iterator<Item = Cow<'a, str>>,
    S: AsRef<str>,
{
    const MIN_CONFIDENCE: f32 = 0.6;
    closest_str_match_idx(titles, name, MIN_CONFIDENCE, strsim::jaro)
}

pub fn best_matching_folder<S, P>(name: S, dir: P) -> Result<PathBuf>
where
    S: AsRef<str>,
    P: AsRef<Path>,
{
    let dir = dir.as_ref();
    let entries = fs::read_dir(dir).context(err::FileIO { path: dir })?;

    let mut dirs = Vec::new();

    for entry in entries {
        let entry = entry.context(err::EntryIO { dir })?;
        let etype = entry.file_type().context(err::EntryIO { dir })?;

        if !etype.is_dir() {
            continue;
        }

        dirs.push(entry);
    }

    let dir = {
        let dir_names = dirs
            .iter()
            .filter_map(|name| parse_folder_title(name.file_name().to_string_lossy()))
            .map(Cow::Owned);

        let dir_idx = best_matching_title(dir_names, &name).context(err::NoMatchingSeries {
            name: name.as_ref(),
        })?;

        dirs.swap_remove(dir_idx)
    };

    Ok(dir.path())
}

pub fn parse_folder_title<S>(item: S) -> Option<String>
where
    S: AsRef<str>,
{
    // This pattern parses titles out of strings like this:
    // [GroupName] Series Title (01-13) [1080p]
    static EXTRACT_SERIES_TITLE: Lazy<Regex> =
        Lazy::new(|| Regex::new(r"(?:\[.+?\]\s*)?(?P<title>.+?)(?:\(|\[|$)").unwrap());

    let caps = EXTRACT_SERIES_TITLE.captures(item.as_ref())?;
    let title = caps["title"].to_string();

    Some(title)
}

pub fn best_matching_info<S>(name: S, items: &[SeriesInfo]) -> Option<usize>
where
    S: AsRef<str>,
{
    let items = items
        .iter()
        .map(|info| Cow::Borrowed(info.title.romaji.as_ref()));

    best_matching_title(items, name)
}

/// Find the most similar string to `value` in `items` and return the index of it.
///
/// `min_confidence` should be a value between 0 and 1 representing the minimum similarity
/// needed in order to have a match.
///
/// `algo` is meant to take functions from the `strsim` crate. However, if implementing
/// manually, then it should return a value between 0 and 1, representing the similarity
/// of two strings.
pub fn closest_str_match_idx<'a, I, S, F>(
    items: I,
    value: S,
    min_confidence: f32,
    algo: F,
) -> Option<usize>
where
    I: Iterator<Item = Cow<'a, str>>,
    S: AsRef<str>,
    F: Fn(&str, &str) -> f64,
{
    let mut max_score = 0.0;
    let mut best_match = None;

    // Casing can really skew the similarity score, so we should match everything
    // in lowercase
    let value = value.as_ref().to_ascii_lowercase();

    for (i, item) in items.enumerate() {
        let item = {
            let mut item = item.into_owned();
            item.make_ascii_lowercase();
            item
        };

        let score = algo(&item, &value) as f32;

        if score > max_score {
            // We want the first item to hit a ~1.0 score rather than the last one
            if score > 0.99 {
                return Some(i);
            }

            best_match = Some(i);
            max_score = score;
        }
    }

    if max_score < min_confidence {
        return None;
    }

    best_match
}
<|endoftext|>


<commit_before>/// Storage for topological data in a mesh.

use std::collections::HashMap;
use std::collections::hash_map::{Iter, IterMut};
use std::hash::Hash;
use std::ops::{Deref, DerefMut};

use graph::topology::Topological;

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct Key(u64);

impl Key {
    // TODO: This allows tests to be more terse, but in a very fragile way.
    //       Replace this with an alternative way to find relevant topology.
    #[cfg(test)]
    pub(crate) fn new(value: u64) -> Self {
        Key(value)
    }
}

impl Deref for Key {
    type Target = u64;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for Key {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

pub trait Generator: Copy + Default {
    fn next(&self) -> Self;
}

impl Generator for () {
    fn next(&self) -> Self {}
}

impl Generator for Key {
    fn next(&self) -> Self {
        Key(**self + 1)
    }
}

pub trait OpaqueKey: Sized {
    type RawKey: Copy + Eq + Hash + Into<Self>;
    type Generator: Generator;

    fn to_inner(&self) -> Self::RawKey;
}

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct VertexKey(Key);

impl From<Key> for VertexKey {
    fn from(key: Key) -> Self {
        VertexKey(key)
    }
}

impl OpaqueKey for VertexKey {
    type RawKey = Key;
    type Generator = Key;

    fn to_inner(&self) -> Self::RawKey {
        self.0
    }
}

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct EdgeKey(Key, Key);

impl EdgeKey {
    // TODO: This may be useful in some existing code that constructs the
    //       opposite edge key.
    #[allow(dead_code)]
    pub(crate) fn to_opposite_key(&self) -> EdgeKey {
        EdgeKey(self.1, self.0)
    }

    pub(crate) fn to_vertex_keys(&self) -> (VertexKey, VertexKey) {
        (self.0.into(), self.1.into())
    }
}

impl OpaqueKey for EdgeKey {
    type RawKey = (Key, Key);
    type Generator = ();

    fn to_inner(&self) -> Self::RawKey {
        (self.0, self.1)
    }
}

impl From<(Key, Key)> for EdgeKey {
    fn from(key: (Key, Key)) -> Self {
        EdgeKey(key.0, key.1)
    }
}

impl From<(VertexKey, VertexKey)> for EdgeKey {
    fn from(key: (VertexKey, VertexKey)) -> Self {
        EdgeKey(key.0.to_inner(), key.1.to_inner())
    }
}

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct FaceKey(Key);

impl From<Key> for FaceKey {
    fn from(key: Key) -> Self {
        FaceKey(key)
    }
}

impl OpaqueKey for FaceKey {
    type RawKey = Key;
    type Generator = Key;

    fn to_inner(&self) -> Self::RawKey {
        self.0
    }
}

pub type StorageIter<'a, T> = Iter<'a, <<T as Topological>::Key as OpaqueKey>::RawKey, T>;
pub type StorageIterMut<'a, T> = IterMut<'a, <<T as Topological>::Key as OpaqueKey>::RawKey, T>;

pub struct Storage<T>(
    <<T as Topological>::Key as OpaqueKey>::Generator,
    HashMap<<<T as Topological>::Key as OpaqueKey>::RawKey, T>,
)
where
    T: Topological;

impl<T> Storage<T>
where
    T: Topological,
{
    pub fn new() -> Self {
        Storage(
            <<T as Topological>::Key as OpaqueKey>::Generator::default(),
            HashMap::new(),
        )
    }

    pub fn map_values_into<U, F>(self, mut f: F) -> Storage<U>
    where
        U: Topological<Key = T::Key>,
        F: FnMut(T) -> U,
    {
        let mut hash = HashMap::new();
        for (key, value) in self.1 {
            hash.insert(key, f(value));
        }
        Storage(self.0, hash)
    }

    #[inline(always)]
    pub fn insert_with_key(&mut self, key: &T::Key, item: T) -> Option<T> {
        self.1.insert(key.to_inner(), item)
    }

    #[inline(always)]
    pub fn contains_key(&self, key: &T::Key) -> bool {
        self.1.contains_key(&key.to_inner())
    }

    #[inline(always)]
    pub fn get(&self, key: &T::Key) -> Option<&T> {
        self.1.get(&key.to_inner())
    }

    #[inline(always)]
    pub fn get_mut(&mut self, key: &T::Key) -> Option<&mut T> {
        self.1.get_mut(&key.to_inner())
    }

    #[inline(always)]
    pub fn remove(&mut self, key: &T::Key) -> Option<T> {
        self.1.remove(&key.to_inner())
    }
}

impl<T> Storage<T>
where
    T: Topological,
    T::Key: From<Key> + OpaqueKey<RawKey = Key, Generator = Key>,
{
    pub fn insert_with_generator(&mut self, item: T) -> T::Key {
        let key = self.0;
        self.1.insert(key, item);
        self.0 = self.0.next();
        key.into()
    }
}

impl<T> Deref for Storage<T>
where
    T: Topological,
{
    type Target = HashMap<<<T as Topological>::Key as OpaqueKey>::RawKey, T>;

    fn deref(&self) -> &Self::Target {
        &self.1
    }
}

impl<T> DerefMut for Storage<T>
where
    T: Topological,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.1
    }
}
<commit_msg>Refactor `Storage` into a struct.<commit_after>/// Storage for topological data in a mesh.

use std::collections::HashMap;
use std::collections::hash_map::{Iter, IterMut};
use std::hash::Hash;
use std::ops::{Deref, DerefMut};

use graph::topology::Topological;

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct Key(u64);

impl Key {
    // TODO: This allows tests to be more terse, but in a very fragile way.
    //       Replace this with an alternative way to find relevant topology.
    #[cfg(test)]
    pub(crate) fn new(value: u64) -> Self {
        Key(value)
    }
}

impl Deref for Key {
    type Target = u64;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for Key {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

pub trait Generator: Copy + Default {
    fn next(&self) -> Self;
}

impl Generator for () {
    fn next(&self) -> Self {}
}

impl Generator for Key {
    fn next(&self) -> Self {
        Key(**self + 1)
    }
}

pub trait OpaqueKey: Sized {
    type RawKey: Copy + Eq + Hash + Into<Self>;
    type Generator: Generator;

    fn to_inner(&self) -> Self::RawKey;
}

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct VertexKey(Key);

impl From<Key> for VertexKey {
    fn from(key: Key) -> Self {
        VertexKey(key)
    }
}

impl OpaqueKey for VertexKey {
    type RawKey = Key;
    type Generator = Key;

    fn to_inner(&self) -> Self::RawKey {
        self.0
    }
}

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct EdgeKey(Key, Key);

impl EdgeKey {
    // TODO: This may be useful in some existing code that constructs the
    //       opposite edge key.
    #[allow(dead_code)]
    pub(crate) fn to_opposite_key(&self) -> EdgeKey {
        EdgeKey(self.1, self.0)
    }

    pub(crate) fn to_vertex_keys(&self) -> (VertexKey, VertexKey) {
        (self.0.into(), self.1.into())
    }
}

impl OpaqueKey for EdgeKey {
    type RawKey = (Key, Key);
    type Generator = ();

    fn to_inner(&self) -> Self::RawKey {
        (self.0, self.1)
    }
}

impl From<(Key, Key)> for EdgeKey {
    fn from(key: (Key, Key)) -> Self {
        EdgeKey(key.0, key.1)
    }
}

impl From<(VertexKey, VertexKey)> for EdgeKey {
    fn from(key: (VertexKey, VertexKey)) -> Self {
        EdgeKey(key.0.to_inner(), key.1.to_inner())
    }
}

#[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
pub struct FaceKey(Key);

impl From<Key> for FaceKey {
    fn from(key: Key) -> Self {
        FaceKey(key)
    }
}

impl OpaqueKey for FaceKey {
    type RawKey = Key;
    type Generator = Key;

    fn to_inner(&self) -> Self::RawKey {
        self.0
    }
}

pub type StorageIter<'a, T> = Iter<'a, <<T as Topological>::Key as OpaqueKey>::RawKey, T>;
pub type StorageIterMut<'a, T> = IterMut<'a, <<T as Topological>::Key as OpaqueKey>::RawKey, T>;

pub struct Storage<T>
where
    T: Topological,
{
    generator: <<T as Topological>::Key as OpaqueKey>::Generator,
    hash: HashMap<<<T as Topological>::Key as OpaqueKey>::RawKey, T>,
}

impl<T> Storage<T>
where
    T: Topological,
{
    pub fn new() -> Self {
        Storage {
            generator: Default::default(),
            hash: HashMap::new(),
        }
    }

    pub fn map_values_into<U, F>(self, mut f: F) -> Storage<U>
    where
        U: Topological<Key = T::Key>,
        F: FnMut(T) -> U,
    {
        let mut hash = HashMap::new();
        for (key, value) in self.hash {
            hash.insert(key, f(value));
        }
        Storage {
            generator: self.generator,
            hash: hash,
        }
    }

    #[inline(always)]
    pub fn insert_with_key(&mut self, key: &T::Key, item: T) -> Option<T> {
        self.hash.insert(key.to_inner(), item)
    }

    #[inline(always)]
    pub fn contains_key(&self, key: &T::Key) -> bool {
        self.hash.contains_key(&key.to_inner())
    }

    #[inline(always)]
    pub fn get(&self, key: &T::Key) -> Option<&T> {
        self.hash.get(&key.to_inner())
    }

    #[inline(always)]
    pub fn get_mut(&mut self, key: &T::Key) -> Option<&mut T> {
        self.hash.get_mut(&key.to_inner())
    }

    #[inline(always)]
    pub fn remove(&mut self, key: &T::Key) -> Option<T> {
        self.hash.remove(&key.to_inner())
    }
}

impl<T> Storage<T>
where
    T: Topological,
    T::Key: From<Key> + OpaqueKey<RawKey = Key, Generator = Key>,
{
    pub fn insert_with_generator(&mut self, item: T) -> T::Key {
        let key = self.generator;
        self.hash.insert(key, item);
        self.generator = self.generator.next();
        key.into()
    }
}

impl<T> Deref for Storage<T>
where
    T: Topological,
{
    type Target = HashMap<<<T as Topological>::Key as OpaqueKey>::RawKey, T>;

    fn deref(&self) -> &Self::Target {
        &self.hash
    }
}

impl<T> DerefMut for Storage<T>
where
    T: Topological,
{
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.hash
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use chip8::Chip8;
use chip8::codeblock::CodeBlock;
use chip8::codeemitter::CodeEmitter;

pub struct Recompiler {
	code_cache: HashMap<u16, CodeBlock>
}

impl Recompiler {
	pub fn new() -> Recompiler {
		Recompiler {
			code_cache: HashMap::new()
		}
	}

	pub fn execute_next_code_block(&mut self, chip8: &mut Chip8) {
		if !self.code_cache.contains_key(&chip8.register_pc) {
			let code_block = Recompiler::recompile_next_code_block(chip8);
			self.code_cache.insert(chip8.register_pc, code_block);
		}
		self.code_cache[&chip8.register_pc].execute();
	}

	fn recompile_next_code_block(chip8: &Chip8) -> CodeBlock {
		let mut code_emitter = CodeEmitter::new();
		let mut register_pc = chip8.register_pc;

		loop {
			let high_byte = chip8.memory[register_pc as usize];
			let low_byte = chip8.memory[register_pc as usize + 1];
			let opcode = (high_byte >> 4, high_byte & 0x0F, low_byte >> 4, low_byte & 0x0F);
			let nnn = ((high_byte as u16 & 0x0F) << 8) | low_byte as u16;
			let x = high_byte as usize & 0x0F;
			//let y = low_byte as usize >> 4;

			register_pc += 2;

			match opcode {
				(0x0, 0x0, 0xE, 0x0) => {
					unimplemented!();
				},
				(0x0, 0x0, 0xE, 0xE) => {
					unimplemented!();
				},
				(0x1, ..) => {
					unimplemented!();
				},
				(0x2, ..) => {
					register_pc = nnn;
				},
				(0x3, ..) => {
					code_emitter.cmp_imm_with_m8(low_byte, &chip8.register_v[x] as *const u8 as u32);
					code_emitter.mov_imm_to_m16(register_pc, &chip8.register_pc as *const u16 as u32);
					code_emitter.jne(9);
					code_emitter.add_imm_to_m16(2, &chip8.register_pc as *const u16 as u32);
					break;
				},
				(0x4, ..) => {
					unimplemented!();
				},
				(0x5, _, _, 0x0) => {
					unimplemented!();
				},
				(0x6, ..) => code_emitter.mov_imm_to_m8(low_byte, &chip8.register_v[x] as *const u8 as u32),
				(0x7, ..) => code_emitter.add_imm_to_m8(low_byte, &chip8.register_v[x] as *const u8 as u32),
				(0x8, _, _, 0x0) => {
					unimplemented!();
				},
				(0x8, _, _, 0x1) => {
					unimplemented!();
				},
				(0x8, _, _, 0x2) => {
					unimplemented!();
				},
				(0x8, _, _, 0x3) => {
					unimplemented!();
				},
				(0x8, _, _, 0x4) => {
					unimplemented!();
				},
				(0x8, _, _, 0x5) => {
					unimplemented!();
				},
				(0x8, _, _, 0x6) => {
					unimplemented!();
				},
				(0x8, _, _, 0x7) => {
					unimplemented!();
				},
				(0x8, _, _, 0xE) => {
					unimplemented!();
				},
				(0x9, _, _, 0x0) => {
					unimplemented!();
				},
				(0xA, ..) => {
					unimplemented!();
				},
				(0xB, ..) => {
					unimplemented!();
				},
				(0xC, ..) => {
					unimplemented!();
				},
				(0xD, _, _, n) => {
					unimplemented!();
				},
				(0xE, _, 0x9, 0xE) => {
					unimplemented!();
				},
				(0xE, _, 0xA, 0x1) => {
					unimplemented!();
				},
				(0xF, _, 0x0, 0x7) => {
					unimplemented!();
				},
				(0xF, _, 0x0, 0xA) => {
					unimplemented!();
				},
				(0xF, _, 0x1, 0x5) => {
					unimplemented!();
				},
				(0xF, _, 0x1, 0x8) => {
					unimplemented!();
				},
				(0xF, _, 0x1, 0xE) => {
					unimplemented!();
				},
				(0xF, _, 0x2, 0x9) => {
					code_emitter.mov_imm_to_al(5);
					code_emitter.mul_al_with_m(&chip8.register_v[x] as *const u8 as u32);
					code_emitter.mov_ax_to_m(&chip8.register_i as *const u16 as u32);
				},
				(0xF, _, 0x3, 0x3) => {
					unimplemented!();
				},
				(0xF, _, 0x5, 0x5) => {
					unimplemented!();
				},
				(0xF, _, 0x6, 0x5) => {
					unimplemented!();
				},
				_ => panic!("unknown opcode")
			}
		}

		code_emitter.ret();

		CodeBlock::new(code_emitter.raw_code)
	}
}
<commit_msg>Recompiler: implement DXYN<commit_after>use std::collections::HashMap;

use chip8::Chip8;
use chip8::codeblock::CodeBlock;
use chip8::codeemitter::CodeEmitter;

pub struct Recompiler {
	code_cache: HashMap<u16, CodeBlock>,
	draw_sprite_interrupt: bool
}

impl Recompiler {
	pub fn new() -> Recompiler {
		Recompiler {
			code_cache: HashMap::new(),
			draw_sprite_interrupt: false
		}
	}

	pub fn execute_next_code_block(&mut self, chip8: &mut Chip8) {
		if !self.code_cache.contains_key(&chip8.register_pc) {
			let code_block = self.recompile_next_code_block(chip8);
			self.code_cache.insert(chip8.register_pc, code_block);
		}
		self.code_cache[&chip8.register_pc].execute();

		if self.draw_sprite_interrupt {
			let high_byte = chip8.memory[chip8.register_pc as usize - 2];
			let low_byte = chip8.memory[chip8.register_pc as usize - 1];
			let x = high_byte as usize & 0x0F;
			let y = low_byte as usize >> 4;
			let n = low_byte as usize & 0x0F;
			let sprite = &chip8.memory[chip8.register_i as usize .. chip8.register_i as usize + n];
			chip8.register_v[0xF] = chip8.display.draw_sprite(chip8.register_v[x], chip8.register_v[y], sprite) as u8;
			self.draw_sprite_interrupt = false;
		}
	}

	fn recompile_next_code_block(&mut self, chip8: &Chip8) -> CodeBlock {
		let mut code_emitter = CodeEmitter::new();
		let mut register_pc = chip8.register_pc;

		loop {
			let high_byte = chip8.memory[register_pc as usize];
			let low_byte = chip8.memory[register_pc as usize + 1];
			let opcode = (high_byte >> 4, high_byte & 0x0F, low_byte >> 4, low_byte & 0x0F);
			let nnn = ((high_byte as u16 & 0x0F) << 8) | low_byte as u16;
			let x = high_byte as usize & 0x0F;
			//let y = low_byte as usize >> 4;

			register_pc += 2;

			match opcode {
				(0x0, 0x0, 0xE, 0x0) => {
					unimplemented!();
				},
				(0x0, 0x0, 0xE, 0xE) => {
					unimplemented!();
				},
				(0x1, ..) => {
					unimplemented!();
				},
				(0x2, ..) => {
					register_pc = nnn;
				},
				(0x3, ..) => {
					code_emitter.cmp_imm_with_m8(low_byte, &chip8.register_v[x] as *const u8 as u32);
					code_emitter.mov_imm_to_m16(register_pc, &chip8.register_pc as *const u16 as u32);
					code_emitter.jne(9);
					code_emitter.add_imm_to_m16(2, &chip8.register_pc as *const u16 as u32);
					break;
				},
				(0x4, ..) => {
					unimplemented!();
				},
				(0x5, _, _, 0x0) => {
					unimplemented!();
				},
				(0x6, ..) => code_emitter.mov_imm_to_m8(low_byte, &chip8.register_v[x] as *const u8 as u32),
				(0x7, ..) => code_emitter.add_imm_to_m8(low_byte, &chip8.register_v[x] as *const u8 as u32),
				(0x8, _, _, 0x0) => {
					unimplemented!();
				},
				(0x8, _, _, 0x1) => {
					unimplemented!();
				},
				(0x8, _, _, 0x2) => {
					unimplemented!();
				},
				(0x8, _, _, 0x3) => {
					unimplemented!();
				},
				(0x8, _, _, 0x4) => {
					unimplemented!();
				},
				(0x8, _, _, 0x5) => {
					unimplemented!();
				},
				(0x8, _, _, 0x6) => {
					unimplemented!();
				},
				(0x8, _, _, 0x7) => {
					unimplemented!();
				},
				(0x8, _, _, 0xE) => {
					unimplemented!();
				},
				(0x9, _, _, 0x0) => {
					unimplemented!();
				},
				(0xA, ..) => {
					unimplemented!();
				},
				(0xB, ..) => {
					unimplemented!();
				},
				(0xC, ..) => {
					unimplemented!();
				},
				(0xD, ..) => {
					code_emitter.mov_imm_to_m8(1, &self.draw_sprite_interrupt as *const bool as u32);
					code_emitter.mov_imm_to_m16(register_pc, &chip8.register_pc as *const u16 as u32);
					break;
				},
				(0xE, _, 0x9, 0xE) => {
					unimplemented!();
				},
				(0xE, _, 0xA, 0x1) => {
					unimplemented!();
				},
				(0xF, _, 0x0, 0x7) => {
					unimplemented!();
				},
				(0xF, _, 0x0, 0xA) => {
					unimplemented!();
				},
				(0xF, _, 0x1, 0x5) => {
					unimplemented!();
				},
				(0xF, _, 0x1, 0x8) => {
					unimplemented!();
				},
				(0xF, _, 0x1, 0xE) => {
					unimplemented!();
				},
				(0xF, _, 0x2, 0x9) => {
					code_emitter.mov_imm_to_al(5);
					code_emitter.mul_al_with_m(&chip8.register_v[x] as *const u8 as u32);
					code_emitter.mov_ax_to_m(&chip8.register_i as *const u16 as u32);
				},
				(0xF, _, 0x3, 0x3) => {
					unimplemented!();
				},
				(0xF, _, 0x5, 0x5) => {
					unimplemented!();
				},
				(0xF, _, 0x6, 0x5) => {
					unimplemented!();
				},
				_ => panic!("unknown opcode")
			}
		}

		code_emitter.ret();

		CodeBlock::new(code_emitter.raw_code)
	}
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;

extern crate futures;
extern crate tokio_core;

use std::thread;
use std::sync::mpsc::channel;
//use futures::stream::Stream;
//use tokio_core::reactor::Core;
//use tokio_core::net::TcpListener;
use std::net::TcpListener;
use std::collections::HashMap;
use std::io::Write;
//use std::io::Read;
use std::io;
use std::io::prelude::*;
use std::io::BufReader;
//use futures::Future;
use std::sync::{Arc, Mutex};

mod userchannel;
mod messaging;

fn main() {
    let address = "127.0.0.1:8080";
    let listener = TcpListener::bind(&address).unwrap();
    let mut spawned = HashMap::new();
    let mut cnt = 0;

    let addr = listener.local_addr().unwrap();
    println!("Listening for connections on {}", addr);
    let (tx, rx) = channel();

    for socket in listener.incoming() {
        /* 1. Read incoming msg channel
         * 2. If it does not exist, spawn new thread
         * 3. Send socket to thread
         */
        let mut result_str = String::new();
        let mut socket = socket.unwrap();
        let mut stream = BufReader::new(socket.try_clone().unwrap());
        let len  = stream.read_line(&mut result_str);
        println!("Got string {}", result_str);
        if !spawned.contains_key(&result_str) {
            let tx = tx.clone();
            thread::spawn(move|| {
                let (thr_tx, thr_rx) = channel();
                println!("Spawned: Sending socket");

                let mut channel_db = userchannel::ChannelDb{ channelname: "Rust".to_string(), users: HashMap::new(), values: Vec::new() };

                tx.send(thr_tx.clone()).unwrap();
                let mut thr_sock: std::net::TcpStream = thr_rx.recv().unwrap();
                println!("Got thr sock");
                loop {
                    let mut bufstr = String::new();
                    let mut stream = BufReader::new(thr_sock.try_clone().unwrap());
                    let len = stream.read_line(&mut bufstr);

                    thr_sock.write(&bufstr.into_bytes()).unwrap();
                }
            });
            let thr_feed = rx.recv().unwrap();
            println!("Got thr_feed");
            spawned.insert(result_str.clone(), thr_feed);
        }
        let thr_socket = spawned.get_mut(&result_str).unwrap();
        thr_socket.send(socket).unwrap()
    }
}
<commit_msg>Timeout based chatting over Telnet.<commit_after>#![feature(proc_macro)]
#[macro_use]
extern crate serde_derive;

extern crate futures;
extern crate tokio_core;

use std::thread;
use std::sync::mpsc::channel;
//use futures::stream::Stream;
//use tokio_core::reactor::Core;
//use tokio_core::net::TcpListener;
use std::net::TcpStream;
use std::net::TcpListener;
use std::collections::HashMap;
use std::io::Write;
use std::time::Duration;
use std::option::Option;
//use std::io::Read;
use std::io;
use std::io::prelude::*;
use std::io::BufReader;
//use futures::Future;
use std::sync::{Arc, Mutex};

mod userchannel;
mod messaging;

fn main() {
    let address = "127.0.0.1:8080";
    let listener = TcpListener::bind(&address).unwrap();
    let mut spawned = HashMap::new();
    let mut cnt = 0;
    let option: Option<Duration> = Some(Duration::from_millis(50));

    let addr = listener.local_addr().unwrap();
    println!("Listening for connections on {}", addr);
    let (tx, rx) = channel();

    for socket in listener.incoming() {
        /* 1. Read incoming msg channel
         * 2. If it does not exist, spawn new thread
         * 3. Send socket to thread
         */
        let mut result_str = String::new();
        let mut socket = socket.unwrap();
        let mut stream = BufReader::new(socket.try_clone().unwrap());
        let len = stream.read_line(&mut result_str);
        println!("Got string {}", result_str);
        socket.set_read_timeout(option);
        if !spawned.contains_key(&result_str) {
            let tx = tx.clone();
            let result_str = result_str.clone();
            thread::spawn(move|| {
                let (thr_tx, thr_rx) = channel();
                println!("Spawned: Sending socket");
                let mut users = HashMap::new();
                tx.send(thr_tx.clone()).unwrap();
                println!("Got thr sock");
                loop {
                    match thr_rx.try_recv() {
                        Ok(val) => {
                            let thr: TcpStream = val;
                            cnt += 1;
                            users.insert(cnt, thr);
                        },
                        Err(_) => {}
                    }
                    let mut bufstr = String::new();
                    for (user, thr_socket) in &users {
                        let mut stream = BufReader::new(thr_socket.try_clone().unwrap());
                        match stream.read_line(&mut bufstr) {
                            Ok(len) => {
                                if(len > 0) {
                                    for (another_user, mut thr_sock) in &users {
                                        if user != another_user {
                                            let mut msg = another_user.to_string();
                                            msg.push_str(":");
                                            msg.push_str(&bufstr);
                                            thr_sock.write(&msg.into_bytes()).unwrap();
                                        }
                                    }
                                }
                            },
                            Err(_) => {}
                        }
                    }
                }
            });
            let thr_feed = rx.recv().unwrap();
            println!("Got thr_feed");
            spawned.insert(result_str.clone(), thr_feed);
        }
        let thr_socket = spawned.get_mut(&result_str).unwrap();
        thr_socket.send(socket).unwrap()
    }
}
<|endoftext|>


<commit_before>#![allow(clippy::trivially_copy_pass_by_ref)]

use crate::hotkey::KeyCode;
use crate::platform::prelude::*;
use crate::settings::{Field, SettingsDescription, Value};
use serde::{Deserialize, Serialize};

/// The configuration to use for a Hotkey System. It describes with keys to use
/// as hotkeys for the different actions.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[serde(default)]
pub struct HotkeyConfig {
    /// The key to use for splitting and starting a new attempt.
    pub split: Option<KeyCode>,
    /// The key to use for resetting the current attempt.
    pub reset: Option<KeyCode>,
    /// The key to use for undoing the last split.
    pub undo: Option<KeyCode>,
    /// The key to use for skipping the current split.
    pub skip: Option<KeyCode>,
    /// The key to use for pausing the current attempt and starting a new
    /// attempt.
    pub pause: Option<KeyCode>,
    /// The key to use for removing all the pause times from the current time.
    pub undo_all_pauses: Option<KeyCode>,
    /// The key to use for switching to the previous comparison.
    pub previous_comparison: Option<KeyCode>,
    /// The key to use for switching to the next comparison.
    pub next_comparison: Option<KeyCode>,
    /// The key to use for toggling between the `Real Time` and `Game Time`
    /// timing methods.
    pub toggle_timing_method: Option<KeyCode>,
}

#[cfg(any(windows, target_os = "linux"))]
impl Default for HotkeyConfig {
    fn default() -> Self {
        use crate::hotkey::KeyCode::*;
        Self {
            split: Some(NumPad1),
            reset: Some(NumPad3),
            undo: Some(NumPad8),
            skip: Some(NumPad2),
            pause: Some(NumPad5),
            undo_all_pauses: None,
            previous_comparison: Some(NumPad4),
            next_comparison: Some(NumPad6),
            toggle_timing_method: None,
        }
    }
}

#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
impl Default for HotkeyConfig {
    fn default() -> Self {
        use crate::hotkey::KeyCode::*;
        Self {
            split: Some(Numpad1),
            reset: Some(Numpad3),
            undo: Some(Numpad8),
            skip: Some(Numpad2),
            pause: Some(Numpad5),
            undo_all_pauses: None,
            previous_comparison: Some(Numpad4),
            next_comparison: Some(Numpad6),
            toggle_timing_method: None,
        }
    }
}

#[cfg(not(any(
    windows,
    target_os = "linux",
    all(target_arch = "wasm32", target_os = "unknown"),
)))]
impl Default for HotkeyConfig {
    fn default() -> Self {
        Self {
            split: Some(KeyCode),
            reset: Some(KeyCode),
            undo: Some(KeyCode),
            skip: Some(KeyCode),
            pause: Some(KeyCode),
            undo_all_pauses: None,
            previous_comparison: Some(KeyCode),
            next_comparison: Some(KeyCode),
            toggle_timing_method: None,
        }
    }
}

impl HotkeyConfig {
    /// Accesses a generic description of the settings available for the hotkey
    /// configuration and their current values.
    pub fn settings_description(&self) -> SettingsDescription {
        SettingsDescription::with_fields(vec![
            Field::new("Start / Split".into(), self.split.into()),
            Field::new("Reset".into(), self.reset.into()),
            Field::new("Undo Split".into(), self.undo.into()),
            Field::new("Skip Split".into(), self.skip.into()),
            Field::new("Pause".into(), self.pause.into()),
            Field::new("Undo All Pauses".into(), self.undo_all_pauses.into()),
            Field::new(
                "Previous Comparison".into(),
                self.previous_comparison.into(),
            ),
            Field::new("Next Comparison".into(), self.next_comparison.into()),
            Field::new(
                "Toggle Timing Method".into(),
                self.toggle_timing_method.into(),
            ),
        ])
    }

    /// Sets a setting's value by its index to the given value.
    ///
    /// # Errors
    ///
    /// An error is returned if a hotkey is already in use by a different
    /// action.
    ///
    /// # Panics
    ///
    /// This panics if the type of the value to be set is not compatible with
    /// the type of the setting's value. A panic can also occur if the index of
    /// the setting provided is out of bounds.
    pub fn set_value(&mut self, index: usize, value: Value) -> Result<(), ()> {
        let value: Option<KeyCode> = value.into();

        if value.is_some() {
            let any = [
                self.split,
                self.reset,
                self.undo,
                self.skip,
                self.pause,
                self.previous_comparison,
                self.next_comparison,
                self.undo_all_pauses,
            ]
            .iter()
            .enumerate()
            .filter(|&(i, _)| i != index)
            .any(|(_, &v)| v == value);

            if any {
                return Err(());
            }
        }

        match index {
            0 => self.split = value,
            1 => self.reset = value,
            2 => self.undo = value,
            3 => self.skip = value,
            4 => self.pause = value,
            5 => self.undo_all_pauses = value,
            6 => self.previous_comparison = value,
            7 => self.next_comparison = value,
            8 => self.toggle_timing_method = value,
            _ => panic!("Unsupported Setting Index"),
        }

        Ok(())
    }

    /// Decodes the hotkey configuration from JSON.
    #[cfg(feature = "std")]
    pub fn from_json<R>(reader: R) -> serde_json::Result<Self>
    where
        R: std::io::Read,
    {
        serde_json::from_reader(reader)
    }

    /// Encodes the hotkey configuration as JSON.
    #[cfg(feature = "std")]
    pub fn write_json<W>(&self, writer: W) -> serde_json::Result<()>
    where
        W: std::io::Write,
    {
        serde_json::to_writer(writer, self)
    }
}
<commit_msg>Fix Hotkey Assignment Bug<commit_after>#![allow(clippy::trivially_copy_pass_by_ref)]

use crate::hotkey::KeyCode;
use crate::platform::prelude::*;
use crate::settings::{Field, SettingsDescription, Value};
use serde::{Deserialize, Serialize};

/// The configuration to use for a Hotkey System. It describes with keys to use
/// as hotkeys for the different actions.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
#[serde(default)]
pub struct HotkeyConfig {
    /// The key to use for splitting and starting a new attempt.
    pub split: Option<KeyCode>,
    /// The key to use for resetting the current attempt.
    pub reset: Option<KeyCode>,
    /// The key to use for undoing the last split.
    pub undo: Option<KeyCode>,
    /// The key to use for skipping the current split.
    pub skip: Option<KeyCode>,
    /// The key to use for pausing the current attempt and starting a new
    /// attempt.
    pub pause: Option<KeyCode>,
    /// The key to use for removing all the pause times from the current time.
    pub undo_all_pauses: Option<KeyCode>,
    /// The key to use for switching to the previous comparison.
    pub previous_comparison: Option<KeyCode>,
    /// The key to use for switching to the next comparison.
    pub next_comparison: Option<KeyCode>,
    /// The key to use for toggling between the `Real Time` and `Game Time`
    /// timing methods.
    pub toggle_timing_method: Option<KeyCode>,
}

#[cfg(any(windows, target_os = "linux"))]
impl Default for HotkeyConfig {
    fn default() -> Self {
        use crate::hotkey::KeyCode::*;
        Self {
            split: Some(NumPad1),
            reset: Some(NumPad3),
            undo: Some(NumPad8),
            skip: Some(NumPad2),
            pause: Some(NumPad5),
            undo_all_pauses: None,
            previous_comparison: Some(NumPad4),
            next_comparison: Some(NumPad6),
            toggle_timing_method: None,
        }
    }
}

#[cfg(all(target_arch = "wasm32", target_os = "unknown"))]
impl Default for HotkeyConfig {
    fn default() -> Self {
        use crate::hotkey::KeyCode::*;
        Self {
            split: Some(Numpad1),
            reset: Some(Numpad3),
            undo: Some(Numpad8),
            skip: Some(Numpad2),
            pause: Some(Numpad5),
            undo_all_pauses: None,
            previous_comparison: Some(Numpad4),
            next_comparison: Some(Numpad6),
            toggle_timing_method: None,
        }
    }
}

#[cfg(not(any(
    windows,
    target_os = "linux",
    all(target_arch = "wasm32", target_os = "unknown"),
)))]
impl Default for HotkeyConfig {
    fn default() -> Self {
        Self {
            split: Some(KeyCode),
            reset: Some(KeyCode),
            undo: Some(KeyCode),
            skip: Some(KeyCode),
            pause: Some(KeyCode),
            undo_all_pauses: None,
            previous_comparison: Some(KeyCode),
            next_comparison: Some(KeyCode),
            toggle_timing_method: None,
        }
    }
}

impl HotkeyConfig {
    /// Accesses a generic description of the settings available for the hotkey
    /// configuration and their current values.
    pub fn settings_description(&self) -> SettingsDescription {
        SettingsDescription::with_fields(vec![
            Field::new("Start / Split".into(), self.split.into()),
            Field::new("Reset".into(), self.reset.into()),
            Field::new("Undo Split".into(), self.undo.into()),
            Field::new("Skip Split".into(), self.skip.into()),
            Field::new("Pause".into(), self.pause.into()),
            Field::new("Undo All Pauses".into(), self.undo_all_pauses.into()),
            Field::new(
                "Previous Comparison".into(),
                self.previous_comparison.into(),
            ),
            Field::new("Next Comparison".into(), self.next_comparison.into()),
            Field::new(
                "Toggle Timing Method".into(),
                self.toggle_timing_method.into(),
            ),
        ])
    }

    /// Sets a setting's value by its index to the given value.
    ///
    /// # Errors
    ///
    /// An error is returned if a hotkey is already in use by a different
    /// action.
    ///
    /// # Panics
    ///
    /// This panics if the type of the value to be set is not compatible with
    /// the type of the setting's value. A panic can also occur if the index of
    /// the setting provided is out of bounds.
    pub fn set_value(&mut self, index: usize, value: Value) -> Result<(), ()> {
        let value: Option<KeyCode> = value.into();

        if value.is_some() {
            let any = [
                self.split,
                self.reset,
                self.undo,
                self.skip,
                self.pause,
                self.undo_all_pauses,
                self.previous_comparison,
                self.next_comparison,
                self.toggle_timing_method,
            ]
            .iter()
            .enumerate()
            .filter(|&(i, _)| i != index)
            .any(|(_, &v)| v == value);

            if any {
                return Err(());
            }
        }

        match index {
            0 => self.split = value,
            1 => self.reset = value,
            2 => self.undo = value,
            3 => self.skip = value,
            4 => self.pause = value,
            5 => self.undo_all_pauses = value,
            6 => self.previous_comparison = value,
            7 => self.next_comparison = value,
            8 => self.toggle_timing_method = value,
            _ => panic!("Unsupported Setting Index"),
        }

        Ok(())
    }

    /// Decodes the hotkey configuration from JSON.
    #[cfg(feature = "std")]
    pub fn from_json<R>(reader: R) -> serde_json::Result<Self>
    where
        R: std::io::Read,
    {
        serde_json::from_reader(reader)
    }

    /// Encodes the hotkey configuration as JSON.
    #[cfg(feature = "std")]
    pub fn write_json<W>(&self, writer: W) -> serde_json::Result<()>
    where
        W: std::io::Write,
    {
        serde_json::to_writer(writer, self)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use serde::{Deserialize, Serialize};
use std::{
    convert::From,
    fmt::{self, Display},
};
use warp::{http::StatusCode, reject::Reject};

use crate::U64;

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct Error {
    pub code: u16,
    pub message: String,
    /// Diem blockchain latest onchain ledger version.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub aptos_ledger_version: Option<U64>,
}

impl Error {
    pub fn new(code: StatusCode, message: String) -> Self {
        Self {
            code: code.as_u16(),
            message,
            aptos_ledger_version: None,
        }
    }

    pub fn from_anyhow_error(code: StatusCode, err: anyhow::Error) -> Self {
        Self::new(code, err.to_string())
    }

    pub fn bad_request<S: Display>(msg: S) -> Self {
        Self::new(StatusCode::BAD_REQUEST, msg.to_string())
    }

    pub fn not_found<S: Display>(resource: &str, identifier: S, ledger_version: u64) -> Self {
        Self::new(
            StatusCode::NOT_FOUND,
            format!("{} not found by {}", resource, identifier),
        )
        .aptos_ledger_version(ledger_version)
    }

    pub fn invalid_param<S: Display>(name: &str, value: S) -> Self {
        Self::bad_request(format!("invalid parameter {}: {}", name, value))
    }

    pub fn invalid_request_body<S: Display>(msg: S) -> Self {
        Self::bad_request(format!("invalid request body: {}", msg))
    }

    pub fn insufficient_storage<S: Display>(msg: S) -> Self {
        Self::new(StatusCode::INSUFFICIENT_STORAGE, msg.to_string())
    }

    pub fn internal(err: anyhow::Error) -> Self {
        Self::from_anyhow_error(StatusCode::INTERNAL_SERVER_ERROR, err)
    }

    pub fn status_code(&self) -> StatusCode {
        StatusCode::from_u16(self.code).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR)
    }

    pub fn aptos_ledger_version(mut self, ledger_version: u64) -> Self {
        self.aptos_ledger_version = Some(ledger_version.into());
        self
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}: {}", self.status_code(), &self.message)?;
        if let Some(val) = &self.aptos_ledger_version {
            write!(f, "\ndiem ledger version: {}", val)?;
        }
        Ok(())
    }
}

impl Reject for Error {}

impl From<anyhow::Error> for Error {
    fn from(e: anyhow::Error) -> Self {
        Self::internal(e)
    }
}

impl From<serde_json::error::Error> for Error {
    fn from(err: serde_json::error::Error) -> Self {
        Self::internal(err.into())
    }
}

#[cfg(test)]
mod tests {
    use crate::error::Error;
    use warp::http::StatusCode;

    #[test]
    fn test_to_string() {
        let err = Error::new(StatusCode::BAD_REQUEST, "invalid address".to_owned());
        assert_eq!(err.to_string(), "400 Bad Request: invalid address")
    }

    #[test]
    fn test_from_anyhow_error_as_internal_error() {
        let err = Error::from(anyhow::format_err!("hello"));
        assert_eq!(err.to_string(), "500 Internal Server Error: hello")
    }

    #[test]
    fn test_to_string_with_aptos_ledger_version() {
        let err = Error::new(StatusCode::BAD_REQUEST, "invalid address".to_owned())
            .aptos_ledger_version(123);
        assert_eq!(
            err.to_string(),
            "400 Bad Request: invalid address\ndiem ledger version: 123"
        )
    }

    #[test]
    fn test_internal_error() {
        let err = Error::internal(anyhow::format_err!("hello"));
        assert_eq!(err.to_string(), "500 Internal Server Error: hello")
    }
}
<commit_msg>[api] discard diem for aptos (#2177)<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use serde::{Deserialize, Serialize};
use std::{
    convert::From,
    fmt::{self, Display},
};
use warp::{http::StatusCode, reject::Reject};

use crate::U64;

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct Error {
    pub code: u16,
    pub message: String,
    /// Aptos blockchain latest onchain ledger version.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub aptos_ledger_version: Option<U64>,
}

impl Error {
    pub fn new(code: StatusCode, message: String) -> Self {
        Self {
            code: code.as_u16(),
            message,
            aptos_ledger_version: None,
        }
    }

    pub fn from_anyhow_error(code: StatusCode, err: anyhow::Error) -> Self {
        Self::new(code, err.to_string())
    }

    pub fn bad_request<S: Display>(msg: S) -> Self {
        Self::new(StatusCode::BAD_REQUEST, msg.to_string())
    }

    pub fn not_found<S: Display>(resource: &str, identifier: S, ledger_version: u64) -> Self {
        Self::new(
            StatusCode::NOT_FOUND,
            format!("{} not found by {}", resource, identifier),
        )
        .aptos_ledger_version(ledger_version)
    }

    pub fn invalid_param<S: Display>(name: &str, value: S) -> Self {
        Self::bad_request(format!("invalid parameter {}: {}", name, value))
    }

    pub fn invalid_request_body<S: Display>(msg: S) -> Self {
        Self::bad_request(format!("invalid request body: {}", msg))
    }

    pub fn insufficient_storage<S: Display>(msg: S) -> Self {
        Self::new(StatusCode::INSUFFICIENT_STORAGE, msg.to_string())
    }

    pub fn internal(err: anyhow::Error) -> Self {
        Self::from_anyhow_error(StatusCode::INTERNAL_SERVER_ERROR, err)
    }

    pub fn status_code(&self) -> StatusCode {
        StatusCode::from_u16(self.code).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR)
    }

    pub fn aptos_ledger_version(mut self, ledger_version: u64) -> Self {
        self.aptos_ledger_version = Some(ledger_version.into());
        self
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}: {}", self.status_code(), &self.message)?;
        if let Some(val) = &self.aptos_ledger_version {
            write!(f, "\ndiem ledger version: {}", val)?;
        }
        Ok(())
    }
}

impl Reject for Error {}

impl From<anyhow::Error> for Error {
    fn from(e: anyhow::Error) -> Self {
        Self::internal(e)
    }
}

impl From<serde_json::error::Error> for Error {
    fn from(err: serde_json::error::Error) -> Self {
        Self::internal(err.into())
    }
}

#[cfg(test)]
mod tests {
    use crate::error::Error;
    use warp::http::StatusCode;

    #[test]
    fn test_to_string() {
        let err = Error::new(StatusCode::BAD_REQUEST, "invalid address".to_owned());
        assert_eq!(err.to_string(), "400 Bad Request: invalid address")
    }

    #[test]
    fn test_from_anyhow_error_as_internal_error() {
        let err = Error::from(anyhow::format_err!("hello"));
        assert_eq!(err.to_string(), "500 Internal Server Error: hello")
    }

    #[test]
    fn test_to_string_with_aptos_ledger_version() {
        let err = Error::new(StatusCode::BAD_REQUEST, "invalid address".to_owned())
            .aptos_ledger_version(123);
        assert_eq!(
            err.to_string(),
            "400 Bad Request: invalid address\ndiem ledger version: 123"
        )
    }

    #[test]
    fn test_internal_error() {
        let err = Error::internal(anyhow::format_err!("hello"));
        assert_eq!(err.to_string(), "500 Internal Server Error: hello")
    }
}
<|endoftext|>