<commit_before>use ::bitreader::BitReader;
use std::io::Read;

// For Huffman codes used in the Brotli spec, is seems that the length of a
// code is at most 10 bits (max alphabet size is 704).
// For this simple use case, we don't need/want to deal with type parameters.
pub type Symbol = u16;

#[derive(Debug, Clone, PartialEq)]
pub struct Tree {
	buf: Vec<Option<Symbol>>,
	len: usize,
	last_symbol: Option<Symbol>,
}

// Index structure in self.buf[]:
//
//
//            0                ^
//           / \               |
// left <-- /   \ --> right    |
//         /     \             |
//        /       \
//       /         \       Max Code Length == Max Number of Edges in a Path == Max Tree Depth
//      1           2      (in this example it's 3)
//     / \         / \
//    /   \       /   \        |
//   3     4     5     6       |
//  / \   / \   / \   / \      |
// 7   8 9  10 11 12 13 14     v
// …
//
// Length of self.buf[] = 2^(codelength + 1) - 1
//

impl Tree {
	pub fn with_max_depth(max_depth: usize) -> Tree {
		Tree {
			buf: vec![None; (1 << (max_depth + 1)) - 1],
			len: 0,
			last_symbol: None,
		}
	}

	pub fn from_raw_data(buf: Vec<Option<Symbol>>, len: usize, last_symbol: Option<Symbol>) -> Tree {
		Tree {
			buf: buf,
			len: len,
			last_symbol: last_symbol,
		}
	}

	pub fn insert(&mut self, code: &[bool], symbol: Symbol) {
		self.len += 1;
		self.last_symbol = Some(symbol);

		let insert_at_index = (1 << code.len()) - 1 + code.iter().fold(0, |acc, &bit| (acc << 1) + if bit { 1 } else { 0 });

		if insert_at_index > self.buf.len() - 1 {
			panic!("Index {:?} exceeds MAX_INDEX at insert (code = {:?})", insert_at_index, code);
		}

		self.buf[insert_at_index] = Some(symbol)
	}

	fn lookup<R: Read>(&self, r: &mut BitReader<R>) -> Result<Option<Symbol>, ::bitreader::BitReaderError> {
		let mut pseudo_code = 1;
		loop {
			pseudo_code = (pseudo_code << 1) + match r.read_bit_as_usize() {
				Ok(b) => b,
				Err(e) => return Err(e),
			};

			let lookup_index = pseudo_code - 1;

			if lookup_index > self.buf.len() - 1 {
				return Ok(None);
			}

			match self.buf[lookup_index] {
				Some(symbol) => return Ok(Some(symbol)),
				None => {},
			}
		}
	}

	pub fn lookup_symbol<R: Read>(&self, mut r: &mut BitReader<R>) -> Result<Option<Symbol>, ::bitreader::BitReaderError, >  {
		// println!("self.len = {:?}", self.len);

		match self.len {
			0 => Ok(None),
			1 => Ok(self.last_symbol),
			_ => self.lookup(&mut r),
		}
	}
}

mod tests {
	#[test]
	fn should_insert_and_lookup_first_level_leaf_on_left() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![0]));
		let mut tree = Tree::with_max_depth(1);
		tree.insert(&vec![false], 666);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
	}

	#[test]
	fn should_insert_and_lookup_first_level_leaf_on_right() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![1]));
		let mut tree = Tree::with_max_depth(1);
		tree.insert(&vec![true], 666);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
	}

	#[test]
	fn should_insert_first_level_leaf_on_left_then_on_right() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![2]));
		let mut tree = Tree::with_max_depth(1);
		tree.insert(&vec![false], 667);
		tree.insert(&vec![true], 666);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(667)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
	}

	#[test]
	fn should_insert_first_level_leaf_on_right_then_on_left() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![1]));
		let mut tree = Tree::with_max_depth(1);
		tree.insert(&vec![true], 666);
		tree.insert(&vec![false], 667);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(667)));
	}

	#[test]
	fn should_insert_second_level_leaf_left_right() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![2]));
		let mut tree = Tree::with_max_depth(2);
		tree.insert(&vec![false, true], 6666);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6666)));
	}

	#[test]
	fn should_insert_second_level_leaf_right_left() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![1]));
		let mut tree = Tree::with_max_depth(2);
		tree.insert(&vec![true, false], 6666);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6666)));
	}

	#[test]
	fn should_lookup_first_level_leaf_left() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![0b11001]));
		let mut tree = Tree::with_max_depth(2);
		tree.insert(&vec![true, false], 6666);
		tree.insert(&vec![false], 666);
		tree.insert(&vec![true, true], 6667);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6666)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6667)));
	}

	#[test]
	fn should_lookup_first_level_leaf_right() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![0b10100]));
		let mut tree = Tree::with_max_depth(2);
		tree.insert(&vec![false, false], 6666);
		tree.insert(&vec![true], 666);
		tree.insert(&vec![false, true], 6667);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6666)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6667)));
	}
}
<commit_msg>MOD: removed incorrect comment about max code length<commit_after>use ::bitreader::BitReader;
use std::io::Read;

pub type Symbol = u16;

#[derive(Debug, Clone, PartialEq)]
pub struct Tree {
	buf: Vec<Option<Symbol>>,
	len: usize,
	last_symbol: Option<Symbol>,
}

// Index structure in self.buf[]:
//
//
//            0                ^
//           / \               |
// left <-- /   \ --> right    |
//         /     \             |
//        /       \
//       /         \       Max Code Length == Max Number of Edges in a Path == Max Tree Depth
//      1           2      (in this example it's 3)
//     / \         / \
//    /   \       /   \        |
//   3     4     5     6       |
//  / \   / \   / \   / \      |
// 7   8 9  10 11 12 13 14     v
// …
//
// Length of self.buf[] = 2^(codelength + 1) - 1
//

impl Tree {
	pub fn with_max_depth(max_depth: usize) -> Tree {
		Tree {
			buf: vec![None; (1 << (max_depth + 1)) - 1],
			len: 0,
			last_symbol: None,
		}
	}

	pub fn from_raw_data(buf: Vec<Option<Symbol>>, len: usize, last_symbol: Option<Symbol>) -> Tree {
		Tree {
			buf: buf,
			len: len,
			last_symbol: last_symbol,
		}
	}

	pub fn insert(&mut self, code: &[bool], symbol: Symbol) {
		self.len += 1;
		self.last_symbol = Some(symbol);

		let insert_at_index = (1 << code.len()) - 1 + code.iter().fold(0, |acc, &bit| (acc << 1) + if bit { 1 } else { 0 });

		if insert_at_index > self.buf.len() - 1 {
			panic!("Index {:?} exceeds MAX_INDEX at insert (code = {:?})", insert_at_index, code);
		}

		self.buf[insert_at_index] = Some(symbol)
	}

	fn lookup<R: Read>(&self, r: &mut BitReader<R>) -> Result<Option<Symbol>, ::bitreader::BitReaderError> {
		let mut pseudo_code = 1;
		loop {
			pseudo_code = (pseudo_code << 1) + match r.read_bit_as_usize() {
				Ok(b) => b,
				Err(e) => return Err(e),
			};

			let lookup_index = pseudo_code - 1;

			if lookup_index > self.buf.len() - 1 {
				return Ok(None);
			}

			match self.buf[lookup_index] {
				Some(symbol) => return Ok(Some(symbol)),
				None => {},
			}
		}
	}

	pub fn lookup_symbol<R: Read>(&self, mut r: &mut BitReader<R>) -> Result<Option<Symbol>, ::bitreader::BitReaderError, >  {
		// println!("self.len = {:?}", self.len);

		match self.len {
			0 => Ok(None),
			1 => Ok(self.last_symbol),
			_ => self.lookup(&mut r),
		}
	}
}

mod tests {
	#[test]
	fn should_insert_and_lookup_first_level_leaf_on_left() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![0]));
		let mut tree = Tree::with_max_depth(1);
		tree.insert(&vec![false], 666);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
	}

	#[test]
	fn should_insert_and_lookup_first_level_leaf_on_right() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![1]));
		let mut tree = Tree::with_max_depth(1);
		tree.insert(&vec![true], 666);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
	}

	#[test]
	fn should_insert_first_level_leaf_on_left_then_on_right() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![2]));
		let mut tree = Tree::with_max_depth(1);
		tree.insert(&vec![false], 667);
		tree.insert(&vec![true], 666);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(667)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
	}

	#[test]
	fn should_insert_first_level_leaf_on_right_then_on_left() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![1]));
		let mut tree = Tree::with_max_depth(1);
		tree.insert(&vec![true], 666);
		tree.insert(&vec![false], 667);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(667)));
	}

	#[test]
	fn should_insert_second_level_leaf_left_right() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![2]));
		let mut tree = Tree::with_max_depth(2);
		tree.insert(&vec![false, true], 6666);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6666)));
	}

	#[test]
	fn should_insert_second_level_leaf_right_left() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![1]));
		let mut tree = Tree::with_max_depth(2);
		tree.insert(&vec![true, false], 6666);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6666)));
	}

	#[test]
	fn should_lookup_first_level_leaf_left() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![0b11001]));
		let mut tree = Tree::with_max_depth(2);
		tree.insert(&vec![true, false], 6666);
		tree.insert(&vec![false], 666);
		tree.insert(&vec![true, true], 6667);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6666)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6667)));
	}

	#[test]
	fn should_lookup_first_level_leaf_right() {
		use ::bitreader::BitReader;
		use super::Tree;
		use std::io::Cursor;

		let mut lookup_stream = BitReader::new(Cursor::new(vec![0b10100]));
		let mut tree = Tree::with_max_depth(2);
		tree.insert(&vec![false, false], 6666);
		tree.insert(&vec![true], 666);
		tree.insert(&vec![false, true], 6667);

		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6666)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(666)));
		assert_eq!(tree.lookup_symbol(&mut lookup_stream), Ok(Some(6667)));
	}
}
<|endoftext|>


<commit_before>//#![recursion_limit = "256"]
// http://stackoverflow.com/questions/25877285/how-to-disable-unused-code-warnings-in-rust
// https://users.rust-lang.org/t/turning-off-compiler-warning-messages/4975/2

mod api;
mod files;

use serde_derive::Serialize;

use dotenv;
use std::env;

use actix_web::{guard, middleware, web, App, Error as ActixError, HttpResponse, HttpServer};

use deadpool_postgres::{Manager, ManagerConfig, Pool, RecyclingMethod};
use tokio_postgres::NoTls;

#[macro_use]
extern crate horrorshow;
use horrorshow::helper::doctype;
use horrorshow::{RenderBox, Template};

static TEMPLATE: &str = "Hello {name}!";
#[derive(Serialize)]
struct Context {
    name: String,
}

#[derive(Serialize, Debug)]
struct TemplateContext {
    parent: String,
    name: String,
    content: String,
    items: Vec<String>,
}

