<commit_before>use std::iter::Iterator;
use std::path;

use image;
use image::{error::ImageResult, DynamicImage, GenericImageView};

pub struct Image {
    pub width: u32,
    pub height: u32,
    img_buf: DynamicImage,
}

impl Image {
    pub fn new<P: AsRef<path::Path> + ToString>(path: P) -> ImageResult<Image> {
        let img_buf = image::open(&path)?;
        let (width, height) = img_buf.dimensions();
        Ok(Image {
            width,
            height,
            img_buf,
        })
    }

    pub fn from(img_buf: DynamicImage) -> Image {
        let (width, height) = img_buf.dimensions();
        Image {
            width,
            height,
            img_buf,
        }
    }

    #[cfg(feature = "qrcode_builder")]
    pub fn from_qr(code: &str, width: u32) -> qrcode::QrResult<Image> {
        use image::ImageBuffer;
        use qrcode::QrCode;
        let code = QrCode::new(code.as_bytes())?;
        let code_width = code.width() as u32;
        let point_width = width / (code_width + 2);
        // QR code quite zone width
        let quite_width = (width % (code_width + 2)) / 2 + point_width;

        #[allow(clippy::many_single_char_names)]
        let img_buf = ImageBuffer::from_fn(width, width, |x, y| {
            let is_white = x < quite_width
                || y < quite_width
                || x >= (width - quite_width)
                || y >= (width - quite_width)
                || !code[(
                    ((x - quite_width) / point_width) as usize,
                    ((y - quite_width) / point_width) as usize,
                )];
            if is_white {
                image::Rgb([0xFF, 0xFF, 0xFF])
            } else {
                image::Rgb([0, 0, 0])
            }
        });
        Ok(Image {
            width,
            height: width,
            img_buf: DynamicImage::ImageRgb8(img_buf),
        })
    }

    pub fn is_blank_pixel(&self, x: u32, y: u32) -> bool {
        let pixel = self.img_buf.get_pixel(x, y);
        // full transprant OR is white
        pixel[3] == 0 || (pixel[0] & pixel[1] & pixel[2]) == 0xFF
    }

    pub fn bitimage_lines(&self, density: u32) -> BitimageLines {
        BitimageLines {
            line: 0,
            density,
            image: self,
        }
    }

    #[allow(clippy::many_single_char_names)]
    fn get_line(&self, num: u32, density: u32) -> Option<Box<[u8]>> {
        let n = self.height as u32 / density;
        let y = num - 1;
        if y >= n {
            return None;
        }

        let c = density / 8;
        let mut data: Vec<u8> = vec![0; (self.width * c) as usize];
        // println!(">>> num={}, density={}, n={}, y={}, c={}, data.len()={}",
        //          num, density, n, y, c, data.len());
        for x in 0..self.width {
            for b in 0..density {
                let i = x * c + (b >> 3);
                // println!("x={}, b={}, i={}, b>>8={}", x, b, i, b>>3);
                let l = y * density + b;
                if l < self.height && !self.is_blank_pixel(x, l) {
                    data[i as usize] += 0x80 >> (b & 0x07);
                }
            }
        }
        Some(data.into_boxed_slice())
    }

    #[allow(clippy::many_single_char_names)]
    pub fn get_raster(&self) -> Box<[u8]> {
        let n = (self.width + 7) / 8; // Number of bytes per line
        let mut data: Vec<u8> = vec![0; (n * self.height) as usize];
        for y in 0..self.height {
            for x in 0..n {
                for b in 0..8 {
                    let i = x * 8 + b;
                    if i < self.width && !self.is_blank_pixel(i, y) {
                        data[(y * n + x) as usize] += 0x80 >> (b & 0x7);
                    }
                }
            }
        }
        data.into_boxed_slice()
    }
}

pub struct BitimageLines<'a> {
    line: u32,
    density: u32,
    image: &'a Image,
}

impl<'a> Iterator for BitimageLines<'a> {
    type Item = Box<[u8]>;

    fn next(&mut self) -> Option<Box<[u8]>> {
        self.line += 1;
        self.image.get_line(self.line, self.density)
    }
}
<commit_msg>fix: fix qrcode color detect<commit_after>use std::iter::Iterator;
use std::path;

use image;
use image::{error::ImageResult, DynamicImage, GenericImageView};

pub struct Image {
    pub width: u32,
    pub height: u32,
    img_buf: DynamicImage,
}

impl Image {
    pub fn new<P: AsRef<path::Path> + ToString>(path: P) -> ImageResult<Image> {
        let img_buf = image::open(&path)?;
        let (width, height) = img_buf.dimensions();
        Ok(Image {
            width,
            height,
            img_buf,
        })
    }

    pub fn from(img_buf: DynamicImage) -> Image {
        let (width, height) = img_buf.dimensions();
        Image {
            width,
            height,
            img_buf,
        }
    }

    #[cfg(feature = "qrcode_builder")]
    pub fn from_qr(code: &str, width: u32) -> qrcode::QrResult<Image> {
        use image::ImageBuffer;
        use qrcode::QrCode;
        let code = QrCode::new(code.as_bytes())?;
        let code_width = code.width() as u32;
        let point_width = width / (code_width + 2);
        // QR code quite zone width
        let quite_width = (width % (code_width + 2)) / 2 + point_width;

        #[allow(clippy::many_single_char_names)]
        let img_buf = ImageBuffer::from_fn(width, width, |x, y| {
            let is_white = x < quite_width
                || y < quite_width
                || x >= (width - quite_width)
                || y >= (width - quite_width)
                || code[(
                    ((x - quite_width) / point_width) as usize,
                    ((y - quite_width) / point_width) as usize,
                )] == qrcode::Color::Light;
            if is_white {
                image::Rgb([0xFF, 0xFF, 0xFF])
            } else {
                image::Rgb([0, 0, 0])
            }
        });
        Ok(Image {
            width,
            height: width,
            img_buf: DynamicImage::ImageRgb8(img_buf),
        })
    }

    pub fn is_blank_pixel(&self, x: u32, y: u32) -> bool {
        let pixel = self.img_buf.get_pixel(x, y);
        // full transprant OR is white
        pixel[3] == 0 || (pixel[0] & pixel[1] & pixel[2]) == 0xFF
    }

    pub fn bitimage_lines(&self, density: u32) -> BitimageLines {
        BitimageLines {
            line: 0,
            density,
            image: self,
        }
    }

    #[allow(clippy::many_single_char_names)]
    fn get_line(&self, num: u32, density: u32) -> Option<Box<[u8]>> {
        let n = self.height as u32 / density;
        let y = num - 1;
        if y >= n {
            return None;
        }

        let c = density / 8;
        let mut data: Vec<u8> = vec![0; (self.width * c) as usize];
        // println!(">>> num={}, density={}, n={}, y={}, c={}, data.len()={}",
        //          num, density, n, y, c, data.len());
        for x in 0..self.width {
            for b in 0..density {
                let i = x * c + (b >> 3);
                // println!("x={}, b={}, i={}, b>>8={}", x, b, i, b>>3);
                let l = y * density + b;
                if l < self.height && !self.is_blank_pixel(x, l) {
                    data[i as usize] += 0x80 >> (b & 0x07);
                }
            }
        }
        Some(data.into_boxed_slice())
    }

    #[allow(clippy::many_single_char_names)]
    pub fn get_raster(&self) -> Box<[u8]> {
        let n = (self.width + 7) / 8; // Number of bytes per line
        let mut data: Vec<u8> = vec![0; (n * self.height) as usize];
        for y in 0..self.height {
            for x in 0..n {
                for b in 0..8 {
                    let i = x * 8 + b;
                    if i < self.width && !self.is_blank_pixel(i, y) {
                        data[(y * n + x) as usize] += 0x80 >> (b & 0x7);
                    }
                }
            }
        }
        data.into_boxed_slice()
    }
}

pub struct BitimageLines<'a> {
    line: u32,
    density: u32,
    image: &'a Image,
}

impl<'a> Iterator for BitimageLines<'a> {
    type Item = Box<[u8]>;

    fn next(&mut self) -> Option<Box<[u8]>> {
        self.line += 1;
        self.image.get_line(self.line, self.density)
    }
}
<|endoftext|>


<commit_before>use std::fmt::Show;
use std::sync::{Arc, Mutex};

use conduit::Request;
use conduit_middleware::Middleware;
use git2;
use oauth2;
use r2d2;
use s3;

use {db, Config};

pub struct App {
    pub database: db::Pool,
    pub github: oauth2::Config,
    pub bucket: s3::Bucket,
    pub s3_proxy: Option<String>,
    pub session_key: String,
    pub git_repo: Mutex<git2::Repository>,
    pub git_repo_checkout: Path,
    pub config: Config,
}

pub struct AppMiddleware {
    app: Arc<App>
}

impl App {
    pub fn new(config: &Config) -> App {
        let github = oauth2::Config::new(
            config.gh_client_id.as_slice(),
            config.gh_client_secret.as_slice(),
            "https://github.com/login/oauth/authorize",
            "https://github.com/login/oauth/access_token",
        );

        let db_config = r2d2::Config {
            pool_size: if config.env == ::Production {10} else {1},
            helper_tasks: if config.env == ::Production {3} else {1},
            test_on_check_out: false,
        };

        let repo = git2::Repository::open(&config.git_repo_checkout).unwrap();
        return App {
            database: db::pool(config.db_url.as_slice(), db_config),
            github: github,
            bucket: s3::Bucket::new(config.s3_bucket.clone(),
                                    config.s3_access_key.clone(),
                                    config.s3_secret_key.clone(),
                                    if config.env == ::Test {"http"} else {"https"}),
            s3_proxy: config.s3_proxy.clone(),
            session_key: config.session_key.clone(),
            git_repo: Mutex::new(repo),
            git_repo_checkout: config.git_repo_checkout.clone(),
            config: config.clone(),
        };
    }

    pub fn db_setup(&self) {
        db::setup(&*self.database.get().unwrap())
    }
}

impl AppMiddleware {
    pub fn new(app: Arc<App>) -> AppMiddleware {
        AppMiddleware { app: app }
    }
}

impl Middleware for AppMiddleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Show + 'static>> {
        req.mut_extensions().insert(self.app.clone());
        Ok(())
    }
}

pub trait RequestApp<'a> {
    fn app(self) -> &'a Arc<App>;
}

impl<'a> RequestApp<'a> for &'a Request + 'a {
    fn app(self) -> &'a Arc<App> {
        self.extensions().find::<Arc<App>>()
            .expect("Missing app")
    }
}
<commit_msg>little feedback when the DB is being setup<commit_after>use std::fmt::Show;
use std::sync::{Arc, Mutex};

use conduit::Request;
use conduit_middleware::Middleware;
use git2;
use oauth2;
use r2d2;
use s3;

use {db, Config};

pub struct App {
    pub database: db::Pool,
    pub github: oauth2::Config,
    pub bucket: s3::Bucket,
    pub s3_proxy: Option<String>,
    pub session_key: String,
    pub git_repo: Mutex<git2::Repository>,
    pub git_repo_checkout: Path,
    pub config: Config,
}

pub struct AppMiddleware {
    app: Arc<App>
}

impl App {
    pub fn new(config: &Config) -> App {
        let github = oauth2::Config::new(
            config.gh_client_id.as_slice(),
            config.gh_client_secret.as_slice(),
            "https://github.com/login/oauth/authorize",
            "https://github.com/login/oauth/access_token",
        );

        let db_config = r2d2::Config {
            pool_size: if config.env == ::Production {10} else {1},
            helper_tasks: if config.env == ::Production {3} else {1},
            test_on_check_out: false,
        };

        let repo = git2::Repository::open(&config.git_repo_checkout).unwrap();
        return App {
            database: db::pool(config.db_url.as_slice(), db_config),
            github: github,
            bucket: s3::Bucket::new(config.s3_bucket.clone(),
                                    config.s3_access_key.clone(),
                                    config.s3_secret_key.clone(),
                                    if config.env == ::Test {"http"} else {"https"}),
            s3_proxy: config.s3_proxy.clone(),
            session_key: config.session_key.clone(),
            git_repo: Mutex::new(repo),
            git_repo_checkout: config.git_repo_checkout.clone(),
            config: config.clone(),
        };
    }

    pub fn db_setup(&self) {
        print!(" - setting up the db\n")
        db::setup(&*self.database.get().unwrap())
    }
}

impl AppMiddleware {
    pub fn new(app: Arc<App>) -> AppMiddleware {
        AppMiddleware { app: app }
    }
}

impl Middleware for AppMiddleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Show + 'static>> {
        req.mut_extensions().insert(self.app.clone());
        Ok(())
    }
}

pub trait RequestApp<'a> {
    fn app(self) -> &'a Arc<App>;
}

impl<'a> RequestApp<'a> for &'a Request + 'a {
    fn app(self) -> &'a Arc<App> {
        self.extensions().find::<Arc<App>>()
            .expect("Missing app")
    }
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};

use conduit::{Request, Response};
use conduit_middleware::Middleware;
use git2;
use oauth2;
use r2d2;
use curl::easy::Easy;

use {db, Config};

/// The `App` struct holds the main components of the application like
/// the database connection pool and configurations
pub struct App {
    /// The database connection pool
    pub database: db::Pool,

    /// The database connection pool
    pub diesel_database: db::DieselPool,

    /// The GitHub OAuth2 configuration
    pub github: oauth2::Config,

    pub session_key: String,
    pub git_repo: Mutex<git2::Repository>,
    pub git_repo_checkout: PathBuf,

    /// The server configuration
    pub config: Config,
}

/// The `AppMiddleware` injects an `App` instance into the `Request` extensions
pub struct AppMiddleware {
    app: Arc<App>
}

impl App {
    pub fn new(config: &Config) -> App {
        let mut github = oauth2::Config::new(
            &config.gh_client_id,
            &config.gh_client_secret,
            "https://github.com/login/oauth/authorize",
            "https://github.com/login/oauth/access_token",
        );

        github.scopes.push(String::from("read:org"));

        let db_config = r2d2::Config::builder()
            .pool_size(if config.env == ::Env::Production {10} else {1})
            .min_idle(if config.env == ::Env::Production {Some(5)} else {None})
            .helper_threads(if config.env == ::Env::Production {3} else {1})
            .build();
        let diesel_db_config = r2d2::Config::builder()
            .pool_size(if config.env == ::Env::Production {50} else {1})
            .min_idle(if config.env == ::Env::Production {Some(5)} else {None})
            .helper_threads(if config.env == ::Env::Production {3} else {1})
            .build();

        let repo = git2::Repository::open(&config.git_repo_checkout).unwrap();
        App {
            database: db::pool(&config.db_url, db_config),
            diesel_database: db::diesel_pool(&config.db_url, diesel_db_config),
            github: github,
            session_key: config.session_key.clone(),
            git_repo: Mutex::new(repo),
            git_repo_checkout: config.git_repo_checkout.clone(),
            config: config.clone(),
        }
    }

    pub fn handle(&self) -> Easy {
        let mut handle = Easy::new();
        if let Some(proxy) = self.config.uploader.proxy() {
            handle.proxy(proxy).unwrap();
        }
        handle
    }
}

impl AppMiddleware {
    pub fn new(app: Arc<App>) -> AppMiddleware {
        AppMiddleware { app: app }
    }
}

impl Middleware for AppMiddleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        req.mut_extensions().insert(self.app.clone());
        Ok(())
    }

    fn after(&self, req: &mut Request, res: Result<Response, Box<Error+Send>>)
             -> Result<Response, Box<Error+Send>> {
        req.mut_extensions().pop::<Arc<App>>().unwrap();
        res
    }
}

/// Adds an `app()` method to the `Request` type returning the global `App` instance
pub trait RequestApp {
    fn app(&self) -> &Arc<App>;
}

impl<T: Request + ?Sized> RequestApp for T {
    fn app(&self) -> &Arc<App> {
        self.extensions().find::<Arc<App>>()
            .expect("Missing app")
    }
}
<commit_msg>Lower number of DB connections available per dyno in production<commit_after>use std::error::Error;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};

use conduit::{Request, Response};
use conduit_middleware::Middleware;
use git2;
use oauth2;
use r2d2;
use curl::easy::Easy;

use {db, Config};

/// The `App` struct holds the main components of the application like
/// the database connection pool and configurations
pub struct App {
    /// The database connection pool
    pub database: db::Pool,

    /// The database connection pool
    pub diesel_database: db::DieselPool,

    /// The GitHub OAuth2 configuration
    pub github: oauth2::Config,

    pub session_key: String,
    pub git_repo: Mutex<git2::Repository>,
    pub git_repo_checkout: PathBuf,

    /// The server configuration
    pub config: Config,
}

/// The `AppMiddleware` injects an `App` instance into the `Request` extensions
pub struct AppMiddleware {
    app: Arc<App>
}

impl App {
    pub fn new(config: &Config) -> App {
        let mut github = oauth2::Config::new(
            &config.gh_client_id,
            &config.gh_client_secret,
            "https://github.com/login/oauth/authorize",
            "https://github.com/login/oauth/access_token",
        );

        github.scopes.push(String::from("read:org"));

        let db_config = r2d2::Config::builder()
            .pool_size(if config.env == ::Env::Production {10} else {1})
            .min_idle(if config.env == ::Env::Production {Some(5)} else {None})
            .helper_threads(if config.env == ::Env::Production {3} else {1})
            .build();
        let diesel_db_config = r2d2::Config::builder()
            .pool_size(if config.env == ::Env::Production {30} else {1})
            .min_idle(if config.env == ::Env::Production {Some(5)} else {None})
            .helper_threads(if config.env == ::Env::Production {3} else {1})
            .build();

        let repo = git2::Repository::open(&config.git_repo_checkout).unwrap();
        App {
            database: db::pool(&config.db_url, db_config),
            diesel_database: db::diesel_pool(&config.db_url, diesel_db_config),
            github: github,
            session_key: config.session_key.clone(),
            git_repo: Mutex::new(repo),
            git_repo_checkout: config.git_repo_checkout.clone(),
            config: config.clone(),
        }
    }

    pub fn handle(&self) -> Easy {
        let mut handle = Easy::new();
        if let Some(proxy) = self.config.uploader.proxy() {
            handle.proxy(proxy).unwrap();
        }
        handle
    }
}

impl AppMiddleware {
    pub fn new(app: Arc<App>) -> AppMiddleware {
        AppMiddleware { app: app }
    }
}

impl Middleware for AppMiddleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Error+Send>> {
        req.mut_extensions().insert(self.app.clone());
        Ok(())
    }

    fn after(&self, req: &mut Request, res: Result<Response, Box<Error+Send>>)
             -> Result<Response, Box<Error+Send>> {
        req.mut_extensions().pop::<Arc<App>>().unwrap();
        res
    }
}

/// Adds an `app()` method to the `Request` type returning the global `App` instance
pub trait RequestApp {
    fn app(&self) -> &Arc<App>;
}

impl<T: Request + ?Sized> RequestApp for T {
    fn app(&self) -> &Arc<App> {
        self.extensions().find::<Arc<App>>()
            .expect("Missing app")
    }
}
<|endoftext|>


<commit_before>extern crate libc;

use std::env;

use ArgMatches;
use Arg;
use args::OptArg;
use args::FlagArg;
use args::PosArg;

pub struct App {
	pub name: &'static str,
	pub author: Option<&'static str>,
	pub version: Option<&'static str>,
	pub about: Option<&'static str>,
	// raw_args: Vec<Arg>,
	flags: Vec<FlagArg>,
	opts: Vec<OptArg>,
	positionals: Vec<PosArg>,
	needs_long_help: bool,
	needs_long_version: bool,
	needs_short_help: bool,
	needs_short_version: bool
}

impl App {
	pub fn new(n: &'static str) -> App {
		App {
			name: n,
			author: None,
			about: None,
			version: None,
			// raw_args: vec![],
			flags: vec![],
			opts: vec![],
			needs_long_version: true,
			needs_long_help: true,
			positionals: vec![],
			needs_short_help: true,
			needs_short_version: true
		}
	}

	pub fn author(&mut self, a: &'static str) -> &mut App {
		self.author = Some(a);
		self
	}

	pub fn about(&mut self, a: &'static str) -> &mut App {
		self.about = Some(a);
		self
	}

	pub fn version(&mut self, v: &'static str)-> &mut App  {
		self.version = Some(v);
		self
	}

	pub fn arg(&mut self, a: &Arg) -> &mut App {
		if let Some(i) = a.index {
			self.positionals.push(PosArg {
				name: a.name,
				index: i,
				required: a.required,
				help: a.help,
				value: None

			});
		} else if a.takes_value {
			self.opts.push(OptArg {
				name: a.name,
				short: a.short,
				long: a.long,
				help: a.help,
				required: a.required,
				value: None
			});
		} else {
			if let Some(l) = a.long {
				if l == "help" {
					self.needs_long_help = false;
				} else if l == "version" {
					self.needs_long_version = false;
				}
			}
			if let Some(s) = a.short {
				if s == 'h' {
					self.needs_short_help = false;
				} else if s == 'v' {
					self.needs_short_version = false;
				}
			}
			self.flags.push(FlagArg{
				name: a.name,
				short: a.short,
				long: a.long,
				help: a.help,
				multiple: a.multiple,
				occurrences: 1
			});
		}
		self
	}

	fn print_help(&self) {
		println!("Help info!");
		unsafe { libc::exit(0); }
	}

	fn print_version(&self) {
		let ver = match self.version {
			Some(v) => v,
			None => ""
		};
		println!("{} {}", self.name, ver);
		unsafe { libc::exit(0); }
	}

	fn parse_long_arg(&self, matches: &mut ArgMatches, arg: &str) -> &'static str {
		let mut p_arg = arg.trim_left_matches(|c| c == '-');
		let mut found = false;
		let mut needs_val = false;

		if p_arg == "help" && self.needs_long_help {
			self.print_help();
		} else if p_arg == "version" && self.needs_long_version {
			self.print_version();
		}
		for f in self.flags.iter() {
			if let Some(l) = f.long {
				if l == p_arg {
					for ff in matches.flags.iter_mut() {
						if ff.name == f.name {
							// already in matches
							ff.occurrences = if ff.multiple { ff.occurrences + 1 } else { 1 };
							found = true;
						}
					}
					if ! found {
						matches.flags.push(f.clone())
					}
					return "";
				}
			}
		}
		if p_arg.contains("=") {
			let p_argv: Vec<&str> = p_arg.split_str("=").collect();
			p_arg = p_argv[0];
			for o in self.opts.iter() {
				if let Some(l) = o.long {
					if l == p_arg {
						found = true;
						matches.opts.push(OptArg{
							name: o.name,
						    short: o.short,
						    long: o.long,
						    help: o.help,
						    required: o.required,
						    value: Some(p_argv[1].to_string())
						});
						break;
					}
				}
			}
		} else {
			for o in self.opts.iter() {
				if let Some(l) = o.long {
					if l == p_arg {
						return o.name;
					}
				}
			}
		}