use std::path;
use std::process::Command;

async fn template(ssr: web::Path<bool>) -> Result<HttpResponse, ActixError> {
    let s: String = if *ssr {
        let s2 = getStr();
        s2.to_owned()
    } else {
        "".to_owned()
    };

    let posts = vec![
        Post {
            title: String::from("First Post"),
            tags: vec![String::from("first post")],
            body: String::from("My Test Post"),
        },
        Post {
            title: String::from("Second Post"),
            tags: vec![],
            body: String::from("My Second Test Post"),
        },
    ];

    let doc_str = render("my blog", posts.into_iter(), &s.to_owned());

    Ok(HttpResponse::Ok().content_type("text/html").body(doc_str))
}

use std::fs;
use std::fs::OpenOptions;
use std::io::prelude::*;

fn getStr() -> String {
    fs::copy(
        "../client/src/elm/Main.elm",
        "../client/src/elm/Main.elm.bak",
    )
    .expect("file not copied");
    let stdout: Vec<u8>;
    {
        let mut main_file = OpenOptions::new()
            .append(true)
            .open("../client/src/elm/Main.elm")
            .expect("file not opened");

        let str1 = format!(
            r#"
            view : Html Msg
            view =
                viewWithModel <|
                    Model [] HomeRoute <|
                        Flags "" {time} ""
            "#,
            time = time::OffsetDateTime::unix_epoch().second()
        );

        main_file
            .write_all(str1.as_bytes())
            .expect("file content not saved");

        // npm i -g elm
        stdout = Command::new("node")
            .current_dir(&path::Path::new("../client"))
            .arg("./node_modules/elm-static-html/index.js")
            .arg("-f")
            .arg("src/elm/Main.elm")
            .output()
            .expect("elm-static-html command failed to start")
            .stdout;
    }
    fs::rename(
        "../client/src/elm/Main.elm.bak",
        "../client/src/elm/Main.elm",
    )
    .expect("file not renamed");

    println!("stdout: {:?}", stdout);

    String::from_utf8_lossy(&*stdout)
        .lines()
        .skip_while(|x| x.find(r#"id="content""#).is_none())
        .collect()
}

fn render_post(post: Post) -> Box<dyn RenderBox> {
    let Post { title, body, tags } = post;
    box_html! {
        article {
            header(class="post-header") {
                h1 : title;
                ul {
                    @ for tag in tags {
                        li : tag
                    }
                }
            }
            section(class="post-body") : body;
        }
    }
}

fn render<I: Iterator<Item = Post>>(title: &str, posts: I, elm_string: &str) -> String {
    (html! {
        : doctype::HTML;
        html {
            head {
                title : title
            }
            body {
                main {
                    header { h1 : title }
                    section(id="posts") {
                        @ for post in posts {
                            : render_post(post)
                        }
                    }
                    div: elm_string
                }
            }
        }
    })
    .into_string()
    .unwrap()
}

struct Post {
    title: String,
    tags: Vec<String>,
    body: String,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Error: NotPresent
    // Chaning to specific file, bc `strace ./target/debug/rustommerce` shown,
    // that dotenv searches up for .env till it reaches /
    // https://galenguyer.com/blog/2020/05/19/docker-rust-notpresent
    let my_path = env::current_dir().map(|a| a.join("../.env"))?;
    dotenv::from_path(my_path.as_path())?;

    env::set_var("RUST_LOG", "actix_web=info");
    env_logger::init();
    let endpoint = format!("127.0.0.1:{}", env::var("SERVER_PORT")?);

    let connection_string = format!(
        "postgres://{}:{}@{}:{}/{}",
        &env::var("DBUSER")?,
        &env::var("DBPASS")?,
        &env::var("DBHOST")?,
        &env::var("DBPORT")?,
        &env::var("DBNAME")?,
    );
    // Idea for parse from
    // https://github.com/OneSignal/L3-37/blob/2031639d1f3a7aa00a5a741b87b464e19d995d21/l337-postgres/src/lib.rs#L217
    let pg_config: tokio_postgres::Config = connection_string.parse()?;
    let mgr_config = ManagerConfig {
        recycling_method: RecyclingMethod::Fast,
    };
    let mgr = Manager::from_config(pg_config, NoTls, mgr_config);
    let pool = Pool::new(mgr, 16);

    let sys = actix_rt::System::new("app");
    HttpServer::new(move || {
        App::new()
            .data(pool.clone())
            .wrap(middleware::Logger::default())
            .service(web::resource("/template/{ssr}").route(web::get().to(template)))
            .service(web::resource("/userInformation").route(web::get().to(api::user_information)))
            .service(web::resource("/dataSets").route(web::get().to(api::data_sets)))
            .service(web::resource("/dataSets/{url}").route(web::get().to(api::data_set)))
            .service(
                web::resource("/dataSetsCategories")
                    .route(web::get().to(api::data_sets_categories)),
            )
            .service(
                web::resource("/dataSetsCategories/{url}")
                    .route(web::get().to(api::data_set_category)),
            )
            .service(web::resource("/favicon").route(web::get().to(files::favicon)))
            .service(web::resource("/styles/{file:.*}").route(web::get().to(files::styles)))
            .service(web::resource("/js/{file:.*}").route(web::get().to(files::js)))
            .default_service(
                // 404 for GET request
                web::resource("")
                    .route(web::get().to(files::index))
                    // all requests that are not `GET`
                    .route(
                        web::route()
                            .guard(guard::Not(guard::Get()))
                            .to(HttpResponse::MethodNotAllowed),
                    ),
            )
    })
    .bind(&endpoint)?
    .run();
    // If you do not return `Ok(())` but just `.run()`, this will happend:
    // When main returns `Result<(), Box<dyn std::error::Error + 'static + Send + Sync>> instead of
    // `io::Result<()>`, there is error and `into()` is needed.
    // expected struct `std::boxed::Box`, found struct `std::io::Error`
    // https://users.rust-lang.org/t/boxing-errors-in-result-throws-type-mismatch/36692/2
    //.map_err(|e| e.into())

    println!("Server running at {:?}", endpoint);
    let _ = sys.run();

    Ok(())
}
<commit_msg>server: remove generation with elm-static-html as it does not support elm-0.19<commit_after>//#![recursion_limit = "256"]
// http://stackoverflow.com/questions/25877285/how-to-disable-unused-code-warnings-in-rust
// https://users.rust-lang.org/t/turning-off-compiler-warning-messages/4975/2

mod api;
mod files;

use serde_derive::Serialize;

use dotenv;
use std::env;

use actix_web::{guard, middleware, web, App, Error as ActixError, HttpResponse, HttpServer};

use deadpool_postgres::{Manager, ManagerConfig, Pool, RecyclingMethod};
use tokio_postgres::NoTls;

#[macro_use]
extern crate horrorshow;
use horrorshow::helper::doctype;
use horrorshow::{RenderBox, Template};

static TEMPLATE: &str = "Hello {name}!";
#[derive(Serialize)]
struct Context {
    name: String,
}

#[derive(Serialize, Debug)]
struct TemplateContext {
    parent: String,
    name: String,
    content: String,
    items: Vec<String>,
}

use std::path;
use std::process::Command;

async fn template(ssr: web::Path<bool>) -> Result<HttpResponse, ActixError> {
    let s: String = if *ssr {
        "true".to_owned()
    } else {
        "false".to_owned()
    };

    let posts = vec![
        Post {
            title: String::from("First Post"),
            tags: vec![String::from("first post")],
            body: String::from("My Test Post"),
        },
        Post {
            title: String::from("Second Post"),
            tags: vec![],
            body: String::from("My Second Test Post"),
        },
    ];

    let doc_str = render("my blog", posts.into_iter(), &s.to_owned());

    Ok(HttpResponse::Ok().content_type("text/html").body(doc_str))
}

fn render_post(post: Post) -> Box<dyn RenderBox> {
    let Post { title, body, tags } = post;
    box_html! {
        article {
            header(class="post-header") {
                h1 : title;
                ul {
                    @ for tag in tags {
                        li : tag
                    }
                }
            }
            section(class="post-body") : body;
        }
    }
}

fn render<I: Iterator<Item = Post>>(title: &str, posts: I, elm_string: &str) -> String {
    (html! {
        : doctype::HTML;
        html {
            head {
                title : title
            }
            body {
                main {
                    header { h1 : title }
                    section(id="posts") {
                        @ for post in posts {
                            : render_post(post)
                        }
                    }
                    div: elm_string
                }
            }
        }
    })
    .into_string()
    .unwrap()
}

struct Post {
    title: String,
    tags: Vec<String>,
    body: String,
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Error: NotPresent
    // Chaning to specific file, bc `strace ./target/debug/rustommerce` shown,
    // that dotenv searches up for .env till it reaches /
    // https://galenguyer.com/blog/2020/05/19/docker-rust-notpresent
    let my_path = env::current_dir().map(|a| a.join("../.env"))?;
    dotenv::from_path(my_path.as_path())?;

    env::set_var("RUST_LOG", "actix_web=info");
    env_logger::init();
    let endpoint = format!("127.0.0.1:{}", env::var("SERVER_PORT")?);

    let connection_string = format!(
        "postgres://{}:{}@{}:{}/{}",
        &env::var("DBUSER")?,
        &env::var("DBPASS")?,
        &env::var("DBHOST")?,
        &env::var("DBPORT")?,
        &env::var("DBNAME")?,
    );
    // Idea for parse from
    // https://github.com/OneSignal/L3-37/blob/2031639d1f3a7aa00a5a741b87b464e19d995d21/l337-postgres/src/lib.rs#L217
    let pg_config: tokio_postgres::Config = connection_string.parse()?;
    let mgr_config = ManagerConfig {
        recycling_method: RecyclingMethod::Fast,
    };
    let mgr = Manager::from_config(pg_config, NoTls, mgr_config);
    let pool = Pool::new(mgr, 16);

    let sys = actix_rt::System::new("app");
    HttpServer::new(move || {
        App::new()
            .data(pool.clone())
            .wrap(middleware::Logger::default())
            .service(web::resource("/template/{ssr}").route(web::get().to(template)))
            .service(web::resource("/userInformation").route(web::get().to(api::user_information)))
            .service(web::resource("/dataSets").route(web::get().to(api::data_sets)))
            .service(web::resource("/dataSets/{url}").route(web::get().to(api::data_set)))
            .service(
                web::resource("/dataSetsCategories")
                    .route(web::get().to(api::data_sets_categories)),
            )
            .service(
                web::resource("/dataSetsCategories/{url}")
                    .route(web::get().to(api::data_set_category)),
            )
            .service(web::resource("/favicon").route(web::get().to(files::favicon)))
            .service(web::resource("/styles/{file:.*}").route(web::get().to(files::styles)))
            .service(web::resource("/js/{file:.*}").route(web::get().to(files::js)))
            .default_service(
                // 404 for GET request
                web::resource("")
                    .route(web::get().to(files::index))
                    // all requests that are not `GET`
                    .route(
                        web::route()
                            .guard(guard::Not(guard::Get()))
                            .to(HttpResponse::MethodNotAllowed),
                    ),
            )
    })
    .bind(&endpoint)?
    .run();
    // If you do not return `Ok(())` but just `.run()`, this will happend:
    // When main returns `Result<(), Box<dyn std::error::Error + 'static + Send + Sync>> instead of
    // `io::Result<()>`, there is error and `into()` is needed.
    // expected struct `std::boxed::Box`, found struct `std::io::Error`
    // https://users.rust-lang.org/t/boxing-errors-in-result-throws-type-mismatch/36692/2
    //.map_err(|e| e.into())

    println!("Server running at {:?}", endpoint);
    let _ = sys.run();

    Ok(())
}
<|endoftext|>


<commit_before>use self::Color::*;
use self::Rank::*;
use std::slice::Iter;
use std::fmt;

extern crate rand;
use self::rand::{thread_rng, Rng};

#[derive(Copy, Clone)]
enum Color
{
    Spades,   // ♠,
    Hearts,   // ♥,
    Diamonds, // ♦,
    Clubs,    // ♣
}

#[derive(Copy, Clone)]
enum Rank
{
    A     = 1,
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    J,
    Q,
    K
}

impl Color
{
    // https://stackoverflow.com/a/21376984
    fn iterator () -> Iter<'static, Color>
    {
        static COLORS: [Color; 4] = [Spades, Hearts, Diamonds, Clubs];
        COLORS.into_iter()
    }
}

impl fmt::Display for Color
{
    // https://stackoverflow.com/a/45893535
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        match *self
        {
            Spades => write!(f, "♠"),
            Hearts => write!(f, "♥"),
            Diamonds => write!(f, "♦"),
            Clubs => write!(f, "♣"),
        }
    }
}

impl Rank
{
    fn iterator () -> Iter<'static, Rank>
    {
        static RANKS: [Rank; 12] =
            [ A, Two, Three, Four, Five, Six, Seven, Eight, Nine, J, Q, K ] ;
        RANKS.into_iter()
    }
}

impl fmt::Display for Rank
{
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        match *self
        {
            A     => write!(f, "A"),
            Two   => write!(f, "2"),
            Three => write!(f, "3"),
            Four  => write!(f, "4"),
            Five  => write!(f, "5"),
            Six   => write!(f, "6"),
            Seven => write!(f, "7"),
            Eight => write!(f, "8"),
            Nine  => write!(f, "9"),
            J     => write!(f, "J"),
            Q     => write!(f, "Q"),
            K     => write!(f, "K"),
        }
    }
}