		// Fails if argument supplied to binary isn't valid
		assert!(found == false);

		""
	}

	fn parse_short_arg(&self, matches: &mut ArgMatches, arg: &str) -> &'static str {
		let mut found = false;
		if arg.len() > 2 {
			// Multiple flags using short i.e. -bgHlS
			let p_arg = arg.trim_left_matches(|c| c == '-');
			for c in p_arg.chars() {
				if c == 'h' && self.needs_short_help {
					self.print_help();
				} else if c == 'v' && self.needs_short_version {
					self.print_version();
				}
				for f in self.flags.iter() {
					if let Some(s) = f.short {
						if c == s {
							found = true;
							matches.flags.push(f.clone());
						}
					}
				}
				// Fails if argument supplied to binary isn't valid
				assert!(found == false);
				return "";
			}
		} else {
			// Short flag or opt
			let p_arg = arg.char_at(1);
			if p_arg == 'h' && self.needs_short_help {
				self.print_help();
			} else if p_arg == 'v' && self.needs_short_version {
				self.print_version();
			}
			for f in self.flags.iter() {
				if let Some(s) = f.short {
					if p_arg == s {
						found = true;
						matches.flags.push(f.clone());
					}
				}
			}
			for o in self.opts.iter() {
				if let Some(s) = o.short {
					if s == p_arg {
						return o.name;
					}
				}
			}
		}
		// Fails if argument supplied to binary isn't valid
		assert!(found == false);

		""
	}

	pub fn get_matches(&mut self) -> ArgMatches {

		let mut matches = ArgMatches::new(self);

		// let mut needs_val = false;
		let mut needs_val_of = "".to_string();
		let mut pos_counter = 1;
		for arg in env::args().collect::<Vec<String>>().tail() {
			let arg_slice = arg.as_slice();
			if ! needs_val_of.is_empty() {
				for o in self.opts.iter() {
					if needs_val_of == o.name.to_string() {
						matches.opts.push(OptArg{
							name: o.name,
						    short: o.short,
						    long: o.long,
						    help: o.help,
						    required: o.required,
						    value: Some(arg.clone())
						});
						needs_val_of.clear();
						break;
					}
				}
				continue;
			}
			if arg_slice.starts_with("--") {
				// Single flag, or option
				needs_val_of = self.parse_long_arg(&mut matches, arg_slice).to_string();

			} else if arg_slice.starts_with("-") {
				needs_val_of = self.parse_short_arg(&mut matches, arg_slice).to_string();
			} else {
				// Positional

				// Fails if no positionals are expected/possible
				assert!(self.positionals.is_empty() == false);

				for p in self.positionals.iter() {
					matches.positionals.push(PosArg{
						name: p.name,
						help: p.help,
						required: p.required,
						value: Some(arg.clone()),
						index: pos_counter
					});
					pos_counter += 1;
				}
			}

		}

		// Fails if we reached the end of args() but were still
		// expecting a value, such as ./fake -c
		// where -c takes a value
		assert!(needs_val_of.is_empty());

		matches
	}
}<commit_msg>v0.0.4.3<commit_after>extern crate libc;

use std::env;

use ArgMatches;
use Arg;
use args::OptArg;
use args::FlagArg;
use args::PosArg;

pub struct App {
	pub name: &'static str,
	pub author: Option<&'static str>,
	pub version: Option<&'static str>,
	pub about: Option<&'static str>,
	// raw_args: Vec<Arg>,
	flags: Vec<FlagArg>,
	opts: Vec<OptArg>,
	positionals: Vec<PosArg>,
	needs_long_help: bool,
	needs_long_version: bool,
	needs_short_help: bool,
	needs_short_version: bool
}

impl App {
	pub fn new(n: &'static str) -> App {
		App {
			name: n,
			author: None,
			about: None,
			version: None,
			// raw_args: vec![],
			flags: vec![],
			opts: vec![],
			needs_long_version: true,
			needs_long_help: true,
			positionals: vec![],
			needs_short_help: true,
			needs_short_version: true
		}
	}

	pub fn author(&mut self, a: &'static str) -> &mut App {
		self.author = Some(a);
		self
	}

	pub fn about(&mut self, a: &'static str) -> &mut App {
		self.about = Some(a);
		self
	}

	pub fn version(&mut self, v: &'static str)-> &mut App  {
		self.version = Some(v);
		self
	}

	pub fn arg(&mut self, a: &Arg) -> &mut App {
		if let Some(i) = a.index {
			self.positionals.push(PosArg {
				name: a.name,
				index: i,
				required: a.required,
				help: a.help,
				value: None

			});
		} else if a.takes_value {
			self.opts.push(OptArg {
				name: a.name,
				short: a.short,
				long: a.long,
				help: a.help,
				required: a.required,
				value: None
			});
		} else {
			if let Some(l) = a.long {
				if l == "help" {
					self.needs_long_help = false;
				} else if l == "version" {
					self.needs_long_version = false;
				}
			}
			if let Some(s) = a.short {
				if s == 'h' {
					self.needs_short_help = false;
				} else if s == 'v' {
					self.needs_short_version = false;
				}
			}
			self.flags.push(FlagArg{
				name: a.name,
				short: a.short,
				long: a.long,
				help: a.help,
				multiple: a.multiple,
				occurrences: 1
			});
		}
		self
	}

	fn print_help(&self) {
		println!("Help info!");
		unsafe { libc::exit(0); }
	}

	fn print_version(&self) {
		let ver = match self.version {
			Some(v) => v,
			None => ""
		};
		println!("{} {}", self.name, ver);
		unsafe { libc::exit(0); }
	}

	fn parse_long_arg(&self, matches: &mut ArgMatches, arg: &str) -> &'static str {
		let mut p_arg = arg.trim_left_matches(|c| c == '-');
		let mut found = false;
		let mut needs_val = false;

		if p_arg == "help" && self.needs_long_help {
			self.print_help();
		} else if p_arg == "version" && self.needs_long_version {
			self.print_version();
		}
		for f in self.flags.iter() {
			if let Some(l) = f.long {
				if l == p_arg {
					found = true;
					let mut mult = false;
					for ff in matches.flags.iter_mut() {
						if ff.name == f.name {
							// already in matches
							ff.occurrences = if ff.multiple { ff.occurrences + 1 } else { 1 };
							mult = true;
						}
					}
					if ! mult {
						matches.flags.push(f.clone())
					}
					return "";
				}
			}
		}
		if p_arg.contains("=") {
			let p_argv: Vec<&str> = p_arg.split_str("=").collect();
			p_arg = p_argv[0];
			for o in self.opts.iter() {
				if let Some(l) = o.long {
					if l == p_arg {
						found = true;
						matches.opts.push(OptArg{
							name: o.name,
						    short: o.short,
						    long: o.long,
						    help: o.help,
						    required: o.required,
						    value: Some(p_argv[1].to_string())
						});
						break;
					}
				}
			}
		} else {
			for o in self.opts.iter() {
				if let Some(l) = o.long {
					if l == p_arg {
						return o.name;
					}
				}
			}
		}

		// Fails if argument supplied to binary isn't valid
		assert!(found == false);

		""
	}

	fn parse_short_arg(&self, matches: &mut ArgMatches, arg: &str) -> &'static str {
		let mut found = false;
		if arg.len() > 2 {
			// Multiple flags using short i.e. -bgHlS
			let p_arg = arg.trim_left_matches(|c| c == '-');
			for c in p_arg.chars() {
				if c == 'h' && self.needs_short_help {
					self.print_help();
				} else if c == 'v' && self.needs_short_version {
					self.print_version();
				}
				for f in self.flags.iter() {
					if let Some(s) = f.short {
						if s == c {
							found = true;
							let mut mult = false;
							for ff in matches.flags.iter_mut() {
								if ff.name == f.name {
									// already in matches
									ff.occurrences = if ff.multiple { ff.occurrences + 1 } else { 1 };
									mult = true;
								}
							}
							if ! mult {
								matches.flags.push(f.clone())
							}
							return "";
						}
					}
				}
				// Fails if argument supplied to binary isn't valid
				assert!(found == false);
				return "";
			}
		} else {
			// Short flag or opt
			let p_arg = arg.char_at(1);
			if p_arg == 'h' && self.needs_short_help {
				self.print_help();
			} else if p_arg == 'v' && self.needs_short_version {
				self.print_version();
			}
			for f in self.flags.iter() {
				if let Some(s) = f.short {
					if p_arg == s {
						found = true;
						matches.flags.push(f.clone());
					}
				}
			}
			for o in self.opts.iter() {
				if let Some(s) = o.short {
					if s == p_arg {
						return o.name;
					}
				}
			}
		}
		// Fails if argument supplied to binary isn't valid
		assert!(found == false);

		""
	}

	pub fn get_matches(&mut self) -> ArgMatches {

		let mut matches = ArgMatches::new(self);

		// let mut needs_val = false;
		let mut needs_val_of = "".to_string();
		let mut pos_counter = 1;
		for arg in env::args().collect::<Vec<String>>().tail() {
			let arg_slice = arg.as_slice();
			if ! needs_val_of.is_empty() {
				for o in self.opts.iter() {
					if needs_val_of == o.name.to_string() {
						matches.opts.push(OptArg{
							name: o.name,
						    short: o.short,
						    long: o.long,
						    help: o.help,
						    required: o.required,
						    value: Some(arg.clone())
						});
						needs_val_of.clear();
						break;
					}
				}
				continue;
			}
			if arg_slice.starts_with("--") {
				// Single flag, or option
				needs_val_of = self.parse_long_arg(&mut matches, arg_slice).to_string();

			} else if arg_slice.starts_with("-") {
				needs_val_of = self.parse_short_arg(&mut matches, arg_slice).to_string();
			} else {
				// Positional

				// Fails if no positionals are expected/possible
				assert!(self.positionals.is_empty() == false);

				for p in self.positionals.iter() {
					matches.positionals.push(PosArg{
						name: p.name,
						help: p.help,
						required: p.required,
						value: Some(arg.clone()),
						index: pos_counter
					});
					pos_counter += 1;
				}
			}

		}

		// Fails if we reached the end of args() but were still
		// expecting a value, such as ./fake -c
		// where -c takes a value
		assert!(needs_val_of.is_empty());

		matches
	}
}<|endoftext|>


<commit_before>use bytecount::naive_count_32;
use regex::Regex;