struct Card
{
    color:     Color,
    rank:      Rank,
    id:        u8,
    facing_up: bool
}

fn main ()
{
    let mut all_cards: Vec<Card> = Vec::new();

    let ids_available: Vec<u8> = (0..51).collect();

    for color in Color::iterator()
    {
        for rank in Rank::iterator()
        {
            let curr_id: u8;

            curr_id = 0;

            let card = Card
            {
                color:     *color,
                rank:      *rank,
                id:        curr_id,
                facing_up: false
            };

            all_cards.push(card);
        }
    }

    for card in all_cards.iter()
    {
        println!("{}{} {} {}",
                 card.color, card.rank, card.id, card.facing_up);
    }
}
<commit_msg>Add copyright notice to server source.<commit_after>/*
 * Copyright (c) 2017 Erik Nordstrøm <erik@nordstroem.no>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

use self::Color::*;
use self::Rank::*;
use std::slice::Iter;
use std::fmt;

extern crate rand;
use self::rand::{thread_rng, Rng};

#[derive(Copy, Clone)]
enum Color
{
    Spades,   // ♠,
    Hearts,   // ♥,
    Diamonds, // ♦,
    Clubs,    // ♣
}

#[derive(Copy, Clone)]
enum Rank
{
    A     = 1,
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    J,
    Q,
    K
}

impl Color
{
    // https://stackoverflow.com/a/21376984
    fn iterator () -> Iter<'static, Color>
    {
        static COLORS: [Color; 4] = [Spades, Hearts, Diamonds, Clubs];
        COLORS.into_iter()
    }
}

impl fmt::Display for Color
{
    // https://stackoverflow.com/a/45893535
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        match *self
        {
            Spades => write!(f, "♠"),
            Hearts => write!(f, "♥"),
            Diamonds => write!(f, "♦"),
            Clubs => write!(f, "♣"),
        }
    }
}

impl Rank
{
    fn iterator () -> Iter<'static, Rank>
    {
        static RANKS: [Rank; 12] =
            [ A, Two, Three, Four, Five, Six, Seven, Eight, Nine, J, Q, K ] ;
        RANKS.into_iter()
    }
}

impl fmt::Display for Rank
{
    fn fmt (&self, f: &mut fmt::Formatter) -> fmt::Result
    {
        match *self
        {
            A     => write!(f, "A"),
            Two   => write!(f, "2"),
            Three => write!(f, "3"),
            Four  => write!(f, "4"),
            Five  => write!(f, "5"),
            Six   => write!(f, "6"),
            Seven => write!(f, "7"),
            Eight => write!(f, "8"),
            Nine  => write!(f, "9"),
            J     => write!(f, "J"),
            Q     => write!(f, "Q"),
            K     => write!(f, "K"),
        }
    }
}

struct Card
{
    color:     Color,
    rank:      Rank,
    id:        u8,
    facing_up: bool
}

fn main ()
{
    let mut all_cards: Vec<Card> = Vec::new();

    let ids_available: Vec<u8> = (0..51).collect();

    for color in Color::iterator()
    {
        for rank in Rank::iterator()
        {
            let curr_id: u8;

            curr_id = 0;

            let card = Card
            {
                color:     *color,
                rank:      *rank,
                id:        curr_id,
                facing_up: false
            };

            all_cards.push(card);
        }
    }

    for card in all_cards.iter()
    {
        println!("{}{} {} {}",
                 card.color, card.rank, card.id, card.facing_up);
    }
}
<|endoftext|>


<commit_before>extern crate libc;
use self::libc::{uint32_t, c_void, c_int};

extern crate errno;
use self::errno::errno;

use std::str;

// Since we cannot access C macros for constants from Rust - I have had to redefine this, based on Apple's source code
// See http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c
// buffersize must be more than PROC_PIDPATHINFO_SIZE
// buffersize must be less than PROC_PIDPATHINFO_MAXSIZE
//
// See http://opensource.apple.com//source/xnu/xnu-1456.1.26/bsd/sys/proc_info.h
// #define PROC_PIDPATHINFO_SIZE		(MAXPATHLEN)
// #define PROC_PIDPATHINFO_MAXSIZE	(4*MAXPATHLEN)
// in http://opensource.apple.com//source/xnu/xnu-1504.7.4/bsd/sys/param.h
// #define	MAXPATHLEN	PATH_MAX
// in https://opensource.apple.com/source/xnu/xnu-792.25.20/bsd/sys/syslimits.h
// #define	PATH_MAX		 1024
const MAXPATHLEN : usize = 1024;
const PROC_PIDPATHINFO_MAXSIZE : usize = 4 * MAXPATHLEN;

// this extern block links to the libproc library
#[link(name="proc", kind="dylib")]
extern {
    // Original signatures from http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c

    // int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize)

    // int proc_pidinfo(int pid, int flavor, uint64_t arg,  void *buffer, int buffersize)

    // int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize)

    // int proc_name(int pid, void * buffer, uint32_t buffersize)

    // int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize)

    // int proc_kmsgbuf(void * buffer, uint32_t  buffersize)

    // int proc_pidpath(int pid, void * buffer, uint32_t  buffersize)
    fn proc_pidpath(pid: c_int, buffer: *mut c_void, buffersize : uint32_t) -> c_int;

    // int proc_libversion(int *major, int * minor)
    // return value of 0 indicates success (inconsistent :-( )
    fn proc_libversion(major : *mut c_int, minor : * mut c_int) -> c_int;
}

fn get_errno_with_message(ret : i32) -> String {
    let e = errno();
    let code = e.0 as i32;
    format!("return code = {}, errno = {}, message = '{}'", ret, code, e)
}

pub fn pidpath(pid : i32) -> Result<String, String> {
    let pathbuf : Vec<u8>= Vec::with_capacity(PROC_PIDPATHINFO_MAXSIZE - 1);

    let buffer_ptr = pathbuf.as_ptr() as *mut c_void;
    let buffer_size = pathbuf.capacity() as u32;

    let ret : i32;
    let rebuilt : Vec<u8>;

    unsafe {
        ret = proc_pidpath(pid, buffer_ptr, buffer_size);
        rebuilt = Vec::from_raw_parts(buffer_ptr as *mut u8, ret as usize, buffer_size as usize);
    };

    if ret <= 0 {
        Err(get_errno_with_message(ret))
    } else {
        match String::from_utf8(rebuilt) {
            Ok(path) => Ok(path),
            Err(e) => Err(format!("Invalid UTF-8 sequence: {}", e))
        }
    }
}

pub fn libversion() -> Result<(i32, i32), String> {
    let mut major = 0;
    let mut minor = 0;
    let ret : i32;

    unsafe {
        ret = proc_libversion(&mut major, &mut minor);
    };

    if ret == 0 {
        Ok((major, minor))
    } else {
        Err(get_errno_with_message(ret))
    }
}

#[test]
fn libversion_test() {
    match libversion() {
        Ok((major, minor)) => {
            // run tests with 'cargo test -- --nocapture' to see the test output
            println!("Major = {}, Minor = {}", major, minor);
        },
        Err(message) => assert!(false, message)
    }
}<commit_msg>Added 2 unit tests for pidpath() function.<commit_after>extern crate libc;
use self::libc::{uint32_t, c_void, c_int};

extern crate errno;
use self::errno::errno;

use std::str;

// Since we cannot access C macros for constants from Rust - I have had to redefine this, based on Apple's source code
// See http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c
// buffersize must be more than PROC_PIDPATHINFO_SIZE
// buffersize must be less than PROC_PIDPATHINFO_MAXSIZE
//
// See http://opensource.apple.com//source/xnu/xnu-1456.1.26/bsd/sys/proc_info.h
// #define PROC_PIDPATHINFO_SIZE		(MAXPATHLEN)
// #define PROC_PIDPATHINFO_MAXSIZE	(4*MAXPATHLEN)
// in http://opensource.apple.com//source/xnu/xnu-1504.7.4/bsd/sys/param.h
// #define	MAXPATHLEN	PATH_MAX
// in https://opensource.apple.com/source/xnu/xnu-792.25.20/bsd/sys/syslimits.h
// #define	PATH_MAX		 1024
const MAXPATHLEN : usize = 1024;
const PROC_PIDPATHINFO_MAXSIZE : usize = 4 * MAXPATHLEN;

// this extern block links to the libproc library
#[link(name="proc", kind="dylib")]
extern {
    // Original signatures from http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c

    // int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize)

    // int proc_pidinfo(int pid, int flavor, uint64_t arg,  void *buffer, int buffersize)

    // int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize)

    // int proc_name(int pid, void * buffer, uint32_t buffersize)

    // int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize)

    // int proc_kmsgbuf(void * buffer, uint32_t  buffersize)

    // int proc_pidpath(int pid, void * buffer, uint32_t  buffersize)
    fn proc_pidpath(pid: c_int, buffer: *mut c_void, buffersize : uint32_t) -> c_int;

    // int proc_libversion(int *major, int * minor)
    // return value of 0 indicates success (inconsistent :-( )
    fn proc_libversion(major : *mut c_int, minor : * mut c_int) -> c_int;
}

fn get_errno_with_message(ret : i32) -> String {
    let e = errno();
    let code = e.0 as i32;
    format!("return code = {}, errno = {}, message = '{}'", ret, code, e)
}

pub fn pidpath(pid : i32) -> Result<String, String> {
    let pathbuf : Vec<u8>= Vec::with_capacity(PROC_PIDPATHINFO_MAXSIZE - 1);

    let buffer_ptr = pathbuf.as_ptr() as *mut c_void;
    let buffer_size = pathbuf.capacity() as u32;

    let ret : i32;
    let rebuilt : Vec<u8>;

    unsafe {
        ret = proc_pidpath(pid, buffer_ptr, buffer_size);
        rebuilt = Vec::from_raw_parts(buffer_ptr as *mut u8, ret as usize, buffer_size as usize);
    };

    if ret <= 0 {
        Err(get_errno_with_message(ret))
    } else {
        match String::from_utf8(rebuilt) {
            Ok(path) => Ok(path),
            Err(e) => Err(format!("Invalid UTF-8 sequence: {}", e))
        }
    }
}

#[test]
// This checks that it can find the path of the init process with PID 1
fn pidpath_test_init_pid() {
    match pidpath(1) {
        // run tests with 'cargo test -- --nocapture' to see the test output
        Ok(path) => println!("Path of init process PID = 1 is '{}'", path),
        Err(message) => assert!(true, message)
    }
}

#[test]
#[should_panic]
// This checks that it cannot find the path of the process with pid -1
fn pidpath_test_unknown_pid() {
    match pidpath(-1) {
        // run tests with 'cargo test -- --nocapture' to see the test output
        Ok(path) => assert!(false, "It found the path of process Pwith ID = -1 (path = {}), that's not possible\n", path),
        Err(message) => assert!(false, message)
    }
}

pub fn libversion() -> Result<(i32, i32), String> {
    let mut major = 0;
    let mut minor = 0;
    let ret : i32;

    unsafe {
        ret = proc_libversion(&mut major, &mut minor);
    };

    if ret == 0 {
        Ok((major, minor))
    } else {
        Err(get_errno_with_message(ret))
    }
}

#[test]
fn libversion_test() {
    match libversion() {
        Ok((major, minor)) => {
            // run tests with 'cargo test -- --nocapture' to see the test output
            println!("Major = {}, Minor = {}", major, minor);
        },
        Err(message) => assert!(false, message)
    }
}<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>Example of using string slices<commit_after>fn main() {
    let s = String::from("Hello there");

    let first = first_word(&s);
    println!("First word is: {}", first);
}

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s[..i];
        }
    }

    &s[..]
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;
use std::fmt;
use std::iter::{FromIterator, IntoIterator};
use std::str::FromStr;
use std::vec::IntoIter;

use error::{Error, Result};

pub fn parse_key_value(s: &str) -> Result<HashMap<String, String>> {
    Ok(HashMap::from_iter(s.lines()
                              .map(|l| l.splitn(2, '=').collect::<Vec<_>>())
                              .map(|kv| (kv[0].to_string(), kv[1].to_string()))))
}

#[derive(Debug)]
pub struct Bind {
    pub service: String,
    pub exports: Vec<String>,
}

impl FromStr for Bind {
    type Err = Error;

    fn from_str(line: &str) -> Result<Self> {
        let mut parts = line.split('=');
        let service = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(service) => service.to_string(),
        };
        let exports = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(exports) => exports.split(' ').map(|t| t.to_string()).collect(),
        };
        Ok(Bind {
               service: service,
               exports: exports,
           })
    }
}

#[derive(Debug, PartialEq)]
pub struct EnvVar {
    pub key: String,
    pub value: String,
    pub separator: Option<char>,
}

#[derive(Debug)]
pub struct EnvVars {
    inner: Vec<EnvVar>,
}

impl EnvVars {
    pub fn new(values: HashMap<String, String>, separators: HashMap<String, String>) -> Self {
        Self {
            inner: values
                .into_iter()
                .map(|(key, value)| if let Some(sep) = separators.get(&key) {
                         EnvVar {
                             key,
                             value,
                             separator: sep.to_owned().pop(),
                         }
                     } else {
                         EnvVar {
                             key,
                             value,
                             separator: None,
                         }
                     })
                .collect(),
        }
    }
}

impl IntoIterator for EnvVars {
    type Item = EnvVar;
    type IntoIter = IntoIter<EnvVar>;

    fn into_iter(self) -> Self::IntoIter {
        self.inner.into_iter()
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum MetaFile {
    Binds,
    BindsOptional,
    CFlags,
    Config,
    Deps,
    TDeps,
    Environment,
    EnvironmentSep,
    Exports,
    Exposes,
    Ident,
    LdRunPath,
    LdFlags,
    Manifest,
    Path,
    SvcUser,
    SvcGroup,
    Target,
}

impl fmt::Display for MetaFile {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let id = match *self {
            MetaFile::Binds => "BINDS",
            MetaFile::BindsOptional => "BINDS_OPTIONAL",
            MetaFile::CFlags => "CFLAGS",
            MetaFile::Config => "default.toml",
            MetaFile::Deps => "DEPS",
            MetaFile::TDeps => "TDEPS",
            MetaFile::Environment => "ENVIRONMENT",
            MetaFile::EnvironmentSep => "ENVIRONMENT_SEP",
            MetaFile::Exports => "EXPORTS",
            MetaFile::Exposes => "EXPOSES",
            MetaFile::Ident => "IDENT",
            MetaFile::LdRunPath => "LD_RUN_PATH",
            MetaFile::LdFlags => "LDFLAGS",
            MetaFile::Manifest => "MANIFEST",
            MetaFile::Path => "PATH",
            MetaFile::SvcUser => "SVC_USER",
            MetaFile::SvcGroup => "SVC_GROUP",
            MetaFile::Target => "TARGET",
        };
        write!(f, "{}", id)
    }
}

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

    static ENVIRONMENT: &str = r#"PATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin
PYTHONPATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages
"#;
    static ENVIRONMENT_SEP: &str = r#"PATH=:
PYTHONPATH=:
"#;

    #[test]
    #[should_panic]
    fn malformed_file() {
        parse_key_value(&"PATH").unwrap();
    }

    #[test]
    fn can_parse_environment_file() {
        let mut m: HashMap<String, String> = HashMap::new();
        m.insert("PATH".to_string(),
                 "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string());
        m.insert("PYTHONPATH".to_string(),
                 "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages"
                     .to_string());

        assert_eq!(parse_key_value(&ENVIRONMENT).unwrap(), m);
    }

    #[test]
    fn can_parse_environment_sep_file() {
        let mut m: HashMap<String, String> = HashMap::new();
        m.insert("PATH".to_string(), ":".to_string());
        m.insert("PYTHONPATH".to_string(), ":".to_string());

        assert_eq!(parse_key_value(&ENVIRONMENT_SEP).unwrap(), m);
    }

    #[test]
    fn new_env_vars() {
        let mut result = EnvVars::new(parse_key_value(&ENVIRONMENT).unwrap(),
                                      parse_key_value(&ENVIRONMENT_SEP).unwrap())
                .into_iter()
                .collect::<Vec<_>>();
        // Sort the result by key, so we have a guarantee of order
        result.sort_by_key(|v| v.key.to_owned());

        let expected =
            vec![EnvVar {
                     key: "PATH".to_string(),
                     value: "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string(),
                     separator: Some(':'),
                 },
                 EnvVar {
                     key: "PYTHONPATH".to_string(),
                     value: "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages"
                         .to_string(),
                     separator: Some(':'),
                 }];

        assert_eq!(result, expected);
    }
}
<commit_msg>Add test can_parse_exports_file<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;
use std::fmt;
use std::iter::{FromIterator, IntoIterator};
use std::str::FromStr;
use std::vec::IntoIter;

use error::{Error, Result};

pub fn parse_key_value(s: &str) -> Result<HashMap<String, String>> {
    Ok(HashMap::from_iter(s.lines()
                              .map(|l| l.splitn(2, '=').collect::<Vec<_>>())
                              .map(|kv| (kv[0].to_string(), kv[1].to_string()))))
}

#[derive(Debug)]
pub struct Bind {
    pub service: String,
    pub exports: Vec<String>,
}

impl FromStr for Bind {
    type Err = Error;

    fn from_str(line: &str) -> Result<Self> {
        let mut parts = line.split('=');
        let service = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(service) => service.to_string(),
        };
        let exports = match parts.next() {
            None => return Err(Error::MetaFileBadBind),
            Some(exports) => exports.split(' ').map(|t| t.to_string()).collect(),
        };
        Ok(Bind {
               service: service,
               exports: exports,
           })
    }
}

#[derive(Debug, PartialEq)]
pub struct EnvVar {
    pub key: String,
    pub value: String,
    pub separator: Option<char>,
}

#[derive(Debug)]
pub struct EnvVars {
    inner: Vec<EnvVar>,
}

impl EnvVars {
    pub fn new(values: HashMap<String, String>, separators: HashMap<String, String>) -> Self {
        Self {
            inner: values
                .into_iter()
                .map(|(key, value)| if let Some(sep) = separators.get(&key) {
                         EnvVar {
                             key,
                             value,
                             separator: sep.to_owned().pop(),
                         }
                     } else {
                         EnvVar {
                             key,
                             value,
                             separator: None,
                         }
                     })
                .collect(),
        }
    }
}

impl IntoIterator for EnvVars {
    type Item = EnvVar;
    type IntoIter = IntoIter<EnvVar>;

    fn into_iter(self) -> Self::IntoIter {
        self.inner.into_iter()
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum MetaFile {
    Binds,
    BindsOptional,
    CFlags,
    Config,
    Deps,
    TDeps,
    Environment,
    EnvironmentSep,
    Exports,
    Exposes,
    Ident,
    LdRunPath,
    LdFlags,
    Manifest,
    Path,
    SvcUser,
    SvcGroup,
    Target,
}

impl fmt::Display for MetaFile {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let id = match *self {
            MetaFile::Binds => "BINDS",
            MetaFile::BindsOptional => "BINDS_OPTIONAL",
            MetaFile::CFlags => "CFLAGS",
            MetaFile::Config => "default.toml",
            MetaFile::Deps => "DEPS",
            MetaFile::TDeps => "TDEPS",
            MetaFile::Environment => "ENVIRONMENT",
            MetaFile::EnvironmentSep => "ENVIRONMENT_SEP",
            MetaFile::Exports => "EXPORTS",
            MetaFile::Exposes => "EXPOSES",
            MetaFile::Ident => "IDENT",
            MetaFile::LdRunPath => "LD_RUN_PATH",
            MetaFile::LdFlags => "LDFLAGS",
            MetaFile::Manifest => "MANIFEST",
            MetaFile::Path => "PATH",
            MetaFile::SvcUser => "SVC_USER",
            MetaFile::SvcGroup => "SVC_GROUP",
            MetaFile::Target => "TARGET",
        };
        write!(f, "{}", id)
    }
}

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

    static ENVIRONMENT: &str = r#"PATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin
PYTHONPATH=/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages
"#;
    static ENVIRONMENT_SEP: &str = r#"PATH=:
PYTHONPATH=:
"#;
    static EXPORTS: &str = r#"status-port=status.port
port=front-end.port
"#;

    #[test]
    #[should_panic]
    fn malformed_file() {
        parse_key_value(&"PATH").unwrap();
    }

    #[test]
    fn can_parse_environment_file() {
        let mut m: HashMap<String, String> = HashMap::new();
        m.insert("PATH".to_string(),
                 "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string());
        m.insert("PYTHONPATH".to_string(),
                 "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages"
                     .to_string());

        assert_eq!(parse_key_value(&ENVIRONMENT).unwrap(), m);
    }

    #[test]
    fn can_parse_environment_sep_file() {
        let mut m: HashMap<String, String> = HashMap::new();
        m.insert("PATH".to_string(), ":".to_string());
        m.insert("PYTHONPATH".to_string(), ":".to_string());

        assert_eq!(parse_key_value(&ENVIRONMENT_SEP).unwrap(), m);
    }

    #[test]
    fn can_parse_exports_file() {
        let mut m: HashMap<String, String> = HashMap::new();
        m.insert("status-port".to_string(), "status.port".to_string());
        m.insert("port".to_string(), "front-end.port".to_string());

        assert_eq!(parse_key_value(&EXPORTS).unwrap(), m);
    }

    #[test]
    fn new_env_vars() {
        let mut result = EnvVars::new(parse_key_value(&ENVIRONMENT).unwrap(),
                                      parse_key_value(&ENVIRONMENT_SEP).unwrap())
                .into_iter()
                .collect::<Vec<_>>();
        // Sort the result by key, so we have a guarantee of order
        result.sort_by_key(|v| v.key.to_owned());

        let expected =
            vec![EnvVar {
                     key: "PATH".to_string(),
                     value: "/hab/pkgs/python/setuptools/35.0.1/20170424072606/bin".to_string(),
                     separator: Some(':'),
                 },
                 EnvVar {
                     key: "PYTHONPATH".to_string(),
                     value: "/hab/pkgs/python/setuptools/35.0.1/20170424072606/lib/python3.6/site-packages"
                         .to_string(),
                     separator: Some(':'),
                 }];

        assert_eq!(result, expected);
    }
}
<|endoftext|>


<commit_before>//! Parse server.properties files

use std::fs::File;
use std::io::prelude::*;
use std::io::{self, BufReader, BufWriter};
use std::num::ParseIntError;
use std::path::Path;
use std::str::ParseBoolError;

macro_rules! parse {
    ($value:ident, String) => {
        $value.to_string()
    };
    ($value:ident, bool) => {
        try!($value.parse().map_err(|_: ParseBoolError| io::Error::new(io::ErrorKind::InvalidInput, "invalid bool value")))
    };
    ($value:ident, i32) => {
        try!($value.parse().map_err(|_: ParseIntError| io::Error::new(io::ErrorKind::InvalidInput, "invalid i32 value")))
    };
    ($value:ident, u16) => {
        try!($value.parse().map_err(|_: ParseIntError| io::Error::new(io::ErrorKind::InvalidInput, "invalid u16 value")))
    }
}

macro_rules! server_properties_impl {
    ($({ $field:ident, $hyphen:expr, $fty:ident, $default:expr})+) => {
        /// Vanilla server.properties
        ///
        /// Documentation of each filed here: http://minecraft.gamepedia.com/Server.properties
        #[derive(Debug)]
        pub struct Properties {
            $(pub $field: $fty),*
        }

        impl Properties {
            pub fn default() -> Properties {
                Properties{
                    $($field: $default),*
                }
            }

            /// Load and parse a server.properties file from `path`,
            pub fn load(path: &Path) -> io::Result<Properties> {
                let mut p = Properties::default();
                let file = try!(File::open(path));
                let file = BufReader::new(file);
                for line in file.lines().map(|l| l.unwrap()) {
                    // Ignore comment lines
                    if line.trim().starts_with("#") {
                        continue
                    }
                    let parts: Vec<&str> = line.trim().splitn(2, '=').collect();
                    let (prop, value) = (parts[0], parts[1]);
                    match prop {
                        $($hyphen => p.$field = parse!(value, $fty),)*
                        prop => println!("Unknown property {}", prop)
                    }
                }
                Ok(p)
            }

            /// Saves a server.properties file into `path`. It creates the
            /// file if it does not exist, and will truncate it if it does.
            pub fn save(&self, path: &Path) -> io::Result<()> {
                let file = try!(File::create(path));
                let mut file = BufWriter::new(file);
                // Header
                try!(write!(&mut file, "#Minecraft server properties"));
                try!(write!(&mut file, "#(File modification datestamp)"));
                // Body. Vanilla MC does write 37 out of 40 properties by default, it
                // only writes the 3 left if they are not using default values. It
                // also writes them unsorted (possibly because they are stored in a
                // HashMap).
                $(try!(write!(&mut file, "{}={}\n", $hyphen, self.$field));)*
                Ok(())
            }
        }

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

            #[test]
            fn decode_default() {
                let props = Properties::default();
                $(assert_eq!(props.$field, $default));*
            }
        }
    }
}

server_properties_impl! {
    { allow_flight, "allow-flight", bool, false }
    { allow_nether, "allow-nether", bool, true }
    { announce_player_achievements, "announce-player-achievements", bool, true }
    { difficulty, "difficulty", i32, 1 }
    { enable_query, "enable-query", bool, false }
    { enable_rcon, "enable-rcon", bool, false }
    { enable_command_block, "enable-command-block", bool, false }
    { force_gamemode, "force-gamemode", bool, false }
    { gamemode, "gamemode", i32, 0 }
    { generate_structures, "generate-structures", bool, true }
    { generator_settings, "generator-settings", String, "".to_string() }
    { hardcore, "hardcore", bool, false }
    { level_name, "level-name", String, "world".to_string() }
    { level_seed, "level-seed", String, "".to_string() }
    { level_type, "level-type", String, "DEFAULT".to_string() }
    { max_build_height, "max-build-height", i32, 256 }
    { max_players, "max-players", i32, 20 }
    { max_tick_time, "max-tick-time", i32, 60000 }
    { max_world_size, "max-world-size", i32, 29999984 }
    { motd, "motd", String, "A Minecraft Server".to_string() }
    { network_compression_threshold, "network-compression-threshold", i32, 256 }
    { online_mode, "online-mode", bool, true }
    { op_permission_level, "op-permission-level", i32, 4 }
    { player_idle_timeout, "player-idle-timeout", i32, 0 }
    { pvp, "pvp", bool, true }
    { query_port, "query.port", i32, 25565 }
    { rcon_password, "rcon.password", String, "".to_string() }
    { rcon_port, "rcon.port", i32, 25575 }
    { resource_pack, "resource-pack", String, "".to_string() }
    { resource_pack_hash, "resource-pack-hash", String, "".to_string() }
    { server_ip, "server-ip", String, "".to_string() }
    { server_port, "server-port", u16, 25565 }
    { snooper_enabled, "snooper-enabled", bool, true }
    { spawn_animals, "spawn-animals", bool, true }
    { spawn_monsters, "spawn-monsters", bool, true }
    { spawn_npcs, "spawn-npcs", bool, true }
    { spawn_protection, "spawn-protection", i32, 16 }
    { use_native_transport, "use-native-transport", bool, true }
    { view_distance, "view-distance", i32, 10 }
    { white_list, "white-list", bool, false }
}
<commit_msg>Provide proper tests for server.properties<commit_after>//! Parse server.properties files

use std::fs::File;
use std::io::prelude::*;
use std::io::{self, BufReader, BufWriter, Error, ErrorKind};
use std::num::ParseIntError;
use std::path::Path;
use std::str::ParseBoolError;

macro_rules! parse {
    ($value:ident, String) => {
        $value.to_string()
    };
    ($value:ident, bool) => {
        try!($value.parse().map_err(|_: ParseBoolError| io::Error::new(io::ErrorKind::InvalidInput, "invalid bool value")))
    };
    ($value:ident, i32) => {
        try!($value.parse().map_err(|_: ParseIntError| io::Error::new(io::ErrorKind::InvalidInput, "invalid i32 value")))
    };
    ($value:ident, u16) => {
        try!($value.parse().map_err(|_: ParseIntError| io::Error::new(io::ErrorKind::InvalidInput, "invalid u16 value")))
    }
}

macro_rules! server_properties_impl {
    ($({ $field:ident, $hyphen:expr, $fty:ident, $default:expr})+) => {
        /// Vanilla server.properties
        ///
        /// Documentation of each filed here: http://minecraft.gamepedia.com/Server.properties
        #[derive(Debug, PartialEq)]
        pub struct Properties {
            $(pub $field: $fty),*
        }

        impl Properties {
            pub fn default() -> Properties {
                Properties{
                    $($field: $default),*
                }
            }

            /// Load and parse a server.properties file from `path`,
            pub fn load(path: &Path) -> io::Result<Properties> {
                let mut p = Properties::default();
                let file = try!(File::open(path));
                let file = BufReader::new(file);
                for line in file.lines().map(|l| l.unwrap()) {
                    // Ignore comment lines
                    if line.trim().starts_with("#") {
                        continue
                    }
                    let parts: Vec<&str> = line.trim().splitn(2, '=').collect();
                    let (prop, value) = (parts[0], parts[1]);
                    match prop {
                        $($hyphen => p.$field = parse!(value, $fty),)*
                        prop => { return Err(Error::new(ErrorKind::Other, &format!("Unknown property {}", prop)[..])); }
                    }
                }
                Ok(p)
            }

            /// Saves a server.properties file into `path`. It creates the
            /// file if it does not exist, and will truncate it if it does.
            pub fn save(&self, path: &Path) -> io::Result<()> {
                let file = try!(File::create(path));
                let mut file = BufWriter::new(file);
                // Header
                try!(write!(&mut file, "#Minecraft server properties"));
                try!(write!(&mut file, "#(File modification datestamp)"));
                // Body. Vanilla MC does write 37 out of 40 properties by default, it
                // only writes the 3 left if they are not using default values. It
                // also writes them unsorted (possibly because they are stored in a
                // HashMap).
                $(try!(write!(&mut file, "{}={}\n", $hyphen, self.$field));)*
                Ok(())
            }
        }

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

            #[test]
            fn default_save_load() {
                use std::env;
                use std::fs;

                let mut dir = env::temp_dir();
                dir.push("default.properties");

                let default_props = Properties::default();
                match default_props.save(&dir) {
                    Ok(_) => {},
                    Err(err) => { panic!("Failed to save server.properties file with error: {}", err); }
                }

                match Properties::load(&dir) {
                    Ok(props) => {
                        assert_eq!(props, default_props);
                    },
                    Err(err) => {
                        panic!("Failed to load server.properties file with error: {}", err);
                    }
                }

                fs::remove_file(&dir).unwrap();
            }

            #[test]
            fn custom_save_load() {
                use std::env;
                use std::fs;

                let mut dir = env::temp_dir();
                dir.push("custom.properties");

                let custom_props = Properties{
                    server_port: 25570,
                    .. Properties::default()
                };
                match custom_props.save(&dir) {
                    Ok(_) => {},
                    Err(err) => { panic!("Failed to save server.properties file with error: {}", err); }
                }

                match Properties::load(&dir) {
                    Ok(props) => { assert_eq!(props, custom_props); },
                    Err(err) => { panic!("Failed to load server.properties file with error: {}", err); }
                }

                fs::remove_file(&dir).unwrap();
            }

            #[test]
            fn load_unknown_property() {
                use std::env;
                use std::error::Error;
                use std::fs;
                use std::io::Write;

                let mut dir = env::temp_dir();
                dir.push("unknown.properties");

                let mut f = fs::File::create(&dir).unwrap();
                f.write_all(b"foo-bar=true\n").unwrap();

                match Properties::load(&dir) {
                    Ok(_) => { panic!("server.properties should have failed to load"); }
                    Err(err) => { assert_eq!(err.description(), "Unknown property foo-bar"); },
                }

                fs::remove_file(&dir).unwrap();
            }

            #[test]
            fn decode_default() {
                let props = Properties::default();
                $(assert_eq!(props.$field, $default));*
            }
        }
    }
}

server_properties_impl! {
    { allow_flight, "allow-flight", bool, false }
    { allow_nether, "allow-nether", bool, true }
    { announce_player_achievements, "announce-player-achievements", bool, true }
    { difficulty, "difficulty", i32, 1 }
    { enable_query, "enable-query", bool, false }
    { enable_rcon, "enable-rcon", bool, false }
    { enable_command_block, "enable-command-block", bool, false }
    { force_gamemode, "force-gamemode", bool, false }
    { gamemode, "gamemode", i32, 0 }
    { generate_structures, "generate-structures", bool, true }
    { generator_settings, "generator-settings", String, "".to_string() }
    { hardcore, "hardcore", bool, false }
    { level_name, "level-name", String, "world".to_string() }
    { level_seed, "level-seed", String, "".to_string() }
    { level_type, "level-type", String, "DEFAULT".to_string() }
    { max_build_height, "max-build-height", i32, 256 }
    { max_players, "max-players", i32, 20 }
    { max_tick_time, "max-tick-time", i32, 60000 }
    { max_world_size, "max-world-size", i32, 29999984 }
    { motd, "motd", String, "A Minecraft Server".to_string() }
    { network_compression_threshold, "network-compression-threshold", i32, 256 }
    { online_mode, "online-mode", bool, true }
    { op_permission_level, "op-permission-level", i32, 4 }
    { player_idle_timeout, "player-idle-timeout", i32, 0 }
    { pvp, "pvp", bool, true }
    { query_port, "query.port", i32, 25565 }
    { rcon_password, "rcon.password", String, "".to_string() }
    { rcon_port, "rcon.port", i32, 25575 }
    { resource_pack, "resource-pack", String, "".to_string() }
    { resource_pack_hash, "resource-pack-hash", String, "".to_string() }
    { server_ip, "server-ip", String, "".to_string() }
    { server_port, "server-port", u16, 25565 }
    { snooper_enabled, "snooper-enabled", bool, true }
    { spawn_animals, "spawn-animals", bool, true }
    { spawn_monsters, "spawn-monsters", bool, true }
    { spawn_npcs, "spawn-npcs", bool, true }
    { spawn_protection, "spawn-protection", i32, 16 }
    { use_native_transport, "use-native-transport", bool, true }
    { view_distance, "view-distance", i32, 10 }
    { white_list, "white-list", bool, false }
}
<|endoftext|>


<commit_before>use tokens::*;

pub struct ParseTree<'a>
{
	pub root: Node<'a>,
}

impl<'a> ParseTree<'a>
{

}

pub struct Node<'a>
{
	pub token: Token<'a>,
	pub children: Vec<Node<'a>>
}

impl<'a> Node<'a>
{
	fn new() -> Node
	{

	}

	fn has_children(&self) -> bool
	{
		self.children.len() > 0
	}

	fn add_child(&mut self, child: Node<'a>)
	{
		self.children.push(child);
	}

	fn value(&self) -> String
	{
		self.token.value.clone()
	}
}
<commit_msg>Lifetime fix for Node<commit_after>use tokens::*;

pub struct ParseTree<'a>
{
	pub root: Node<'a>,
}

impl<'a> ParseTree<'a>
{

}

pub struct Node<'a>
{
	pub token: Token<'a>,
	pub children: Vec<Node<'a>>
}

impl<'a> Node<'a>
{
	fn new(token: Token<'a>) -> Node<'a>
	{
		Node
		{
			token: token,
			children: Vec::new()
		}
	}

	fn has_children(&self) -> bool
	{
		self.children.len() > 0
	}

	fn add_child(&mut self, child: Node<'a>)
	{
		self.children.push(child);
	}

	fn value(&self) -> String
	{
		self.token.value.clone()
	}
}
<|endoftext|>


<commit_before>use std::net::{SocketAddr, Shutdown};
use std::str::FromStr;
use std::sync::Arc;
use std::time::{Instant, Duration};

use jsonrpc::{MetaIoHandler, Value, Metadata};
use jsonrpc::futures::{self, Future, future};

use server_utils::tokio::{
	timer::Delay,
	net::TcpStream,
	io::{self},
	self,
};

use parking_lot::Mutex;

use ServerBuilder;
use MetaExtractor;
use RequestContext;

fn casual_server() -> ServerBuilder {
	let mut io = MetaIoHandler::<()>::default();
	io.add_method("say_hello", |_params| {
		Ok(Value::String("hello".to_string()))
	});
	ServerBuilder::new(io)
}

#[test]
fn doc_test() {
	::logger::init_log();

	let mut io = MetaIoHandler::<()>::default();
	io.add_method("say_hello", |_params| {
		Ok(Value::String("hello".to_string()))
	});
	let server = ServerBuilder::new(io);

	server.start(&SocketAddr::from_str("0.0.0.0:17770").unwrap())
		.expect("Server must run with no issues")
		.close()
}

#[test]
fn doc_test_connect() {
	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17775".parse().unwrap();
	let server = casual_server();
	let _server = server.start(&addr).expect("Server must run with no issues");

	let stream = TcpStream::connect(&addr)
		.and_then(move |_stream| {
			Ok(())
		})
		.map_err(|err| panic!("Server connection error: {:?}", err));

	tokio::run(stream);
}

#[test]
fn disconnect() {
	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17777".parse().unwrap();
	let server = casual_server();
	let dispatcher = server.dispatcher();
	let _server = server.start(&addr).expect("Server must run with no issues");

	let stream = TcpStream::connect(&addr)
		.and_then(move |stream| {
			assert_eq!(stream.peer_addr().unwrap(), addr);
			stream.shutdown(::std::net::Shutdown::Both)
		})
		.map_err(|err| panic!("Error disconnecting: {:?}", err));

	tokio::run(stream);

	::std::thread::sleep(::std::time::Duration::from_millis(50));

	assert_eq!(0, dispatcher.peer_count());
}

fn dummy_request(addr: &SocketAddr, data: Vec<u8>) -> Vec<u8> {
	let (ret_tx, ret_rx) = futures::sync::oneshot::channel();

	let stream = TcpStream::connect(addr)
		.and_then(move |stream| {
			io::write_all(stream, data)
		})
		.and_then(|(stream, _data)| {
			stream.shutdown(Shutdown::Write).unwrap();
			io::read_to_end(stream, vec![]).wait()
		})
		.and_then(move |(_stream, read_buf)| {
			ret_tx.send(read_buf).map_err(|err| panic!("Unable to send {:?}", err))
		})
		.map_err(|err| panic!("Error connecting or closing connection: {:?}", err));;

	tokio::run(stream);
	ret_rx.wait().expect("Unable to receive result")
}

fn dummy_request_str(addr: &SocketAddr, data: Vec<u8>) -> String {
	String::from_utf8(dummy_request(addr, data)).expect("String should be utf-8")
}

#[test]
fn doc_test_handle() {
	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17780".parse().unwrap();

	let server = casual_server();
	let _server = server.start(&addr).expect("Server must run with no issues");

	let result = dummy_request_str(
		&addr,
		b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n"[..].to_owned(),
		);

	assert_eq!(
		result,
		"{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n",
		"Response does not exactly much the expected response",
		);
}

#[test]
fn req_parallel() {
	use std::thread;

	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17782".parse().unwrap();
	let server = casual_server();
	let _server = server.start(&addr).expect("Server must run with no issues");

	let mut handles = Vec::new();
	for _ in 0..6 {
		let addr = addr.clone();
		handles.push(
			thread::spawn(move || {
				for _ in 0..100 {
					let result = dummy_request_str(
						&addr,
						b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n"[..].to_owned(),
						);

					assert_eq!(
						result,
						"{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n",
						"Response does not exactly much the expected response",
						);
				}
			})
		);
	}

	for handle in handles.drain(..) {
		handle.join().unwrap();
	}
}

#[derive(Clone)]
pub struct SocketMetadata {
	addr: SocketAddr,
}

impl Default for SocketMetadata {
	fn default() -> Self {
		SocketMetadata { addr: "0.0.0.0:0".parse().unwrap() }
	}
}

impl SocketMetadata {
	pub fn addr(&self) -> &SocketAddr {
		&self.addr
	}
}

impl Metadata for SocketMetadata { }

impl From<SocketAddr> for SocketMetadata {
	fn from(addr: SocketAddr) -> SocketMetadata {
		SocketMetadata { addr: addr }
	}
}

pub struct PeerMetaExtractor;

impl MetaExtractor<SocketMetadata> for PeerMetaExtractor {
	fn extract(&self, context: &RequestContext) -> SocketMetadata {
		context.peer_addr.into()
	}
}

fn meta_server() -> ServerBuilder<SocketMetadata> {
	let mut io = MetaIoHandler::<SocketMetadata>::default();
	io.add_method_with_meta("say_hello", |_params, meta: SocketMetadata| {
		future::ok(Value::String(format!("hello, {}", meta.addr())))
	});
	ServerBuilder::new(io).session_meta_extractor(PeerMetaExtractor)
}

#[test]
fn peer_meta() {
	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17785".parse().unwrap();
	let server = meta_server();
	let _server = server.start(&addr).expect("Server must run with no issues");

	let result = dummy_request_str(
		&addr,
		b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n"[..].to_owned()
		);

	// contains random port, so just smoky comparing response length
	assert_eq!(
		59,
		result.len()
		);
}

#[derive(Default)]
pub struct PeerListMetaExtractor {
	peers: Arc<Mutex<Vec<SocketAddr>>>,
}

impl MetaExtractor<SocketMetadata> for PeerListMetaExtractor {
	fn extract(&self, context: &RequestContext) -> SocketMetadata {
		trace!(target: "tcp", "extracting to peer list...");
		self.peers.lock().push(context.peer_addr.clone());
		context.peer_addr.into()
	}
}

#[test]
fn message() {
	// MASSIVE SETUP
	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17790".parse().unwrap();
	let mut io = MetaIoHandler::<SocketMetadata>::default();
	io.add_method_with_meta("say_hello", |_params, _: SocketMetadata| {
		future::ok(Value::String("hello".to_owned()))
	});
	let extractor = PeerListMetaExtractor::default();
	let peer_list = extractor.peers.clone();
	let server = ServerBuilder::new(io)
		.session_meta_extractor(extractor);
	let dispatcher = server.dispatcher();

	let _server = server.start(&addr).expect("Server must run with no issues");

	let delay = Delay::new(Instant::now() + Duration::from_millis(500))
		.map_err(|err| panic!("{:?}", err));

	let message = "ping";
	let executed_dispatch = Arc::new(Mutex::new(false));
	let executed_request = Arc::new(Mutex::new(false));
	let executed_dispatch_move = executed_dispatch.clone();
	let executed_request_move = executed_request.clone();

	// CLIENT RUN
	let stream = TcpStream::connect(&addr)
		.and_then(|stream| {
			future::ok(stream).join(delay)
		})
		.and_then(move |stream| {
			let peer_addr = peer_list.lock()[0].clone();
			dispatcher.push_message(
				&peer_addr,
				message.to_owned(),
				).expect("Should be sent with no errors");
			trace!(target: "tcp", "Dispatched message for {}", peer_addr);
			future::ok(stream)
		})
		.and_then(move |(stream, _)| {
			// Read message plus newline appended by codec.
			io::read_exact(stream, vec![0u8; message.len() + 1])
		})
		.and_then(move |(stream, read_buf)| {
			trace!(target: "tcp", "Read ping message");
			let ping_signal = read_buf[..].to_vec();

			assert_eq!(
				format!("{}\n", message),
				String::from_utf8(ping_signal).expect("String should be utf-8"),
				"Sent request does not match received by the peer",
				);
			// ensure that the above assert was actually triggered
			*executed_dispatch_move.lock() = true;

			future::ok(stream)
		})
		.and_then(|stream| {
			// make request AFTER message dispatches
			let data = b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n";
			io::write_all(stream, &data[..])
		})
		.and_then(|(stream, _)| {
			stream.shutdown(Shutdown::Write).unwrap();
			io::read_to_end(stream, Vec::new())
		})
		.and_then(move |(_, read_buf)| {
			trace!(target: "tcp", "Read response message");
			let response_signal = read_buf[..].to_vec();
			assert_eq!(
				"{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n",
				String::from_utf8(response_signal).expect("String should be utf-8"),
				"Response does not match the expected handling",
				);
			*executed_request_move.lock() = true;

			future::ok(())
		})
		.map_err(|err| panic!("Dispach message error: {:?}", err));

	tokio::run(stream);
	assert!(*executed_dispatch.lock());
	assert!(*executed_request.lock());
}
<commit_msg>Fix windows build. (#329)<commit_after>use std::net::{SocketAddr, Shutdown};
use std::str::FromStr;
use std::sync::Arc;
use std::time::{Instant, Duration};

use jsonrpc::{MetaIoHandler, Value, Metadata};
use jsonrpc::futures::{self, Future, future};

use server_utils::tokio::{
	timer::Delay,
	net::TcpStream,
	io::{self},
	self,
};

use parking_lot::Mutex;

use ServerBuilder;
use MetaExtractor;
use RequestContext;

fn casual_server() -> ServerBuilder {
	let mut io = MetaIoHandler::<()>::default();
	io.add_method("say_hello", |_params| {
		Ok(Value::String("hello".to_string()))
	});
	ServerBuilder::new(io)
}

#[test]
fn doc_test() {
	::logger::init_log();

	let mut io = MetaIoHandler::<()>::default();
	io.add_method("say_hello", |_params| {
		Ok(Value::String("hello".to_string()))
	});
	let server = ServerBuilder::new(io);

	server.start(&SocketAddr::from_str("0.0.0.0:17770").unwrap())
		.expect("Server must run with no issues")
		.close()
}

#[test]
fn doc_test_connect() {
	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17775".parse().unwrap();
	let server = casual_server();
	let _server = server.start(&addr).expect("Server must run with no issues");

	let stream = TcpStream::connect(&addr)
		.and_then(move |_stream| {
			Ok(())
		})
		.map_err(|err| panic!("Server connection error: {:?}", err));

	tokio::run(stream);
}

#[test]
fn disconnect() {
	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17777".parse().unwrap();
	let server = casual_server();
	let dispatcher = server.dispatcher();
	let _server = server.start(&addr).expect("Server must run with no issues");

	let stream = TcpStream::connect(&addr)
		.and_then(move |stream| {
			assert_eq!(stream.peer_addr().unwrap(), addr);
			stream.shutdown(::std::net::Shutdown::Both)
		})
		.map_err(|err| panic!("Error disconnecting: {:?}", err));

	tokio::run(stream);

	::std::thread::sleep(::std::time::Duration::from_millis(50));

	assert_eq!(0, dispatcher.peer_count());
}

fn dummy_request(addr: &SocketAddr, data: Vec<u8>) -> Vec<u8> {
	let (ret_tx, ret_rx) = futures::sync::oneshot::channel();

	let stream = TcpStream::connect(addr)
		.and_then(move |stream| {
			io::write_all(stream, data)
		})
		.and_then(|(stream, _data)| {
			stream.shutdown(Shutdown::Write).unwrap();
			io::read_to_end(stream, vec![]).wait()
		})
		.and_then(move |(_stream, read_buf)| {
			ret_tx.send(read_buf).map_err(|err| panic!("Unable to send {:?}", err))
		})
		.map_err(|err| panic!("Error connecting or closing connection: {:?}", err));;

	tokio::run(stream);
	ret_rx.wait().expect("Unable to receive result")
}

fn dummy_request_str(addr: &SocketAddr, data: Vec<u8>) -> String {
	String::from_utf8(dummy_request(addr, data)).expect("String should be utf-8")
}

#[test]
fn doc_test_handle() {
	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17780".parse().unwrap();

	let server = casual_server();
	let _server = server.start(&addr).expect("Server must run with no issues");

	let result = dummy_request_str(
		&addr,
		b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n"[..].to_owned(),
		);

	assert_eq!(
		result,
		"{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n",
		"Response does not exactly much the expected response",
		);
}

#[test]
fn req_parallel() {
	use std::thread;

	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17782".parse().unwrap();
	let server = casual_server();
	let _server = server.start(&addr).expect("Server must run with no issues");

	let mut handles = Vec::new();
	for _ in 0..6 {
		let addr = addr.clone();
		handles.push(
			thread::spawn(move || {
				for _ in 0..100 {
					let result = dummy_request_str(
						&addr,
						b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n"[..].to_owned(),
						);

					assert_eq!(
						result,
						"{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n",
						"Response does not exactly much the expected response",
						);
				}
			})
		);
	}

	for handle in handles.drain(..) {
		handle.join().unwrap();
	}
}

#[derive(Clone)]
pub struct SocketMetadata {
	addr: SocketAddr,
}

impl Default for SocketMetadata {
	fn default() -> Self {
		SocketMetadata { addr: "0.0.0.0:0".parse().unwrap() }
	}
}

impl SocketMetadata {
	pub fn addr(&self) -> &SocketAddr {
		&self.addr
	}
}

impl Metadata for SocketMetadata { }

impl From<SocketAddr> for SocketMetadata {
	fn from(addr: SocketAddr) -> SocketMetadata {
		SocketMetadata { addr: addr }
	}
}

pub struct PeerMetaExtractor;

impl MetaExtractor<SocketMetadata> for PeerMetaExtractor {
	fn extract(&self, context: &RequestContext) -> SocketMetadata {
		context.peer_addr.into()
	}
}

fn meta_server() -> ServerBuilder<SocketMetadata> {
	let mut io = MetaIoHandler::<SocketMetadata>::default();
	io.add_method_with_meta("say_hello", |_params, meta: SocketMetadata| {
		future::ok(Value::String(format!("hello, {}", meta.addr())))
	});
	ServerBuilder::new(io).session_meta_extractor(PeerMetaExtractor)
}

#[test]
fn peer_meta() {
	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17785".parse().unwrap();
	let server = meta_server();
	let _server = server.start(&addr).expect("Server must run with no issues");

	let result = dummy_request_str(
		&addr,
		b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n"[..].to_owned()
		);

	println!("{}", result);

	// contains random port, so just smoky comparing response length
	assert_eq!(
		if cfg!(windows) { 58 } else { 59 },
		result.len()
	);
}

#[derive(Default)]
pub struct PeerListMetaExtractor {
	peers: Arc<Mutex<Vec<SocketAddr>>>,
}

impl MetaExtractor<SocketMetadata> for PeerListMetaExtractor {
	fn extract(&self, context: &RequestContext) -> SocketMetadata {
		trace!(target: "tcp", "extracting to peer list...");
		self.peers.lock().push(context.peer_addr.clone());
		context.peer_addr.into()
	}
}

#[test]
fn message() {
	// MASSIVE SETUP
	::logger::init_log();
	let addr: SocketAddr = "127.0.0.1:17790".parse().unwrap();
	let mut io = MetaIoHandler::<SocketMetadata>::default();
	io.add_method_with_meta("say_hello", |_params, _: SocketMetadata| {
		future::ok(Value::String("hello".to_owned()))
	});
	let extractor = PeerListMetaExtractor::default();
	let peer_list = extractor.peers.clone();
	let server = ServerBuilder::new(io)
		.session_meta_extractor(extractor);
	let dispatcher = server.dispatcher();

	let _server = server.start(&addr).expect("Server must run with no issues");

	let delay = Delay::new(Instant::now() + Duration::from_millis(500))
		.map_err(|err| panic!("{:?}", err));

	let message = "ping";
	let executed_dispatch = Arc::new(Mutex::new(false));
	let executed_request = Arc::new(Mutex::new(false));
	let executed_dispatch_move = executed_dispatch.clone();
	let executed_request_move = executed_request.clone();

	// CLIENT RUN
	let stream = TcpStream::connect(&addr)
		.and_then(|stream| {
			future::ok(stream).join(delay)
		})
		.and_then(move |stream| {
			let peer_addr = peer_list.lock()[0].clone();
			dispatcher.push_message(
				&peer_addr,
				message.to_owned(),
				).expect("Should be sent with no errors");
			trace!(target: "tcp", "Dispatched message for {}", peer_addr);
			future::ok(stream)
		})
		.and_then(move |(stream, _)| {
			// Read message plus newline appended by codec.
			io::read_exact(stream, vec![0u8; message.len() + 1])
		})
		.and_then(move |(stream, read_buf)| {
			trace!(target: "tcp", "Read ping message");
			let ping_signal = read_buf[..].to_vec();

			assert_eq!(
				format!("{}\n", message),
				String::from_utf8(ping_signal).expect("String should be utf-8"),
				"Sent request does not match received by the peer",
				);
			// ensure that the above assert was actually triggered
			*executed_dispatch_move.lock() = true;

			future::ok(stream)
		})
		.and_then(|stream| {
			// make request AFTER message dispatches
			let data = b"{\"jsonrpc\": \"2.0\", \"method\": \"say_hello\", \"params\": [42, 23], \"id\": 1}\n";
			io::write_all(stream, &data[..])
		})
		.and_then(|(stream, _)| {
			stream.shutdown(Shutdown::Write).unwrap();
			io::read_to_end(stream, Vec::new())
		})
		.and_then(move |(_, read_buf)| {
			trace!(target: "tcp", "Read response message");
			let response_signal = read_buf[..].to_vec();
			assert_eq!(
				"{\"jsonrpc\":\"2.0\",\"result\":\"hello\",\"id\":1}\n",
				String::from_utf8(response_signal).expect("String should be utf-8"),
				"Response does not match the expected handling",
				);
			*executed_request_move.lock() = true;

			future::ok(())
		})
		.map_err(|err| panic!("Dispach message error: {:?}", err));

	tokio::run(stream);
	assert!(*executed_dispatch.lock());
	assert!(*executed_request.lock());
}
<|endoftext|>


<commit_before>extern crate syntex_syntax;

use std::fs::File;
use std::io;
use std::path::Path;

use syntex_syntax::ast;
use syntex_syntax::attr;
use syntex_syntax::codemap::{DUMMY_SP, respan};
use syntex_syntax::config;
use syntex_syntax::ext::base::{
    IdentMacroExpander,
    MultiItemDecorator,
    MultiItemModifier,
    NamedSyntaxExtension,
    SyntaxExtension,
    TTMacroExpander,
};
use syntex_syntax::ext::expand;
use syntex_syntax::feature_gate;
use syntex_syntax::parse::{self, token};
use syntex_syntax::print::{pp, pprust};
use syntex_syntax::ptr::P;

pub struct Registry {
    macros: Vec<ast::MacroDef>,
    syntax_exts: Vec<NamedSyntaxExtension>,
    cfg: Vec<P<ast::MetaItem>>,
    attrs: Vec<ast::Attribute>,
}

impl Registry {
    pub fn new() -> Registry {
        Registry {
            macros: Vec::new(),
            syntax_exts: Vec::new(),
            cfg: Vec::new(),
            attrs: Vec::new(),
        }
    }

    pub fn add_cfg(&mut self, cfg: &str) {
        let meta_item = parse::parse_meta_from_source_str(
            "cfgspec".to_string(),
            cfg.to_string(),
            Vec::new(),
            &parse::new_parse_sess());

        self.cfg.push(meta_item);
    }

    pub fn add_attr(&mut self, attr: &str) {
        let meta_item = parse::parse_meta_from_source_str(
            "attrspec".to_string(),
            attr.to_string(),
            Vec::new(),
            &parse::new_parse_sess());

        self.attrs.push(respan(DUMMY_SP, ast::Attribute_ {
            id: attr::mk_attr_id(),
            style: ast::AttrOuter,
            value: meta_item,
            is_sugared_doc: false,
        }));
    }

    pub fn register_macro<F>(&mut self, name: &str, extension: F)
        where F: TTMacroExpander + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::NormalTT(
            Box::new(extension),
            None,
            false
        );
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn register_ident<F>(&mut self, name: &str, extension: F)
        where F: IdentMacroExpander + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::IdentTT(
            Box::new(extension),
            None,
            false
        );
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn register_decorator<F>(&mut self, name: &str, extension: F)
        where F: MultiItemDecorator + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::MultiDecorator(Box::new(extension));
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn register_modifier<F>(&mut self, name: &str, extension: F)
        where F: MultiItemModifier + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::MultiModifier(Box::new(extension));
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn expand(self, crate_name: &str, src: &Path, dst: &Path) -> io::Result<()> {
        let sess = parse::new_parse_sess();

        let mut krate = parse::parse_crate_from_file(
            src,
            self.cfg,
            &sess);

        krate.attrs.extend(self.attrs);

        let krate = config::strip_unconfigured_items(
            &sess.span_diagnostic,
            krate);

        let features = feature_gate::check_crate_macros(
            &sess.span_diagnostic.cm,
            &sess.span_diagnostic,
            &krate);

        let mut ecfg = expand::ExpansionConfig::default(crate_name.to_string());
        ecfg.features = Some(&features);

        let krate = expand::expand_crate(
            &sess,
            ecfg,
            self.macros,
            self.syntax_exts,
            krate);

        let dst = try!(File::create(dst));

        let mut printer = pprust::rust_printer(Box::new(dst));
        try!(printer.print_mod(&krate.module, &krate.attrs[..]));
        try!(printer.print_remaining_comments());
        pp::eof(&mut printer.s)
    }
}
<commit_msg>Add support for pre and post expansion passes<commit_after>extern crate syntex_syntax;

use std::fs::File;
use std::io;
use std::path::Path;

use syntex_syntax::ast;
use syntex_syntax::attr;
use syntex_syntax::codemap::{DUMMY_SP, respan};
use syntex_syntax::config;
use syntex_syntax::ext::base::{
    IdentMacroExpander,
    MultiItemDecorator,
    MultiItemModifier,
    NamedSyntaxExtension,
    SyntaxExtension,
    TTMacroExpander,
};
use syntex_syntax::ext::expand;
use syntex_syntax::feature_gate;
use syntex_syntax::parse::{self, token};
use syntex_syntax::print::{pp, pprust};
use syntex_syntax::ptr::P;

pub type Pass = fn(ast::Crate) -> ast::Crate;

pub struct Registry {
    macros: Vec<ast::MacroDef>,
    syntax_exts: Vec<NamedSyntaxExtension>,
    pre_expansion_passes: Vec<Box<Pass>>,
    post_expansion_passes: Vec<Box<Pass>>,
    cfg: Vec<P<ast::MetaItem>>,
    attrs: Vec<ast::Attribute>,
}

impl Registry {
    pub fn new() -> Registry {
        Registry {
            macros: Vec::new(),
            syntax_exts: Vec::new(),
            pre_expansion_passes: Vec::new(),
            post_expansion_passes: Vec::new(),
            cfg: Vec::new(),
            attrs: Vec::new(),
        }
    }

    pub fn add_cfg(&mut self, cfg: &str) {
        let meta_item = parse::parse_meta_from_source_str(
            "cfgspec".to_string(),
            cfg.to_string(),
            Vec::new(),
            &parse::new_parse_sess());

        self.cfg.push(meta_item);
    }

    pub fn add_attr(&mut self, attr: &str) {
        let meta_item = parse::parse_meta_from_source_str(
            "attrspec".to_string(),
            attr.to_string(),
            Vec::new(),
            &parse::new_parse_sess());

        self.attrs.push(respan(DUMMY_SP, ast::Attribute_ {
            id: attr::mk_attr_id(),
            style: ast::AttrOuter,
            value: meta_item,
            is_sugared_doc: false,
        }));
    }

    pub fn register_macro<F>(&mut self, name: &str, extension: F)
        where F: TTMacroExpander + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::NormalTT(
            Box::new(extension),
            None,
            false
        );
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn register_ident<F>(&mut self, name: &str, extension: F)
        where F: IdentMacroExpander + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::IdentTT(
            Box::new(extension),
            None,
            false
        );
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn register_decorator<F>(&mut self, name: &str, extension: F)
        where F: MultiItemDecorator + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::MultiDecorator(Box::new(extension));
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn register_modifier<F>(&mut self, name: &str, extension: F)
        where F: MultiItemModifier + 'static
    {
        let name = token::intern(name);
        let syntax_extension = SyntaxExtension::MultiModifier(Box::new(extension));
        self.syntax_exts.push((name, syntax_extension));
    }

    pub fn add_pre_expansion_pass(&mut self, pass: Pass) {
        self.pre_expansion_passes.push(Box::new(pass))
    }

    pub fn add_post_expansion_pass(&mut self, pass: Pass) {
        self.post_expansion_passes.push(Box::new(pass))
    }

    pub fn expand(self, crate_name: &str, src: &Path, dst: &Path) -> io::Result<()> {
        let sess = parse::new_parse_sess();

        let mut krate = parse::parse_crate_from_file(
            src,
            self.cfg,
            &sess);

        krate.attrs.extend(self.attrs);

        let krate = config::strip_unconfigured_items(
            &sess.span_diagnostic,
            krate);

        let features = feature_gate::check_crate_macros(
            &sess.span_diagnostic.cm,
            &sess.span_diagnostic,
            &krate);

        let krate = self.pre_expansion_passes.iter()
            .fold(krate, |krate, f| (f)(krate));

        let mut ecfg = expand::ExpansionConfig::default(crate_name.to_string());
        ecfg.features = Some(&features);

        let krate = expand::expand_crate(
            &sess,
            ecfg,
            self.macros,
            self.syntax_exts,
            krate);

        let krate = self.post_expansion_passes.iter()
            .fold(krate, |krate, f| (f)(krate));

        let dst = try!(File::create(dst));

        let mut printer = pprust::rust_printer(Box::new(dst));
        try!(printer.print_mod(&krate.module, &krate.attrs[..]));
        try!(printer.print_remaining_comments());
        pp::eof(&mut printer.s)
    }
}
<|endoftext|>