lazy_static! {
    static ref PAT_TOKENS: Regex = Regex::new(r#"(?xm)
          (?:\(:)
        | (?:=>\n\x20+)
        | (?:\n\x20+)
        | "
        | =
        | \(
        | \)
        | \s+
        | [^\(\)=\s"]+"#).expect("Failed to compile lexer regex");
}

#[derive(Debug, PartialEq)]
pub enum Token<'a> {
    StartBlock(i32),
    RightParen,
    Rocket(i32),
    Dedent,
    Text(i32, &'a str),
    Quote(i32),
}

pub fn lex(data: &str) -> Vec<Token> {
    let data_bytes = data.as_bytes();
    let mut lineno: i32 = 0;
    let mut last_match_start: usize = 0;
    let mut tokens: Vec<Token> = vec![];
    let mut indent: Vec<usize> = vec![0];

    for pat_match in PAT_TOKENS.find_iter(data) {
        lineno += naive_count_32(&data_bytes[last_match_start..pat_match.start()], b'\n') as i32;
        last_match_start = pat_match.start();
        let token_text = pat_match.as_str();
        let bytes = token_text.as_bytes();

        let token = match bytes[0] {
            b')' => Token::RightParen,
            b'"' => Token::Quote(lineno),
            _ if bytes == b"(:" => Token::StartBlock(lineno),
            _ if bytes.starts_with(b"=>\n") => {
                indent.push(bytes.len() - 3);
                Token::Rocket(lineno)
            }
            _ if bytes.starts_with(b"\n") => {
                let mut current_indentation_level =
                    *(indent.last().expect("Indentation stack is empty"));
                let new_indentation_level = token_text.len() - 1;

                while new_indentation_level < current_indentation_level {
                    indent.pop();
                    current_indentation_level =
                        *(indent.last().expect("Indentation stack is empty"));
                    tokens.push(Token::Dedent);
                }

                let new_end = token_text.len() - current_indentation_level;
                Token::Text(lineno, &token_text[..new_end])
            }
            _ => Token::Text(lineno, token_text),
        };

        tokens.push(token)
    }

    while indent.len() > 1 {
        tokens.push(Token::Dedent);
        indent.pop();
    }

    tokens
}

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

    #[test]
    fn test_empty() {
        assert_eq!(lex(""), vec![]);
    }

    #[test]
    fn test_expression() {
        assert_eq!(
            lex(r#"(:foo bar (:a "b c") "baz" )"#),
            vec![
                Token::StartBlock(0),
                Token::Text(0, "foo"),
                Token::Text(0, " "),
                Token::Text(0, "bar"),
                Token::Text(0, " "),
                Token::StartBlock(0),
                Token::Text(0, "a"),
                Token::Text(0, " "),
                Token::Quote(0),
                Token::Text(0, "b"),
                Token::Text(0, " "),
                Token::Text(0, "c"),
                Token::Quote(0),
                Token::RightParen,
                Token::Text(0, " "),
                Token::Quote(0),
                Token::Text(0, "baz"),
                Token::Quote(0),
                Token::Text(0, " "),
                Token::RightParen,
            ]
        );
    }

    #[test]
    fn test_rocket() {
        assert_eq!(
            lex(
                r#"
(:note "a title" =>
  stuff  1

  stuff 2

  (:note =>
    more stuff

    second =>paragraph

  closing nested

(:h2 foo)"#
            ),
            vec![
                Token::Text(0, "\n"),
                Token::StartBlock(1),
                Token::Text(1, "note"),
                Token::Text(1, " "),
                Token::Quote(1),
                Token::Text(1, "a"),
                Token::Text(1, " "),
                Token::Text(1, "title"),
                Token::Quote(1),
                Token::Text(1, " "),
                Token::Rocket(1),
                Token::Text(2, "stuff"),
                Token::Text(2, "  "),
                Token::Text(2, "1"),
                Token::Text(2, "\n\n"),
                Token::Text(4, "stuff"),
                Token::Text(4, " "),
                Token::Text(4, "2"),
                Token::Text(4, "\n\n"),
                Token::StartBlock(6),
                Token::Text(6, "note"),
                Token::Text(6, " "),
                Token::Rocket(6),
                Token::Text(7, "more"),
                Token::Text(7, " "),
                Token::Text(7, "stuff"),
                Token::Text(7, "\n\n"),
                Token::Text(9, "second"),
                Token::Text(9, " "),
                Token::Text(9, "="),
                Token::Text(9, ">paragraph"),
                Token::Dedent,
                Token::Text(9, "\n\n"),
                Token::Text(11, "closing"),
                Token::Text(11, " "),
                Token::Text(11, "nested"),
                Token::Dedent,
                Token::Text(11, "\n\n"),
                Token::StartBlock(13),
                Token::Text(13, "h2"),
                Token::Text(13, " "),
                Token::Text(13, "foo"),
                Token::RightParen,
            ]
        );
    }

    #[test]
    fn test_rocket_indentation() {
        assert_eq!(
            lex(
                r#"
(:note =>
  stuff
    stuff"#.trim()
            ),
            vec![
                Token::StartBlock(0),
                Token::Text(0, "note"),
                Token::Text(0, " "),
                Token::Rocket(0),
                Token::Text(1, "stuff"),
                Token::Text(1, "\n  "),
                Token::Text(2, "stuff"),
                Token::Dedent,
            ]
        );
    }
}
<commit_msg>lex: Properly close rocket block after \n+\x20+\n+<commit_after>use bytecount::naive_count_32;
use regex::Regex;

lazy_static! {
    static ref PAT_TOKENS: Regex = Regex::new(r#"(?xm)
          (?:\(:)
        | (?:=>\n\x20+)
        | (?:\n+\x20+)
        | "
        | =
        | \(
        | \)
        | \s+
        | [^\(\)=\s"]+"#).expect("Failed to compile lexer regex");
}

#[derive(Debug, PartialEq)]
pub enum Token<'a> {
    StartBlock(i32),
    RightParen,
    Rocket(i32),
    Dedent,
    Text(i32, &'a str),
    Quote(i32),
}

pub fn lex(data: &str) -> Vec<Token> {
    let data_bytes = data.as_bytes();
    let mut lineno: i32 = 0;
    let mut last_match_start: usize = 0;
    let mut tokens: Vec<Token> = vec![];
    let mut indent: Vec<usize> = vec![0];

    for pat_match in PAT_TOKENS.find_iter(data) {
        lineno += naive_count_32(&data_bytes[last_match_start..pat_match.start()], b'\n') as i32;
        last_match_start = pat_match.start();
        let token_text = pat_match.as_str();
        let bytes = token_text.as_bytes();

        let token = match bytes[0] {
            b')' => Token::RightParen,
            b'"' => Token::Quote(lineno),
            _ if bytes == b"(:" => Token::StartBlock(lineno),
            _ if bytes.starts_with(b"=>\n") => {
                indent.push(bytes.len() - 3);
                Token::Rocket(lineno)
            }
            _ if bytes.starts_with(b"\n") => {
                let mut current_indentation_level =
                    *(indent.last().expect("Indentation stack is empty"));
                let new_indentation_level = token_text.len() - 1;

                while new_indentation_level < current_indentation_level {
                    indent.pop();
                    current_indentation_level =
                        *(indent.last().expect("Indentation stack is empty"));
                    tokens.push(Token::Dedent);
                }

                let new_end = token_text.len() - current_indentation_level;
                Token::Text(lineno, &token_text[..new_end])
            }
            _ => Token::Text(lineno, token_text),
        };

        tokens.push(token)
    }

    while indent.len() > 1 {
        tokens.push(Token::Dedent);
        indent.pop();
    }

    tokens
}

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

    #[test]
    fn test_empty() {
        assert_eq!(lex(""), vec![]);
    }

    #[test]
    fn test_expression() {
        assert_eq!(
            lex(r#"(:foo bar (:a "b c") "baz" )"#),
            vec![
                Token::StartBlock(0),
                Token::Text(0, "foo"),
                Token::Text(0, " "),
                Token::Text(0, "bar"),
                Token::Text(0, " "),
                Token::StartBlock(0),
                Token::Text(0, "a"),
                Token::Text(0, " "),
                Token::Quote(0),
                Token::Text(0, "b"),
                Token::Text(0, " "),
                Token::Text(0, "c"),
                Token::Quote(0),
                Token::RightParen,
                Token::Text(0, " "),
                Token::Quote(0),
                Token::Text(0, "baz"),
                Token::Quote(0),
                Token::Text(0, " "),
                Token::RightParen,
            ]
        );
    }

    #[test]
    fn test_rocket() {
        assert_eq!(
            lex(
                "
(:note \"a title\" =>
  stuff  1

  stuff 2

  (:note =>
    more stuff

    second =>paragraph

  closing nested

\x20\x20

(:h2 foo)"
            ),
            vec![
                Token::Text(0, "\n"),
                Token::StartBlock(1),
                Token::Text(1, "note"),
                Token::Text(1, " "),
                Token::Quote(1),
                Token::Text(1, "a"),
                Token::Text(1, " "),
                Token::Text(1, "title"),
                Token::Quote(1),
                Token::Text(1, " "),
                Token::Rocket(1),
                Token::Text(2, "stuff"),
                Token::Text(2, "  "),
                Token::Text(2, "1"),
                Token::Text(2, "\n\n"),
                Token::Text(4, "stuff"),
                Token::Text(4, " "),
                Token::Text(4, "2"),
                Token::Text(4, "\n\n"),
                Token::StartBlock(6),
                Token::Text(6, "note"),
                Token::Text(6, " "),
                Token::Rocket(6),
                Token::Text(7, "more"),
                Token::Text(7, " "),
                Token::Text(7, "stuff"),
                Token::Text(7, "\n\n"),
                Token::Text(9, "second"),
                Token::Text(9, " "),
                Token::Text(9, "="),
                Token::Text(9, ">paragraph"),
                Token::Dedent,
                Token::Text(9, "\n\n"),
                Token::Text(11, "closing"),
                Token::Text(11, " "),
                Token::Text(11, "nested"),
                Token::Text(11, "\n\n"),
                Token::Dedent,
                Token::Text(13, "\n\n"),
                Token::StartBlock(15),
                Token::Text(15, "h2"),
                Token::Text(15, " "),
                Token::Text(15, "foo"),
                Token::RightParen,
            ]
        );
    }

    #[test]
    fn test_rocket_indentation() {
        assert_eq!(
            lex(
                r#"
(:note =>
  stuff
    stuff"#.trim()
            ),
            vec![
                Token::StartBlock(0),
                Token::Text(0, "note"),
                Token::Text(0, " "),
                Token::Rocket(0),
                Token::Text(1, "stuff"),
                Token::Text(1, "\n  "),
                Token::Text(2, "stuff"),
                Token::Dedent,
            ]
        );
    }
}
<|endoftext|>


<commit_before>/* Copyright (c) 2014, Peter Nelson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#![crate_name = "jit"]
#![allow(raw_pointer_deriving, dead_code, non_camel_case_types, non_upper_case_globals, unknown_features)]
#![deny(unused_parens, unknown_lints, unreachable_code, unused_allocation, unused_allocation, unused_must_use)]
#![feature(globs, macro_rules, slicing_syntax, unboxed_closures, unsafe_destructor, phase)]
#![stable]
//! This crate wraps LibJIT in an idiomatic style.
//! For example, here's a quick example which makes a multiply function using LibJIT:
//!
//! ```rust
//! extern crate jit;
//! use jit::{Context, UncompiledFunction, get_type};
//! fn main() {
//!     // make a new context to make functions on
//!     let ref ctx = Context::new();
//!     // get the type of the function
//!     let sig = get_type::<fn(int, int) -> int>();
//!     // make the function
//!     let func = UncompiledFunction::new(ctx, sig);
//!     ctx.build(|| {
//!         let ref x = func[0];
//!         let ref y = func[1];
//!         let ref result = func.insn_mul(x, y);
//!         func.insn_return(result);
//!     });
//!     // compile the IR and get the machine code as a function
//!     let mul = func.compile_with::<(int, int), int>(|mul| {
//!         assert_eq!(mul((4, 5)), 20);
//!     });
//! }
//! ```
extern crate libc;
#[cfg(test)]
extern crate test;
extern crate "libjit-sys" as raw;
use raw::{
    jit_init,
    jit_uses_interpreter,
    jit_supports_threads,
    jit_supports_virtual_memory
};
pub use raw::{
    jit_nint,
    jit_nuint
};
pub use compile::Compile;
pub use context::Context;
pub use function::*;
pub use label::Label;
pub use types::*;
pub use types::get as get_type;
pub use util::NativeRef;
pub use value::Value;

/// Initialise the library and prepare for operations
#[inline]
pub fn init() -> () {
    unsafe {
        jit_init()
    }
}
/// Check if the JIT is using a fallback interpreter
#[inline]
pub fn uses_interpreter() -> bool {
    unsafe {
        jit_uses_interpreter() != 0
    }
}
/// Check if the JIT supports theads
#[inline]
pub fn supports_threads() -> bool {
    unsafe {
        jit_supports_threads() != 0
    }
}
/// Check if the JIT supports virtual memory
#[inline]
pub fn supports_virtual_memory() -> bool {
    unsafe {
        jit_supports_virtual_memory() != 0
    }
}
#[macro_escape]
mod macros;
mod context;
mod compile;
mod elf;
mod function;
mod label;
#[cfg(test)]
mod tests;
mod types;
mod util;
mod value;<commit_msg>Fix example in docs<commit_after>/* Copyright (c) 2014, Peter Nelson
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
#![crate_name = "jit"]
#![allow(raw_pointer_deriving, dead_code, non_camel_case_types, non_upper_case_globals, unknown_features)]
#![deny(unused_parens, unknown_lints, unreachable_code, unused_allocation, unused_allocation, unused_must_use)]
#![feature(globs, macro_rules, slicing_syntax, unboxed_closures, unsafe_destructor, phase)]
#![stable]
//! This crate wraps LibJIT in an idiomatic style.
//! For example, here's a quick example which makes a multiply function using LibJIT:
//!
//! ```rust
//! extern crate jit;
//! use jit::{Context, get_type};
//! fn main() {
//!     // make a new context to make functions on
//!     let ref ctx = Context::new();
//!     // get the type of the function
//!     let sig = get_type::<fn(int, int) -> int>();
//!     // make the function
//!     let func = ctx.build_func(sig, |func| {
//!         let ref x = func[0];
//!         let ref y = func[1];
//!         let ref result = func.insn_mul(x, y);
//!         func.insn_return(result);
//!     });
//!     // compile the IR and get the machine code as a function
//!     let mul = func.with::<(int, int), int>(|mul| {
//!         assert_eq!(mul((4, 5)), 20);
//!     });
//! }
//! ```
extern crate libc;
#[cfg(test)]
extern crate test;
extern crate "libjit-sys" as raw;
use raw::{
    jit_init,
    jit_uses_interpreter,
    jit_supports_threads,
    jit_supports_virtual_memory
};
pub use raw::{
    jit_nint,
    jit_nuint
};
pub use compile::Compile;
pub use context::Context;
pub use function::*;
pub use label::Label;
pub use types::*;
pub use types::get as get_type;
pub use util::NativeRef;
pub use value::Value;

/// Initialise the library and prepare for operations
#[inline]
pub fn init() -> () {
    unsafe {
        jit_init()
    }
}
/// Check if the JIT is using a fallback interpreter
#[inline]
pub fn uses_interpreter() -> bool {
    unsafe {
        jit_uses_interpreter() != 0
    }
}
/// Check if the JIT supports theads
#[inline]
pub fn supports_threads() -> bool {
    unsafe {
        jit_supports_threads() != 0
    }
}
/// Check if the JIT supports virtual memory
#[inline]
pub fn supports_virtual_memory() -> bool {
    unsafe {
        jit_supports_virtual_memory() != 0
    }
}
#[macro_escape]
mod macros;
mod context;
mod compile;
mod elf;
mod function;
mod label;
#[cfg(test)]
mod tests;
mod types;
mod util;
mod value;<|endoftext|>


<commit_before>extern crate lmdb;
extern crate lmdb_sys;

use std::{result, str};
use std::path::Path;
use lmdb::{Cursor, DUP_SORT, INTEGER_KEY};
use lmdb::Transaction as LmdbTransaction;

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Error {
    DbCreateError,
    DbOpenError,
    DbWriteError,
    DbCorruptError,
    ParseError,
    TransactionError,
    PathError,
    NotFoundError,
}

pub type Result<T> = result::Result<T, Error>;

pub struct LmdbAdapter {
    env: lmdb::Environment,
    nodes: lmdb::Database,
    entries: lmdb::Database,
}

pub struct RwTransaction<'a>(lmdb::RwTransaction<'a>);
pub struct RoTransaction<'a>(lmdb::RoTransaction<'a>);

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

pub struct Node<'a> {
    pub id: Id,
    pub parent_id: Id,
    pub name: &'a str,
}

pub struct Entry<'a> {
    pub node: Node<'a>,
    pub objectclass: &'a str,
}

// Ids are 64-bit integers in host-native byte order
// LMDB has special optimizations for host-native integers as keys
impl Id {
    fn root() -> Id {
        Id(0)
    }

    fn from_bytes(bytes: &[u8]) -> Result<Id> {
        if bytes.len() != 8 {
            return Err(Error::ParseError);
        }

        let mut id = [0u8; 8];
        id.copy_from_slice(&bytes[0..8]);

        Ok(Id(unsafe { std::mem::transmute(id) }))
    }

    fn as_bytes(self) -> [u8; 8] {
        let Id(id) = self;
        unsafe { std::mem::transmute(id) }
    }

    fn next(self) -> Id {
        let Id(id) = self;
        Id(id + 1)
    }
}

impl<'a> Node<'a> {
    fn root() -> Node<'a> {
        Node {
            id: Id::root(),
            parent_id: Id::root(),
            name: "/",
        }
    }

    fn from_parent_id_and_bytes(parent_id: Id, bytes: &[u8]) -> Result<Node> {
        if bytes.len() < 8 {
            return Err(Error::DbCorruptError);
        }

        let id = try!(Id::from_bytes(&bytes[0..8]));
        let name = try!(std::str::from_utf8(&bytes[8..]).map_err(|_err| Error::DbCorruptError));

        Ok(Node {
            id: id,
            parent_id: parent_id,
            name: name,
        })
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(8 + self.name.len());
        bytes.extend_from_slice(&self.id.as_bytes());
        bytes.extend_from_slice(self.name.as_bytes());
        bytes
    }
}

impl LmdbAdapter {
    pub fn create_database(path: &Path) -> Result<LmdbAdapter> {
        let env = try!(lmdb::Environment::new()
                           .set_max_dbs(8)
                           .open_with_permissions(&path, 0o600)
                           .map_err(|_err| Error::DbCreateError));

        let nodes = try!(env.create_db(Some("nodes"), INTEGER_KEY | DUP_SORT)
                            .map_err(|_err| Error::DbCreateError));

        let entries = try!(env.create_db(Some("entries"), INTEGER_KEY)
                              .map_err(|_err| Error::DbCreateError));

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn open_database(path: &Path) -> Result<LmdbAdapter> {
        let env = try!(lmdb::Environment::new().open(&path).map_err(|_err| Error::DbOpenError));

        let nodes = try!(env.open_db(Some("nodes")).map_err(|_err| Error::DbOpenError));

        let entries = try!(env.open_db(Some("entries")).map_err(|_err| Error::DbOpenError));

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn rw_transaction(&self) -> Result<RwTransaction> {
        match self.env.begin_rw_txn() {
            Ok(txn) => Ok(RwTransaction(txn)),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn ro_transaction(&self) -> Result<RoTransaction> {
        match self.env.begin_ro_txn() {
            Ok(txn) => Ok(RoTransaction(txn)),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn next_available_id<T: Transaction>(&self, txn: &T) -> Result<Id> {
        let cursor = try!(txn.open_ro_cursor(self.nodes)
                             .map_err(|_err| Error::TransactionError));

        let last_id = match cursor.get(None, None, lmdb_sys::MDB_LAST) {
            Ok((id, _)) => Id::from_bytes(id.unwrap()).unwrap(),
            Err(_) => Id::root(),
        };

        Ok(last_id.next())
    }

    pub fn create_entry<'a>(&'a self,
                            txn: &'a mut RwTransaction,
                            id: Id,
                            parent_id: Id,
                            name: &'a str,
                            objectclass: &'a str)
                            -> Result<Entry> {
        let node = Node {
            id: id,
            parent_id: parent_id,
            name: name,
        };

        try!(txn.put(self.nodes,
                     &parent_id.as_bytes(),
                     &node.to_bytes())
                .map_err(|_err| Error::DbWriteError));

        try!(txn.put(self.entries,
                     &id.as_bytes(),
                     &objectclass.as_bytes())
                .map_err(|_err| Error::DbWriteError));

        Ok(Entry {
            node: node,
            objectclass: objectclass,
        })
    }

    pub fn find_entry<'a, T: Transaction>(&'a self, txn: &'a T, path: &str) -> Result<Entry> {
        let node = try!(self.find_node(txn, path));

        let entry_bytes = try!(txn.get(self.entries, &node.id.as_bytes())
                                  .map_err(|_err| Error::DbCorruptError));

        let objectclass = try!(std::str::from_utf8(&entry_bytes)
                                   .map_err(|_err| Error::DbCorruptError));

        Ok(Entry {
            node: node,
            objectclass: objectclass,
        })
    }

    fn find_node<T: Transaction>(&self, txn: &T, path: &str) -> Result<Node> {
        let all_components: Vec<&str> = path.split("/").collect();

        if all_components.is_empty() {
            return Err(Error::PathError);
        }

        let (prefix, components) = all_components.split_first().unwrap();

        // Does the path start with something other than "/"?
        if !prefix.is_empty() {
            return Err(Error::PathError);
        }

        // Perform a hierarchical path lookup
        // TODO: since LMDB is ordered, we could e.g. perform a binary search
        components.iter().fold(Ok(Node::root()), |parent_node, component| {
            let parent_id = try!(parent_node).id;

            let mut cursor = try!(txn.open_ro_cursor(self.nodes)
                                     .map_err(|_err| Error::DbCorruptError));

            let mut child_node = None;

            for (id, node_bytes) in cursor.iter_from(parent_id.as_bytes()) {
                if id != parent_id.as_bytes() {
                    return Err(Error::NotFoundError);
                }

                let node = try!(Node::from_parent_id_and_bytes(parent_id, node_bytes));

                if node.name == *component {
                    child_node = Some(node);
                    break;
                }
            }

            child_node.ok_or(Error::NotFoundError)
        })
    }
}

pub trait Transaction {
    fn get(&self, database: lmdb::Database, key: &[u8]) -> Result<&[u8]>;
    fn commit(self) -> Result<()>;
    fn open_ro_cursor(&self, db: lmdb::Database) -> lmdb::Result<lmdb::RoCursor>;
}

impl<'a> Transaction for RwTransaction<'a> {
    fn get(&self, database: lmdb::Database, key: &[u8]) -> Result<&[u8]> {
        self.0.get(database, &key).map_err(|_err| Error::TransactionError)
    }

    fn commit(self) -> Result<()> {
        self.0.commit().map_err(|_err| Error::TransactionError)
    }

    fn open_ro_cursor(&self, db: lmdb::Database) -> lmdb::Result<lmdb::RoCursor> {
        self.0.open_ro_cursor(db)
    }
}

impl<'a> Transaction for RoTransaction<'a> {
    fn get(&self, database: lmdb::Database, key: &[u8]) -> Result<&[u8]> {
        self.0.get(database, &key).map_err(|_err| Error::TransactionError)
    }

    fn commit(self) -> Result<()> {
        self.0.commit().map_err(|_err| Error::TransactionError)
    }

    fn open_ro_cursor(&self, db: lmdb::Database) -> lmdb::Result<lmdb::RoCursor> {
        self.0.open_ro_cursor(db)
    }
}

impl<'a> RwTransaction<'a> {
    fn put(&mut self, database: lmdb::Database, key: &[u8], data: &[u8]) -> Result<()> {
        self.0.put(database, &key, &data, lmdb::WriteFlags::empty()).map_err(|_err| Error::TransactionError)
    }
}

#[cfg(test)]
mod tests {
    use std::path::Path;
    use {LmdbAdapter, Id, Transaction};

    #[test]
    fn test_entry_lookup() {
        let path = Path::new("./tmp");
        let adapter = LmdbAdapter::create_database(path).unwrap();

        {
            let mut txn = adapter.rw_transaction().unwrap();

            let domain_id = adapter.next_available_id(&txn).unwrap();
            adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

            let hosts_id = domain_id.next();
            adapter.create_entry(&mut txn, hosts_id, domain_id, "hosts", "ou").unwrap();

            let host_id = hosts_id.next();
            adapter.create_entry(&mut txn, host_id, hosts_id, "master.example.com", "host").unwrap();

            txn.commit().unwrap();
        }

        {
            let txn = adapter.ro_transaction().unwrap();

            {
                let entry = adapter.find_entry(&txn, "/example.com/hosts/master.example.com")
                                   .unwrap();

                assert_eq!(entry.node.name, "master.example.com");
                assert_eq!(entry.objectclass, "host");
            }

            txn.commit().unwrap();
        }
    }
}
<commit_msg>Extract create_database() test helper<commit_after>extern crate lmdb;
extern crate lmdb_sys;

use std::{result, str};
use std::path::Path;
use lmdb::{Cursor, DUP_SORT, INTEGER_KEY};
use lmdb::Transaction as LmdbTransaction;

#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum Error {
    DbCreateError,
    DbOpenError,
    DbWriteError,
    DbCorruptError,
    ParseError,
    TransactionError,
    PathError,
    NotFoundError,
}

pub type Result<T> = result::Result<T, Error>;

pub struct LmdbAdapter {
    env: lmdb::Environment,
    nodes: lmdb::Database,
    entries: lmdb::Database,
}

pub struct RwTransaction<'a>(lmdb::RwTransaction<'a>);
pub struct RoTransaction<'a>(lmdb::RoTransaction<'a>);

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

pub struct Node<'a> {
    pub id: Id,
    pub parent_id: Id,
    pub name: &'a str,
}

pub struct Entry<'a> {
    pub node: Node<'a>,
    pub objectclass: &'a str,
}

// Ids are 64-bit integers in host-native byte order
// LMDB has special optimizations for host-native integers as keys
impl Id {
    fn root() -> Id {
        Id(0)
    }

    fn from_bytes(bytes: &[u8]) -> Result<Id> {
        if bytes.len() != 8 {
            return Err(Error::ParseError);
        }

        let mut id = [0u8; 8];
        id.copy_from_slice(&bytes[0..8]);

        Ok(Id(unsafe { std::mem::transmute(id) }))
    }

    fn as_bytes(self) -> [u8; 8] {
        let Id(id) = self;
        unsafe { std::mem::transmute(id) }
    }

    fn next(self) -> Id {
        let Id(id) = self;
        Id(id + 1)
    }
}

impl<'a> Node<'a> {
    fn root() -> Node<'a> {
        Node {
            id: Id::root(),
            parent_id: Id::root(),
            name: "/",
        }
    }

    fn from_parent_id_and_bytes(parent_id: Id, bytes: &[u8]) -> Result<Node> {
        if bytes.len() < 8 {
            return Err(Error::DbCorruptError);
        }

        let id = try!(Id::from_bytes(&bytes[0..8]));
        let name = try!(std::str::from_utf8(&bytes[8..]).map_err(|_err| Error::DbCorruptError));

        Ok(Node {
            id: id,
            parent_id: parent_id,
            name: name,
        })
    }

    fn to_bytes(&self) -> Vec<u8> {
        let mut bytes = Vec::with_capacity(8 + self.name.len());
        bytes.extend_from_slice(&self.id.as_bytes());
        bytes.extend_from_slice(self.name.as_bytes());
        bytes
    }
}

impl LmdbAdapter {
    pub fn create_database(path: &Path) -> Result<LmdbAdapter> {
        let env = try!(lmdb::Environment::new()
                           .set_max_dbs(8)
                           .open_with_permissions(&path, 0o600)
                           .map_err(|_err| Error::DbCreateError));

        let nodes = try!(env.create_db(Some("nodes"), INTEGER_KEY | DUP_SORT)
                            .map_err(|_err| Error::DbCreateError));

        let entries = try!(env.create_db(Some("entries"), INTEGER_KEY)
                              .map_err(|_err| Error::DbCreateError));

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn open_database(path: &Path) -> Result<LmdbAdapter> {
        let env = try!(lmdb::Environment::new().open(&path).map_err(|_err| Error::DbOpenError));

        let nodes = try!(env.open_db(Some("nodes")).map_err(|_err| Error::DbOpenError));

        let entries = try!(env.open_db(Some("entries")).map_err(|_err| Error::DbOpenError));

        Ok(LmdbAdapter {
            env: env,
            nodes: nodes,
            entries: entries,
        })
    }

    pub fn rw_transaction(&self) -> Result<RwTransaction> {
        match self.env.begin_rw_txn() {
            Ok(txn) => Ok(RwTransaction(txn)),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn ro_transaction(&self) -> Result<RoTransaction> {
        match self.env.begin_ro_txn() {
            Ok(txn) => Ok(RoTransaction(txn)),
            Err(_) => Err(Error::TransactionError),
        }
    }

    pub fn next_available_id<T: Transaction>(&self, txn: &T) -> Result<Id> {
        let cursor = try!(txn.open_ro_cursor(self.nodes)
                             .map_err(|_err| Error::TransactionError));

        let last_id = match cursor.get(None, None, lmdb_sys::MDB_LAST) {
            Ok((id, _)) => Id::from_bytes(id.unwrap()).unwrap(),
            Err(_) => Id::root(),
        };

        Ok(last_id.next())
    }

    pub fn create_entry<'a>(&'a self,
                            txn: &'a mut RwTransaction,
                            id: Id,
                            parent_id: Id,
                            name: &'a str,
                            objectclass: &'a str)
                            -> Result<Entry> {
        let node = Node {
            id: id,
            parent_id: parent_id,
            name: name,
        };

        try!(txn.put(self.nodes,
                     &parent_id.as_bytes(),
                     &node.to_bytes())
                .map_err(|_err| Error::DbWriteError));

        try!(txn.put(self.entries,
                     &id.as_bytes(),
                     &objectclass.as_bytes())
                .map_err(|_err| Error::DbWriteError));

        Ok(Entry {
            node: node,
            objectclass: objectclass,
        })
    }

    pub fn find_entry<'a, T: Transaction>(&'a self, txn: &'a T, path: &str) -> Result<Entry> {
        let node = try!(self.find_node(txn, path));

        let entry_bytes = try!(txn.get(self.entries, &node.id.as_bytes())
                                  .map_err(|_err| Error::DbCorruptError));

        let objectclass = try!(std::str::from_utf8(&entry_bytes)
                                   .map_err(|_err| Error::DbCorruptError));

        Ok(Entry {
            node: node,
            objectclass: objectclass,
        })
    }

    fn find_node<T: Transaction>(&self, txn: &T, path: &str) -> Result<Node> {
        let all_components: Vec<&str> = path.split("/").collect();

        if all_components.is_empty() {
            return Err(Error::PathError);
        }

        let (prefix, components) = all_components.split_first().unwrap();

        // Does the path start with something other than "/"?
        if !prefix.is_empty() {
            return Err(Error::PathError);
        }

        // Perform a hierarchical path lookup
        // TODO: since LMDB is ordered, we could e.g. perform a binary search
        components.iter().fold(Ok(Node::root()), |parent_node, component| {
            let parent_id = try!(parent_node).id;

            let mut cursor = try!(txn.open_ro_cursor(self.nodes)
                                     .map_err(|_err| Error::DbCorruptError));

            let mut child_node = None;

            for (id, node_bytes) in cursor.iter_from(parent_id.as_bytes()) {
                if id != parent_id.as_bytes() {
                    return Err(Error::NotFoundError);
                }

                let node = try!(Node::from_parent_id_and_bytes(parent_id, node_bytes));

                if node.name == *component {
                    child_node = Some(node);
                    break;
                }
            }

            child_node.ok_or(Error::NotFoundError)
        })
    }
}

pub trait Transaction {
    fn get(&self, database: lmdb::Database, key: &[u8]) -> Result<&[u8]>;
    fn commit(self) -> Result<()>;
    fn open_ro_cursor(&self, db: lmdb::Database) -> lmdb::Result<lmdb::RoCursor>;
}

impl<'a> Transaction for RwTransaction<'a> {
    fn get(&self, database: lmdb::Database, key: &[u8]) -> Result<&[u8]> {
        self.0.get(database, &key).map_err(|_err| Error::TransactionError)
    }

    fn commit(self) -> Result<()> {
        self.0.commit().map_err(|_err| Error::TransactionError)
    }

    fn open_ro_cursor(&self, db: lmdb::Database) -> lmdb::Result<lmdb::RoCursor> {
        self.0.open_ro_cursor(db)
    }
}

impl<'a> Transaction for RoTransaction<'a> {
    fn get(&self, database: lmdb::Database, key: &[u8]) -> Result<&[u8]> {
        self.0.get(database, &key).map_err(|_err| Error::TransactionError)
    }

    fn commit(self) -> Result<()> {
        self.0.commit().map_err(|_err| Error::TransactionError)
    }

    fn open_ro_cursor(&self, db: lmdb::Database) -> lmdb::Result<lmdb::RoCursor> {
        self.0.open_ro_cursor(db)
    }
}

impl<'a> RwTransaction<'a> {
    fn put(&mut self, database: lmdb::Database, key: &[u8], data: &[u8]) -> Result<()> {
        self.0.put(database, &key, &data, lmdb::WriteFlags::empty()).map_err(|_err| Error::TransactionError)
    }
}

#[cfg(test)]
mod tests {
    use std::fs;
    use std::path::Path;
    use {LmdbAdapter, Id, Transaction};

    fn create_database() -> LmdbAdapter {
        let path = Path::new("./tmp");

        if !path.exists() {
            panic!("Unable to find repo-local temp path")
        }

        let data = path.join("data.mdb");
        if data.exists() {
            fs::remove_file(data).unwrap()
        }

        let lock = path.join("lock.mdb");
        if lock.exists() {
            fs::remove_file(lock).unwrap()
        }

        LmdbAdapter::create_database(path).unwrap()
    }

    #[test]
    fn test_entry_lookup() {
        let adapter = create_database();

        {
            let mut txn = adapter.rw_transaction().unwrap();

            let domain_id = adapter.next_available_id(&txn).unwrap();
            adapter.create_entry(&mut txn, domain_id, Id::root(), "example.com", "domain").unwrap();

            let hosts_id = domain_id.next();
            adapter.create_entry(&mut txn, hosts_id, domain_id, "hosts", "ou").unwrap();

            let host_id = hosts_id.next();
            adapter.create_entry(&mut txn, host_id, hosts_id, "master.example.com", "host").unwrap();

            txn.commit().unwrap();
        }

        {
            let txn = adapter.ro_transaction().unwrap();

            {
                let entry = adapter.find_entry(&txn, "/example.com/hosts/master.example.com")
                                   .unwrap();

                assert_eq!(entry.node.name, "master.example.com");
                assert_eq!(entry.objectclass, "host");
            }

            txn.commit().unwrap();
        }
    }
}
<|endoftext|>


<commit_before>use std::error::FromError;
use std::io::{BufferedStream, IoError};
use std::io::net::tcp::TcpStream;

#[derive(Show)]
pub enum MemcacheError {
    InternalIoError(IoError),
    ServerError
}

impl FromError<IoError> for MemcacheError {
    fn from_error(err: IoError) -> MemcacheError {
        MemcacheError::InternalIoError(err)
    }
}

pub type MemcacheResult<T> = Result<T, MemcacheError>;

pub struct Connection {
    pub host: String,
    pub port: u16,
    stream: BufferedStream<TcpStream>,
}

impl Connection {
    pub fn flush(&mut self) -> MemcacheResult<()> {
        try!{ self.stream.write_str("flush_all\r\n") };
        try!{ self.stream.flush() };
        let result = try!{ self.stream.read_line() };
        if result.as_slice() != "OK\r\n" {
            return Err(MemcacheError::ServerError);
        }
        return Ok(());
    }

    pub fn delete(&mut self, key: &str) -> MemcacheResult<bool> {
        try!{ self.stream.write_str(format!("delete {}\r\n", key).as_slice()) };
        try!{ self.stream.flush() };
        let result = try! { self.stream.read_line() };
        if result.as_slice() == "DELETED\r\n" {
            return Ok(true);
        } else if result.as_slice() == "NOT_FOUND\r\n" {
            return Ok(false);
        } else {
            return Err(MemcacheError::ServerError);
        }
    }

    pub fn get(&mut self, key: &str) -> MemcacheResult<Option<Vec<u8>>> {
        try!{ self.stream.write_str(format!("get {}\r\n", key).as_slice()) };
        try!{ self.stream.flush() };
        let result = try!{ self.stream.read_line() };
        if result.as_slice() == "END\r\n" {
            return Ok(None);
        }
        let header: Vec<&str> = result.split(' ').collect();
        if header.len() != 4 || header[0] != "VALUE" || header[1] != key {
            return Err(MemcacheError::ServerError);
        }
        let length: uint = match header[3].trim().parse() {
            Some(length) => { length }
            None => { return Err(MemcacheError::ServerError); }
        };
        let value = try!{ self.stream.read_exact(length) };
        return Ok(Some(value));
    }

    pub fn set(&mut self, key: &str, value: &[u8], exptime: int) -> MemcacheResult<bool> {
        try!{ self.stream.write_str(format!("set {} 0 {} {}\r\n", key, exptime, value.len()).as_slice()) };
        try!{ self.stream.write(value) };
        try!{ self.stream.write_str("\r\n") };
        try!{ self.stream.flush() };
        let result = try!{ self.stream.read_line() };
        if result.as_slice() == "STORED\r\n" {
            return Ok(true);
        } else if result.as_slice() == "NOT_STORED\r\n" {
            return Ok(false);
        }
        return Err(MemcacheError::ServerError);
    }

    pub fn connect(host: &str, port: u16) -> MemcacheResult<Connection> {
        let stream = try!{ TcpStream::connect((host, port)) };
        return Ok(Connection{
            host: host.to_string(),
            port: port,
            stream: BufferedStream::new(stream)
        });
    }
}

#[test]
fn test_connect() -> () {
    Connection::connect("localhost", 2333).unwrap();
}

#[test]
fn test_flush() -> () {
    let mut conn = Connection::connect("localhost", 2333).unwrap();
    conn.flush().unwrap();
}

#[test]
fn test_set() -> () {
    let mut conn = Connection::connect("localhost", 2333).unwrap();
    conn.flush().unwrap();
    assert!{ conn.set("foo", b"bar", 10).unwrap() == true };
}

#[test]
fn test_get() -> () {
    let mut conn = Connection::connect("localhost", 2333).unwrap();
    conn.flush().unwrap();
    assert!{ conn.get("foo").unwrap() == None };

    assert!{ conn.set("foo", b"bar", 0).unwrap() == true };
    assert!{ conn.get("foo").unwrap().unwrap().as_slice() == b"bar" };
}

#[test]
fn test_delete() -> () {
    let mut conn = Connection::connect("localhost", 2333).unwrap();
    conn.flush().unwrap();
    assert!{ conn.delete("foo").unwrap() == false };
}
<commit_msg>now flags works well<commit_after>use std::error::FromError;
use std::io::{BufferedStream, IoError};
use std::io::net::tcp::TcpStream;

#[derive(Show)]
pub enum MemcacheError {
    InternalIoError(IoError),
    ServerError
}

impl FromError<IoError> for MemcacheError {
    fn from_error(err: IoError) -> MemcacheError {
        MemcacheError::InternalIoError(err)
    }
}

pub type MemcacheResult<T> = Result<T, MemcacheError>;

pub struct Connection {
    pub host: String,
    pub port: u16,
    stream: BufferedStream<TcpStream>,
}

impl Connection {
    pub fn flush(&mut self) -> MemcacheResult<()> {
        try!{ self.stream.write_str("flush_all\r\n") };
        try!{ self.stream.flush() };
        let result = try!{ self.stream.read_line() };
        if result.as_slice() != "OK\r\n" {
            return Err(MemcacheError::ServerError);
        }
        return Ok(());
    }

    pub fn delete(&mut self, key: &str) -> MemcacheResult<bool> {
        try!{ self.stream.write_str(format!("delete {}\r\n", key).as_slice()) };
        try!{ self.stream.flush() };
        let result = try! { self.stream.read_line() };
        if result.as_slice() == "DELETED\r\n" {
            return Ok(true);
        } else if result.as_slice() == "NOT_FOUND\r\n" {
            return Ok(false);
        } else {
            return Err(MemcacheError::ServerError);
        }
    }

    pub fn get(&mut self, key: &str) -> MemcacheResult<Option<(Vec<u8>, u16)>> {
        try!{ self.stream.write_str(format!("get {}\r\n", key).as_slice()) };
        try!{ self.stream.flush() };
        let result = try!{ self.stream.read_line() };
        if result.as_slice() == "END\r\n" {
            return Ok(None);
        }
        let header: Vec<&str> = result.split(' ').collect();
        if header.len() != 4 || header[0] != "VALUE" || header[1] != key {
            return Err(MemcacheError::ServerError);
        }
        let flags: u16 = match header[2].trim().parse() {
            Some(flags) => { flags }
            None => { return Err(MemcacheError::ServerError); }
        };
        let length: uint = match header[3].trim().parse() {
            Some(length) => { length }
            None => { return Err(MemcacheError::ServerError); }
        };
        let value = try!{ self.stream.read_exact(length) };
        return Ok(Some((value, flags)));
    }

    pub fn set(&mut self, key: &str, value: &[u8], exptime: int, flags: u16) -> MemcacheResult<bool> {
        try!{ self.stream.write_str(format!("set {} {} {} {}\r\n", key, flags, exptime, value.len()).as_slice()) };
        try!{ self.stream.write(value) };
        try!{ self.stream.write_str("\r\n") };
        try!{ self.stream.flush() };
        let result = try!{ self.stream.read_line() };
        if result.as_slice() == "STORED\r\n" {
            return Ok(true);
        } else if result.as_slice() == "NOT_STORED\r\n" {
            return Ok(false);
        }
        return Err(MemcacheError::ServerError);
    }

    pub fn connect(host: &str, port: u16) -> MemcacheResult<Connection> {
        let stream = try!{ TcpStream::connect((host, port)) };
        return Ok(Connection{
            host: host.to_string(),
            port: port,
            stream: BufferedStream::new(stream)
        });
    }
}

#[test]
fn test_connect() -> () {
    Connection::connect("localhost", 2333).unwrap();
}

#[test]
fn test_flush() -> () {
    let mut conn = Connection::connect("localhost", 2333).unwrap();
    conn.flush().unwrap();
}

#[test]
fn test_set() -> () {
    let mut conn = Connection::connect("localhost", 2333).unwrap();
    conn.flush().unwrap();
    assert!{ conn.set("foo", b"bar", 10, 0).unwrap() == true };
}

#[test]
fn test_get() -> () {
    let mut conn = Connection::connect("localhost", 2333).unwrap();
    conn.flush().unwrap();
    assert!{ conn.get("foo").unwrap() == None };

    assert!{ conn.set("foo", b"bar", 0, 10).unwrap() == true };
    let result = conn.get("foo").unwrap().unwrap();
    assert!{ result.0 == b"bar" };
    assert!{ result.1 == 10 };
}

#[test]
fn test_delete() -> () {
    let mut conn = Connection::connect("localhost", 2333).unwrap();
    conn.flush().unwrap();
    assert!{ conn.delete("foo").unwrap() == false };
}
<|endoftext|>


<commit_before>// Many of my decisions were based off the following document
// https://web.archive.org/web/20140727185616/http://algs4.cs.princeton.edu/33balanced/

use std::cmp::Ord;
use std::option::{None, Option, Some};

/// Four
enum Four<V: Ord> {
    InternalFour(V, V, V, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>),
    LeafFour(V, V, V),
}

impl <V: Ord> Four<V> {
    fn to_two(self) -> Two<V> {
        match self {
            LeafFour(v1, v2, v3) =>
                Two(v2,
                    box LeafTwoNode(LeafTwo(v1)),
                    box LeafTwoNode(LeafTwo(v3))),
            InternalFour(v1, v2, v3, n1, n2, n3, n4) =>
                Two(v2,
                    box TwoNode(Two(v1, n1, n2)),
                    box TwoNode(Two(v3, n3, n4))),
        }
    }
}

/// InsertResult
enum InsertResult<V: Ord> {
    Fit(Node<V>),
    Split(Four<V>),
}

/// Direction
enum Direction {
    Left,
    Middle,
    Right,
    Leaf,
}

/// Two
pub struct Two<V: Ord>(pub V, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Two<V> {
    fn to_node(self) -> Node<V> { TwoNode(self) }

    fn to_three(self, other_value: V, other_node: Box<Node<V>>) -> Three<V> {
        let Two(self_value, self_left, self_middle) = self;
        if self_value > other_value {
            Three(other_value, self_value, other_node, self_left, self_middle)
        } else {
            Three(self_value, other_value, self_left, self_middle, other_node)
        }
    }
}

/// Three
pub struct Three<V: Ord>(pub V, pub V, pub Box<Node<V>>, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Three<V> {
    fn to_node(self) -> Node<V> { ThreeNode(self) }

    fn to_four(self, other_value: V, other_node: Box<Node<V>>) -> Four<V> {
        let Three(self_value1, self_value2, self_left, self_middle, self_right) = self;
        if other_value < self_value1 {
            InternalFour(other_value, self_value1, self_value2, other_node, self_left, self_middle, self_right)
        } else {
            InternalFour(self_value1, self_value2, other_value, self_left, self_middle, self_right, other_node)
        }
    }
}

/// LeafTwo
pub struct LeafTwo<V: Ord>(pub V);

/// LeafThree
pub struct LeafThree<V: Ord>(pub V, pub V);

impl <V: Ord> LeafThree<V> {
    fn to_four(self, value: V) -> Four<V> {
        let LeafThree(value1, value2) = self;
        if value > value2      { LeafFour(value1, value2, value) }
        else if value < value1 { LeafFour(value, value1, value2) }
        else                   { LeafFour(value1, value, value2) }
    }
}

/// Node
pub enum Node<V: Ord> {
    LeafTwoNode(LeafTwo<V>),
    LeafThreeNode(LeafThree<V>),
    TwoNode(Two<V>),
    ThreeNode(Three<V>),
}

impl <V: Ord> Node<V> {
    fn next_direction(&self, to_insert: &V) -> Direction {
        match self {
            &TwoNode(Two(ref value, _, _)) =>
                if to_insert < value { Left }
                else                 { Middle },
            &ThreeNode(Three(ref value1, ref value2, _, _, _)) =>
                if      to_insert < value1 { Left }
                else if to_insert > value2 { Right }
                else                       { Middle },
            _ => Leaf,
        }
    }

    fn contains_node(&self, to_check: &V) -> bool {
        match self {
            &TwoNode(Two(ref v, _, _)) |
                &LeafTwoNode(LeafTwo(ref v)) if to_check == v => true,

            &ThreeNode(Three(ref v1, ref v2, _, _, _)) |
                &LeafThreeNode(LeafThree(ref v1, ref v2)) if to_check == v1 || to_check == v2 => true,

            _ => false
        }
    }

    fn insert(self, to_insert: V) -> InsertResult<V> {
        // If value is already in this node, we're done (prevent duplicates)
        if self.contains_node(&to_insert) { return Fit(self); }

        let next_direction = self.next_direction(&to_insert);

        match self {
            // Insert if leaf TwoNode
            LeafTwoNode(LeafTwo(value)) => {
                let (smaller, larger) =
                    if value < to_insert { (value, to_insert) }
                    else                 { (to_insert, value) };
                let new_node = LeafThreeNode(LeafThree(smaller, larger));
                Fit(new_node)
            },

            // Split if leaf ThreeNode
            LeafThreeNode(leaf_three) => {
                let four_node = leaf_three.to_four(to_insert);
                Split(four_node)
            },

            // Recurse down if internal Node and handle results
            TwoNode(Two(value, box left, box middle)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node) = match next_direction {
                    Left => (left, middle),
                    Middle => (middle, left),
                    _ => fail!(""),
                };

                // Recurse, save the result of the insert
                let insert_result = next_node.insert(to_insert);

                // Handle the result of the insert
                let new_node = match insert_result {
                    Fit(returned_node) =>
                        match next_direction {
                            Left =>   Two(value, box returned_node, box other_node),
                            Middle => Two(value, box other_node, box returned_node),
                            _ => fail!(""),
                        }.to_node(),
                    Split(four_node) => four_node.to_two().to_three(value, box other_node).to_node(),
                };

                Fit(new_node)
            },

            // Recurse down if internal Node and handle results
            ThreeNode(Three(value1, value2, left, middle, right)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node1, other_node2) = match next_direction {
                    Left => (left, middle, right),
                    Middle => (middle, left, right),
                    Right => (right, left, middle),
                    _ => fail!(""),
                };

                let insert_result = next_node.insert(to_insert);

                match insert_result {
                    Fit(returned_node) => {
                        let three = match next_direction {
                            Left =>   Three(value1, value2, box returned_node, other_node1, other_node2),
                            Middle => Three(value1, value2, other_node1, box returned_node, other_node2),
                            Right =>  Three(value1, value2, other_node1, other_node2, box returned_node),
                            _ => fail!(""),
                        };
                        Fit(three.to_node())
                    },
                    Split(four_node) => {
                        let two = four_node.to_two();
                        let new_node = match next_direction {
                            Left =>   two.to_three(value1, other_node1).to_four(value2, other_node2),
                            Middle => two.to_three(value1, other_node1).to_four(value2, other_node2),
                            Right =>  two.to_three(value2, other_node2).to_four(value1, other_node1),
                            _ => fail!(""),
                        };
                        Split(new_node)
                    }
                }
            }
        }
    }
}

/// TTTree
pub struct TTTree<V: Ord> {
    pub root: Option<Node<V>>,
}

impl <V: Ord> TTTree<V> {
    pub fn new() -> TTTree<V> {
        TTTree { root: None }
    }

    pub fn insert(&mut self, value: V) -> () {
        let root: Option<Node<V>> = self.root.take();
        let new_root: Node<V> = match root {
            None => LeafTwoNode(LeafTwo(value)),
            Some(root) => {
                let result = root.insert(value);
                match result {
                    Fit(node) => node,
                    Split(four_node) => four_node.to_two().to_node(),
                }
            }
        };
        self.root = Some(new_root);
    }
}

// TODO:
// Collection trait
// convert this to Key/Value K/V
<commit_msg>Move TODO to the top<commit_after>// Many of my decisions were based off the following document
// https://web.archive.org/web/20140727185616/http://algs4.cs.princeton.edu/33balanced/

// TODO:
// Collection trait
// convert this to Key/Value K/V

use std::cmp::Ord;
use std::option::{None, Option, Some};

/// Four
enum Four<V: Ord> {
    InternalFour(V, V, V, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>, Box<Node<V>>),
    LeafFour(V, V, V),
}

impl <V: Ord> Four<V> {
    fn to_two(self) -> Two<V> {
        match self {
            LeafFour(v1, v2, v3) =>
                Two(v2,
                    box LeafTwoNode(LeafTwo(v1)),
                    box LeafTwoNode(LeafTwo(v3))),
            InternalFour(v1, v2, v3, n1, n2, n3, n4) =>
                Two(v2,
                    box TwoNode(Two(v1, n1, n2)),
                    box TwoNode(Two(v3, n3, n4))),
        }
    }
}

/// InsertResult
enum InsertResult<V: Ord> {
    Fit(Node<V>),
    Split(Four<V>),
}

/// Direction
enum Direction {
    Left,
    Middle,
    Right,
    Leaf,
}

/// Two
pub struct Two<V: Ord>(pub V, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Two<V> {
    fn to_node(self) -> Node<V> { TwoNode(self) }

    fn to_three(self, other_value: V, other_node: Box<Node<V>>) -> Three<V> {
        let Two(self_value, self_left, self_middle) = self;
        if self_value > other_value {
            Three(other_value, self_value, other_node, self_left, self_middle)
        } else {
            Three(self_value, other_value, self_left, self_middle, other_node)
        }
    }
}

/// Three
pub struct Three<V: Ord>(pub V, pub V, pub Box<Node<V>>, pub Box<Node<V>>, pub Box<Node<V>>);

impl <V: Ord> Three<V> {
    fn to_node(self) -> Node<V> { ThreeNode(self) }

    fn to_four(self, other_value: V, other_node: Box<Node<V>>) -> Four<V> {
        let Three(self_value1, self_value2, self_left, self_middle, self_right) = self;
        if other_value < self_value1 {
            InternalFour(other_value, self_value1, self_value2, other_node, self_left, self_middle, self_right)
        } else {
            InternalFour(self_value1, self_value2, other_value, self_left, self_middle, self_right, other_node)
        }
    }
}

/// LeafTwo
pub struct LeafTwo<V: Ord>(pub V);

/// LeafThree
pub struct LeafThree<V: Ord>(pub V, pub V);

impl <V: Ord> LeafThree<V> {
    fn to_four(self, value: V) -> Four<V> {
        let LeafThree(value1, value2) = self;
        if value > value2      { LeafFour(value1, value2, value) }
        else if value < value1 { LeafFour(value, value1, value2) }
        else                   { LeafFour(value1, value, value2) }
    }
}

/// Node
pub enum Node<V: Ord> {
    LeafTwoNode(LeafTwo<V>),
    LeafThreeNode(LeafThree<V>),
    TwoNode(Two<V>),
    ThreeNode(Three<V>),
}

impl <V: Ord> Node<V> {
    fn next_direction(&self, to_insert: &V) -> Direction {
        match self {
            &TwoNode(Two(ref value, _, _)) =>
                if to_insert < value { Left }
                else                 { Middle },
            &ThreeNode(Three(ref value1, ref value2, _, _, _)) =>
                if      to_insert < value1 { Left }
                else if to_insert > value2 { Right }
                else                       { Middle },
            _ => Leaf,
        }
    }

    fn contains_node(&self, to_check: &V) -> bool {
        match self {
            &TwoNode(Two(ref v, _, _)) |
                &LeafTwoNode(LeafTwo(ref v)) if to_check == v => true,

            &ThreeNode(Three(ref v1, ref v2, _, _, _)) |
                &LeafThreeNode(LeafThree(ref v1, ref v2)) if to_check == v1 || to_check == v2 => true,

            _ => false
        }
    }

    fn insert(self, to_insert: V) -> InsertResult<V> {
        // If value is already in this node, we're done (prevent duplicates)
        if self.contains_node(&to_insert) { return Fit(self); }

        let next_direction = self.next_direction(&to_insert);

        match self {
            // Insert if leaf TwoNode
            LeafTwoNode(LeafTwo(value)) => {
                let (smaller, larger) =
                    if value < to_insert { (value, to_insert) }
                    else                 { (to_insert, value) };
                let new_node = LeafThreeNode(LeafThree(smaller, larger));
                Fit(new_node)
            },

            // Split if leaf ThreeNode
            LeafThreeNode(leaf_three) => {
                let four_node = leaf_three.to_four(to_insert);
                Split(four_node)
            },

            // Recurse down if internal Node and handle results
            TwoNode(Two(value, box left, box middle)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node) = match next_direction {
                    Left => (left, middle),
                    Middle => (middle, left),
                    _ => fail!(""),
                };

                // Recurse, save the result of the insert
                let insert_result = next_node.insert(to_insert);

                // Handle the result of the insert
                let new_node = match insert_result {
                    Fit(returned_node) =>
                        match next_direction {
                            Left =>   Two(value, box returned_node, box other_node),
                            Middle => Two(value, box other_node, box returned_node),
                            _ => fail!(""),
                        }.to_node(),
                    Split(four_node) => four_node.to_two().to_three(value, box other_node).to_node(),
                };

                Fit(new_node)
            },

            // Recurse down if internal Node and handle results
            ThreeNode(Three(value1, value2, left, middle, right)) => {

                // Determine which node we'll recurse next
                let (next_node, other_node1, other_node2) = match next_direction {
                    Left => (left, middle, right),
                    Middle => (middle, left, right),
                    Right => (right, left, middle),
                    _ => fail!(""),
                };

                let insert_result = next_node.insert(to_insert);

                match insert_result {
                    Fit(returned_node) => {
                        let three = match next_direction {
                            Left =>   Three(value1, value2, box returned_node, other_node1, other_node2),
                            Middle => Three(value1, value2, other_node1, box returned_node, other_node2),
                            Right =>  Three(value1, value2, other_node1, other_node2, box returned_node),
                            _ => fail!(""),
                        };
                        Fit(three.to_node())
                    },
                    Split(four_node) => {
                        let two = four_node.to_two();
                        let new_node = match next_direction {
                            Left =>   two.to_three(value1, other_node1).to_four(value2, other_node2),
                            Middle => two.to_three(value1, other_node1).to_four(value2, other_node2),
                            Right =>  two.to_three(value2, other_node2).to_four(value1, other_node1),
                            _ => fail!(""),
                        };
                        Split(new_node)
                    }
                }
            }
        }
    }
}

/// TTTree
pub struct TTTree<V: Ord> {
    pub root: Option<Node<V>>,
}

impl <V: Ord> TTTree<V> {
    pub fn new() -> TTTree<V> {
        TTTree { root: None }
    }

    pub fn insert(&mut self, value: V) -> () {
        let root: Option<Node<V>> = self.root.take();
        let new_root: Node<V> = match root {
            None => LeafTwoNode(LeafTwo(value)),
            Some(root) => {
                let result = root.insert(value);
                match result {
                    Fit(node) => node,
                    Split(four_node) => four_node.to_two().to_node(),
                }
            }
        };
        self.root = Some(new_root);
    }
}
<|endoftext|>