<commit_before>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

extern crate ansi_term;
extern crate atty;
#[macro_use]
extern crate clap;
extern crate ignore;
#[macro_use]
extern crate lazy_static;
#[cfg(all(unix, not(target_os = "redox")))]
extern crate libc;
extern crate num_cpus;
extern crate regex;
extern crate regex_syntax;

pub mod fshelper;
pub mod lscolors;
mod app;
mod exec;
mod internal;
mod output;
mod walk;

use std::env;
use std::error::Error;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time;

use atty::Stream;
use regex::{RegexBuilder, RegexSetBuilder};

use exec::CommandTemplate;
use internal::{error, pattern_has_uppercase_char, transform_args_with_exec, FdOptions, FileTypes};
use lscolors::LsColors;

fn main() {
    let checked_args = transform_args_with_exec(env::args_os());
    let matches = app::build_app().get_matches_from(checked_args);

    // Get the search pattern
    let pattern = matches.value_of("pattern").unwrap_or("");

    // Get the current working directory
    let current_dir = Path::new(".");
    if !fshelper::is_dir(current_dir) {
        error("Error: could not get current directory.");
    }

    //Get one or more root directories to search.
    let mut dir_vec: Vec<_> = match matches.values_of("path") {
        Some(paths) => paths
            .map(|path| {
                let path_buffer = PathBuf::from(path);
                if !fshelper::is_dir(&path_buffer) {
                    error(&format!(
                        "Error: '{}' is not a directory.",
                        path_buffer.to_string_lossy()
                    ));
                }
                path_buffer
            })
            .collect::<Vec<_>>(),
        None => vec![current_dir.to_path_buf()],
    };

    if matches.is_present("absolute-path") {
        dir_vec = dir_vec
            .iter()
            .map(|path_buffer| fshelper::absolute_path(path_buffer).unwrap())
            .collect();
    }

    // Treat pattern as literal string if '--fixed-strings' is used
    let pattern_regex = if matches.is_present("fixed-strings") {
        regex::escape(pattern)
    } else {
        String::from(pattern)
    };

    // The search will be case-sensitive if the command line flag is set or
    // if the pattern has an uppercase character (smart case).
    let case_sensitive = !matches.is_present("ignore-case")
        && (matches.is_present("case-sensitive") || pattern_has_uppercase_char(&pattern_regex));

    let colored_output = match matches.value_of("color") {
        Some("always") => true,
        Some("never") => false,
        _ => atty::is(Stream::Stdout),
    };

    #[cfg(windows)]
    let colored_output = colored_output && ansi_term::enable_ansi_support().is_ok();

    let ls_colors = if colored_output {
        Some(
            env::var("LS_COLORS")
                .ok()
                .map(|val| LsColors::from_string(&val))
                .unwrap_or_default(),
        )
    } else {
        None
    };

    let command = matches.values_of("exec").map(CommandTemplate::new);

    let config = FdOptions {
        case_sensitive,
        search_full_path: matches.is_present("full-path"),
        ignore_hidden: !(matches.is_present("hidden")
            || matches.occurrences_of("rg-alias-hidden-ignore") >= 2),
        read_fdignore: !(matches.is_present("no-ignore")
            || matches.is_present("rg-alias-hidden-ignore")),
        read_vcsignore: !(matches.is_present("no-ignore")
            || matches.is_present("rg-alias-hidden-ignore")
            || matches.is_present("no-ignore-vcs")),
        follow_links: matches.is_present("follow"),
        null_separator: matches.is_present("null_separator"),
        max_depth: matches
            .value_of("depth")
            .and_then(|n| usize::from_str_radix(n, 10).ok()),
        threads: std::cmp::max(
            matches
                .value_of("threads")
                .and_then(|n| usize::from_str_radix(n, 10).ok())
                .unwrap_or_else(num_cpus::get),
            1,
        ),
        max_buffer_time: matches
            .value_of("max-buffer-time")
            .and_then(|n| u64::from_str_radix(n, 10).ok())
            .map(time::Duration::from_millis),
        ls_colors,
        file_types: matches.values_of("file-type").map(|values| {
            let mut file_types = FileTypes::default();
            for value in values {
                match value {
                    "f" | "file" => file_types.files = true,
                    "d" | "directory" => file_types.directories = true,
                    "l" | "symlink" => file_types.symlinks = true,
                    _ => unreachable!(),
                }
            }
            file_types
        }),
        extensions: matches.values_of("extension").map(|exts| {
            let patterns = exts.map(|e| e.trim_left_matches('.'))
                .map(|e| format!(r".\.{}$", regex::escape(e)));
            match RegexSetBuilder::new(patterns)
                .case_insensitive(true)
                .build()
            {
                Ok(re) => re,
                Err(err) => error(err.description()),
            }
        }),
        command,
        exclude_patterns: matches
            .values_of("exclude")
            .map(|v| v.map(|p| String::from("!") + p).collect())
            .unwrap_or_else(|| vec![]),
    };

    match RegexBuilder::new(&pattern_regex)
        .case_insensitive(!config.case_sensitive)
        .dot_matches_new_line(true)
        .build()
    {
        Ok(re) => walk::scan(&dir_vec, Arc::new(re), Arc::new(config)),
        Err(err) => error(
            format!(
                "{}\nHint: You can use the '--fixed-strings' option to search for a \
                 literal string instead of a regular expression",
                err.description()
            ).as_str(),
        ),
    }
}
<commit_msg>Formatting change<commit_after>// Copyright (c) 2017 fd developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>
// or the MIT license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

extern crate ansi_term;
extern crate atty;
#[macro_use]
extern crate clap;
extern crate ignore;
#[macro_use]
extern crate lazy_static;
#[cfg(all(unix, not(target_os = "redox")))]
extern crate libc;
extern crate num_cpus;
extern crate regex;
extern crate regex_syntax;

pub mod fshelper;
pub mod lscolors;
mod app;
mod exec;
mod internal;
mod output;
mod walk;

use std::env;
use std::error::Error;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::time;

use atty::Stream;
use regex::{RegexBuilder, RegexSetBuilder};

use exec::CommandTemplate;
use internal::{error, pattern_has_uppercase_char, transform_args_with_exec, FdOptions, FileTypes};
use lscolors::LsColors;

fn main() {
    let checked_args = transform_args_with_exec(env::args_os());
    let matches = app::build_app().get_matches_from(checked_args);

    // Get the search pattern
    let pattern = matches.value_of("pattern").unwrap_or("");

    // Get the current working directory
    let current_dir = Path::new(".");
    if !fshelper::is_dir(current_dir) {
        error("Error: could not get current directory.");
    }

    // Get one or more root directories to search.
    let mut dir_vec: Vec<_> = match matches.values_of("path") {
        Some(paths) => paths
            .map(|path| {
                let path_buffer = PathBuf::from(path);
                if !fshelper::is_dir(&path_buffer) {
                    error(&format!(
                        "Error: '{}' is not a directory.",
                        path_buffer.to_string_lossy()
                    ));
                }
                path_buffer
            })
            .collect::<Vec<_>>(),
        None => vec![current_dir.to_path_buf()],
    };

    if matches.is_present("absolute-path") {
        dir_vec = dir_vec
            .iter()
            .map(|path_buffer| fshelper::absolute_path(path_buffer).unwrap())
            .collect();
    }

    // Treat pattern as literal string if '--fixed-strings' is used
    let pattern_regex = if matches.is_present("fixed-strings") {
        regex::escape(pattern)
    } else {
        String::from(pattern)
    };

    // The search will be case-sensitive if the command line flag is set or
    // if the pattern has an uppercase character (smart case).
    let case_sensitive = !matches.is_present("ignore-case")
        && (matches.is_present("case-sensitive") || pattern_has_uppercase_char(&pattern_regex));

    let colored_output = match matches.value_of("color") {
        Some("always") => true,
        Some("never") => false,
        _ => atty::is(Stream::Stdout),
    };

    #[cfg(windows)]
    let colored_output = colored_output && ansi_term::enable_ansi_support().is_ok();

    let ls_colors = if colored_output {
        Some(
            env::var("LS_COLORS")
                .ok()
                .map(|val| LsColors::from_string(&val))
                .unwrap_or_default(),
        )
    } else {
        None
    };

    let command = matches.values_of("exec").map(CommandTemplate::new);

    let config = FdOptions {
        case_sensitive,
        search_full_path: matches.is_present("full-path"),
        ignore_hidden: !(matches.is_present("hidden")
            || matches.occurrences_of("rg-alias-hidden-ignore") >= 2),
        read_fdignore: !(matches.is_present("no-ignore")
            || matches.is_present("rg-alias-hidden-ignore")),
        read_vcsignore: !(matches.is_present("no-ignore")
            || matches.is_present("rg-alias-hidden-ignore")
            || matches.is_present("no-ignore-vcs")),
        follow_links: matches.is_present("follow"),
        null_separator: matches.is_present("null_separator"),
        max_depth: matches
            .value_of("depth")
            .and_then(|n| usize::from_str_radix(n, 10).ok()),
        threads: std::cmp::max(
            matches
                .value_of("threads")
                .and_then(|n| usize::from_str_radix(n, 10).ok())
                .unwrap_or_else(num_cpus::get),
            1,
        ),
        max_buffer_time: matches
            .value_of("max-buffer-time")
            .and_then(|n| u64::from_str_radix(n, 10).ok())
            .map(time::Duration::from_millis),
        ls_colors,
        file_types: matches.values_of("file-type").map(|values| {
            let mut file_types = FileTypes::default();
            for value in values {
                match value {
                    "f" | "file" => file_types.files = true,
                    "d" | "directory" => file_types.directories = true,
                    "l" | "symlink" => file_types.symlinks = true,
                    _ => unreachable!(),
                }
            }
            file_types
        }),
        extensions: matches.values_of("extension").map(|exts| {
            let patterns = exts.map(|e| e.trim_left_matches('.'))
                .map(|e| format!(r".\.{}$", regex::escape(e)));
            match RegexSetBuilder::new(patterns)
                .case_insensitive(true)
                .build()
            {
                Ok(re) => re,
                Err(err) => error(err.description()),
            }
        }),
        command,
        exclude_patterns: matches
            .values_of("exclude")
            .map(|v| v.map(|p| String::from("!") + p).collect())
            .unwrap_or_else(|| vec![]),
    };

    match RegexBuilder::new(&pattern_regex)
        .case_insensitive(!config.case_sensitive)
        .dot_matches_new_line(true)
        .build()
    {
        Ok(re) => walk::scan(&dir_vec, Arc::new(re), Arc::new(config)),
        Err(err) => error(
            format!(
                "{}\nHint: You can use the '--fixed-strings' option to search for a \
                 literal string instead of a regular expression",
                err.description()
            ).as_str(),
        ),
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![allow(unknown_lints)]
// #![allow(unused_features)]
// #![feature(test)]
#[macro_use] extern crate clap;
extern crate cgmath;
// use cgmath::prelude::*;

extern crate gl;

extern crate glutin;

extern crate gltf;
extern crate gltf_importer;
extern crate gltf_utils;

extern crate image;
extern crate num_traits;

#[macro_use]
extern crate bitflags;

use clap::{Arg, App, AppSettings};

#[macro_use]extern crate log;
extern crate simplelog;
use simplelog::{TermLogger, LevelFilter, Config as LogConfig};

mod utils;
mod viewer;
use viewer::{GltfViewer};

mod shader;
mod controls;
mod framebuffer;
mod macros;
// TODO!: adapt Source...
// mod http_source;
// use http_source::HttpSource;
mod render;

pub fn main() {
    let args = App::new("gltf-viewer")
        .version(format!("{} ({})", crate_version!(), option_env!("VERSION").unwrap_or("")).as_str())
        .setting(AppSettings::UnifiedHelpMessage)
        .setting(AppSettings::DeriveDisplayOrder)
        .arg(Arg::with_name("FILE") // TODO!: re-add URL when fixed...
            .required(true)
            .takes_value(true)
            .help("glTF file name"))
        .arg(Arg::with_name("screenshot")
            .long("screenshot")
            .short("s")
            .value_name("FILE")
            .help("Create screenshot (PNG)"))
        .arg(Arg::with_name("verbose")
            .long("verbose")
            .short("v")
            .multiple(true)
            .help("Enable verbose logging (log level INFO). Can be repeated multiple times to increase log level to DEBUG/TRACE)"))
        .arg(Arg::with_name("WIDTH")
            .long("width")
            .short("w")
            .default_value("800")
            .help("Width in pixels")
            .validator(|value| value.parse::<u32>().map(|_| ()).map_err(|err| err.to_string())))
        .arg(Arg::with_name("HEIGHT")
            .long("height")
            .short("h")
            .default_value("600")
            .help("Height in pixels")
            .validator(|value| value.parse::<u32>().map(|_| ()).map_err(|err| err.to_string())))
        .arg(Arg::with_name("COUNT")
            .long("count")
            .short("c")
            .default_value("1")
            .help("Saves N screenshots of size WxH, rotating evenly spaced around the object")
            .validator(|value| value.parse::<u32>().map(|_| ()).map_err(|err| err.to_string())))
        .arg(Arg::with_name("headless")
            .long("headless")
            .help("Use real headless rendering for screenshots (Default is a hidden window) [EXPERIMENTAL]"))
        .get_matches();
    let source = args.value_of("FILE").unwrap();
    let width: u32 = args.value_of("WIDTH").unwrap().parse().unwrap();
    let height: u32 = args.value_of("HEIGHT").unwrap().parse().unwrap();
    let count: u32 = args.value_of("COUNT").unwrap().parse().unwrap();

    let log_level = match args.occurrences_of("verbose") {
        0 => LevelFilter::Warn,
        1 => LevelFilter::Info,
        2 => LevelFilter::Debug,
        _ => LevelFilter::Trace
    };

    let _ = TermLogger::init(log_level, LogConfig { time: None, target: None, ..LogConfig::default() });

    let mut viewer = GltfViewer::new(source, width, height,
        args.is_present("headless"),
        !args.is_present("screenshot"));

    if args.is_present("screenshot") {
        let filename = args.value_of("screenshot").unwrap();

        if !filename.to_lowercase().ends_with(".png") {
            warn!("filename should end with .png");
        }
        if count > 1 {
            viewer.multiscreenshot(filename, width, height, count)
        } else {
            viewer.screenshot(filename, width, height)
        }
        return;
    }

    viewer.start_render_loop();
}

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

    #[test]
    fn print_struct_sizes() {
        // run with `cargo test -- --nocapture`
        println!("Sizes in bytes:");
        println!("Scene:     {:>3}", std::mem::size_of::<render::Scene>());
        println!("Node:      {:>3}", std::mem::size_of::<render::Node>());
        println!("Mesh:      {:>3}", std::mem::size_of::<render::Mesh>());
        println!("Primitive: {:>3}", std::mem::size_of::<render::Primitive>());
        println!("Vertex:    {:>3}", std::mem::size_of::<render::Vertex>());
        println!();
        println!("Option<String>: {:>3}", std::mem::size_of::<Option<String>>());
        println!("String:         {:>3}", std::mem::size_of::<String>());
        println!("Vec<f32>:       {:>3}", std::mem::size_of::<Vec<f32>>());
        println!("Vec<Node>:      {:>3}", std::mem::size_of::<Vec<render::Node>>());
    }

//     extern crate test;
//     use self::test::Bencher;
//     #[bench]
//     fn bench_frame_timer(b: &mut Bencher) {
//         let mut timer = FrameTimer::new("Foobar", 60);
//         b.iter(|| {
//             for _ in 0..60 {
//                 timer.start();
//                 timer.end();
//             }
//         })
//     }
}
<commit_msg>improve version string<commit_after>#![allow(dead_code)]
#![allow(unknown_lints)]
// #![allow(unused_features)]
// #![feature(test)]
#[macro_use] extern crate clap;
extern crate cgmath;
// use cgmath::prelude::*;

extern crate gl;

extern crate glutin;

extern crate gltf;
extern crate gltf_importer;
extern crate gltf_utils;

extern crate image;
extern crate num_traits;

#[macro_use]
extern crate bitflags;

use clap::{Arg, App, AppSettings};

#[macro_use]extern crate log;
extern crate simplelog;
use simplelog::{TermLogger, LevelFilter, Config as LogConfig};

mod utils;
mod viewer;
use viewer::{GltfViewer};

mod shader;
mod controls;
mod framebuffer;
mod macros;
// TODO!: adapt Source...
// mod http_source;
// use http_source::HttpSource;
mod render;

pub fn main() {
    let args = App::new("gltf-viewer")
        .version(option_env!("VERSION").unwrap_or(crate_version!()))
        .setting(AppSettings::UnifiedHelpMessage)
        .setting(AppSettings::DeriveDisplayOrder)
        .arg(Arg::with_name("FILE") // TODO!: re-add URL when fixed...
            .required(true)
            .takes_value(true)
            .help("glTF file name"))
        .arg(Arg::with_name("screenshot")
            .long("screenshot")
            .short("s")
            .value_name("FILE")
            .help("Create screenshot (PNG)"))
        .arg(Arg::with_name("verbose")
            .long("verbose")
            .short("v")
            .multiple(true)
            .help("Enable verbose logging (log level INFO). Can be repeated multiple times to increase log level to DEBUG/TRACE)"))
        .arg(Arg::with_name("WIDTH")
            .long("width")
            .short("w")
            .default_value("800")
            .help("Width in pixels")
            .validator(|value| value.parse::<u32>().map(|_| ()).map_err(|err| err.to_string())))
        .arg(Arg::with_name("HEIGHT")
            .long("height")
            .short("h")
            .default_value("600")
            .help("Height in pixels")
            .validator(|value| value.parse::<u32>().map(|_| ()).map_err(|err| err.to_string())))
        .arg(Arg::with_name("COUNT")
            .long("count")
            .short("c")
            .default_value("1")
            .help("Saves N screenshots of size WxH, rotating evenly spaced around the object")
            .validator(|value| value.parse::<u32>().map(|_| ()).map_err(|err| err.to_string())))
        .arg(Arg::with_name("headless")
            .long("headless")
            .help("Use real headless rendering for screenshots (Default is a hidden window) [EXPERIMENTAL]"))
        .get_matches();
    let source = args.value_of("FILE").unwrap();
    let width: u32 = args.value_of("WIDTH").unwrap().parse().unwrap();
    let height: u32 = args.value_of("HEIGHT").unwrap().parse().unwrap();
    let count: u32 = args.value_of("COUNT").unwrap().parse().unwrap();

    let log_level = match args.occurrences_of("verbose") {
        0 => LevelFilter::Warn,
        1 => LevelFilter::Info,
        2 => LevelFilter::Debug,
        _ => LevelFilter::Trace
    };

    let _ = TermLogger::init(log_level, LogConfig { time: None, target: None, ..LogConfig::default() });

    let mut viewer = GltfViewer::new(source, width, height,
        args.is_present("headless"),
        !args.is_present("screenshot"));

    if args.is_present("screenshot") {
        let filename = args.value_of("screenshot").unwrap();

        if !filename.to_lowercase().ends_with(".png") {
            warn!("filename should end with .png");
        }
        if count > 1 {
            viewer.multiscreenshot(filename, width, height, count)
        } else {
            viewer.screenshot(filename, width, height)
        }
        return;
    }

    viewer.start_render_loop();
}

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

    #[test]
    fn print_struct_sizes() {
        // run with `cargo test -- --nocapture`
        println!("Sizes in bytes:");
        println!("Scene:     {:>3}", std::mem::size_of::<render::Scene>());
        println!("Node:      {:>3}", std::mem::size_of::<render::Node>());
        println!("Mesh:      {:>3}", std::mem::size_of::<render::Mesh>());
        println!("Primitive: {:>3}", std::mem::size_of::<render::Primitive>());
        println!("Vertex:    {:>3}", std::mem::size_of::<render::Vertex>());
        println!();
        println!("Option<String>: {:>3}", std::mem::size_of::<Option<String>>());
        println!("String:         {:>3}", std::mem::size_of::<String>());
        println!("Vec<f32>:       {:>3}", std::mem::size_of::<Vec<f32>>());
        println!("Vec<Node>:      {:>3}", std::mem::size_of::<Vec<render::Node>>());
    }

//     extern crate test;
//     use self::test::Bencher;
//     #[bench]
//     fn bench_frame_timer(b: &mut Bencher) {
//         let mut timer = FrameTimer::new("Foobar", 60);
//         b.iter(|| {
//             for _ in 0..60 {
//                 timer.start();
//                 timer.end();
//             }
//         })
//     }
}
<|endoftext|>


<commit_before>
use vertex::{Vertex, VertexProxy};
use edge::{Edge, EdgeProxy};
use graph::TraversableToVertex;
// define a traversal as a series of stages

struct VertexVisit {
    vertex: VertexProxy
}

struct EdgeVisit {
    edge: EdgeProxy
}

enum TraversalStage {

}

pub enum GraphElement {
    Vertex(VertexProxy),
    Edge(EdgeProxy)
}

// used to track a single graph traversal
// will be used in conjunction with a GraphQuery

pub struct Path {
    path: Vec<GraphElement>
}

impl Path {
    fn new(vertex: VertexProxy) -> Path {
		Path{path:vec![GraphElement::Vertex(vertex)]}
    }
	fn new_empty() -> Path {
		Path{path:vec![]}
	}

}

impl Clone for Path {
	fn clone(&self) -> Path {
		Path::new_empty()
	}

	fn clone_from(&mut self, source: &Self ) {

	}
}

pub struct GraphQuery {
	// many paths
    pub paths: Vec<Path>
}

impl GraphQuery {
    pub fn new(vertices: Vec<VertexProxy>) -> GraphQuery {
        // create a new path for each proxy, add the proxy
        let mut paths = Vec::new();
        for p in vertices {
			let mut path = Path::new(p);
            paths.push(path)
        }
        GraphQuery{paths:paths}
    }

    pub fn empty() -> GraphQuery {
        // return an empty graph query
        GraphQuery{paths:Vec::new()}
    }

	pub fn get_paths(&self) -> &Vec<Path> {
		&self.paths
	}

	/*
	generic mapper for our queries
	future this may use worker threads to perform
	traversals
	 */
    fn full_map<F: Fn(&Path) -> Vec<Path>>(&self, closure: F) -> GraphQuery  {
        let mut result = GraphQuery::empty(); // result
		for x in self.paths.iter() {
			let mut tmp = closure(x);
			result.paths.append(&mut tmp)
		}
		result
    }

	/*
	accepts a proxy and a closure, per
	takes the last element
	 */
	fn map<F: Fn(&GraphElement) -> Vec<GraphElement>>(&self, closure: F)
		-> GraphQuery {
		GraphQuery::empty()
	}

	/*

	 */
    pub fn outV(&self) -> GraphQuery {
		let f = |path: &Path| {
			println!("applying outV");
			let mut result : Vec<Path> = Vec::new();
			//take the final element in the path
			let element = path.path.last().unwrap();

			match element {
				&GraphElement::Vertex(ref v) => {
					println!("matched vertex");
					let mut tmp = v.outV();
					for vertex in tmp {
						println!("adding path based on vertex match");
						let new_path = path.clone();
						result.push(new_path);
					}
				},
				&GraphElement::Edge(ref e) => {

				}
			}
			// apply outV

			result
		};
		self.full_map(f)
    }

//	pub fn inV(&self) -> GraphQuery {
//		let g = GraphQuery::empty();
//		let f = |element: &GraphElement| {
//			element.inV()
//		};
//		self.map(f)
//	}
}

<commit_msg>getting new map ready<commit_after>
use vertex::{Vertex, VertexProxy};
use edge::{Edge, EdgeProxy};
use graph::TraversableToVertex;
// define a traversal as a series of stages

struct VertexVisit {
    vertex: VertexProxy
}

struct EdgeVisit {
    edge: EdgeProxy
}

enum TraversalStage {

}

pub enum GraphElement {
    Vertex(VertexProxy),
    Edge(EdgeProxy)
}

// used to track a single graph traversal
// will be used in conjunction with a GraphQuery

pub struct Path {
    path: Vec<GraphElement>
}

impl Path {
    fn new(vertex: VertexProxy) -> Path {
		Path{path:vec![GraphElement::Vertex(vertex)]}
    }
	fn new_empty() -> Path {
		Path{path:vec![]}
	}

}

impl Clone for Path {
	fn clone(&self) -> Path {
		Path::new_empty()
	}

	fn clone_from(&mut self, source: &Self ) {

	}
}

pub struct GraphQuery {
	// many paths
    pub paths: Vec<Path>
}

impl GraphQuery {
    pub fn new(vertices: Vec<VertexProxy>) -> GraphQuery {
        // create a new path for each proxy, add the proxy
        let mut paths = Vec::new();
        for p in vertices {
			let mut path = Path::new(p);
            paths.push(path)
        }
        GraphQuery{paths:paths}
    }

    pub fn empty() -> GraphQuery {
        // return an empty graph query
        GraphQuery{paths:Vec::new()}
    }

	pub fn get_paths(&self) -> &Vec<Path> {
		&self.paths
	}

	/*
	generic mapper for our queries
	future this may use worker threads to perform
	traversals
	 */
    fn full_map<F: Fn(&Path) -> Vec<Path>>(&self, closure: F) -> GraphQuery  {
        let mut result = GraphQuery::empty(); // result
		for x in self.paths.iter() {
			let mut tmp = closure(x);
			result.paths.append(&mut tmp)
		}
		result
    }

	/*
	accepts a proxy and a closure, per
	takes the last element
	 */
	fn map<F: Fn(&GraphElement) -> Vec<GraphElement>>(&self, closure: F)
		-> GraphQuery {
		let mut result = GraphQuery::empty();
		for x in self.paths.iter() {
			// apply the closure to the last element in each map
			// if nothing is returned, we should not use the path anymore
		}

		result

	}

	/*

	 */
    pub fn outV(&self) -> GraphQuery {
		let f = |path: &Path| {
			println!("applying outV");
			let mut result : Vec<Path> = Vec::new();
			//take the final element in the path
			let element = path.path.last().unwrap();

			match element {
				&GraphElement::Vertex(ref v) => {
					println!("matched vertex");
					let mut tmp = v.outV();
					for vertex in tmp {
						println!("adding path based on vertex match");
						let new_path = path.clone();
						result.push(new_path);
					}
				},
				&GraphElement::Edge(ref e) => {

				}
			}
			// apply outV

			result
		};
		self.full_map(f)
    }

//	pub fn inV(&self) -> GraphQuery {
//		let g = GraphQuery::empty();
//		let f = |element: &GraphElement| {
//			element.inV()
//		};
//		self.map(f)
//	}
}

<|endoftext|>


<commit_before>/*!

A texture is an image available for drawing.

To create a texture, you must first create a struct that implements one of `Texture1dData`,
 `Texture2dData` or `Texture3dData`. Then call the appropriate `new` function of the type of
 texture that you desire.

The most common types of textures are `CompressedTexture2d` and `Texture2d` (the two dimensions
being the width and height), it is what you will use most of the time.

*/

use {gl, framebuffer};

#[cfg(feature = "image")]
use image;

use buffer::{mod, Buffer};
use uniforms::{UniformValue, IntoUniformValue, Sampler};
use {Surface, GlObject, ToGlEnum};

use self::tex_impl::TextureImplementation;

pub use self::format::{ClientFormat, TextureFormat};
pub use self::format::{UncompressedFloatFormat, UncompressedIntFormat, UncompressedUintFormat};
pub use self::format::{CompressedFormat, DepthFormat, DepthStencilFormat, StencilFormat};
pub use self::pixel::PixelValue;

mod format;
mod pixel;
mod tex_impl;

include!(concat!(env!("OUT_DIR"), "/textures.rs"));

/// Trait that describes a texture.
pub trait Texture {
    /// Returns the width in pixels of the texture.
    fn get_width(&self) -> u32;

    /// Returns the height in pixels of the texture, or `None` for one dimension textures.
    fn get_height(&self) -> Option<u32>;

    /// Returns the depth in pixels of the texture, or `None` for one or two dimension textures.
    fn get_depth(&self) -> Option<u32>;

    /// Returns the number of textures in the array, or `None` for non-arrays.
    fn get_array_size(&self) -> Option<u32>;
}

/// Trait that describes data for a one-dimensional texture.
#[experimental = "Will be rewritten to use an associated type"]
pub trait Texture1dData<T> {
    /// Returns the format of the pixels.
    fn get_format(Option<Self>) -> ClientFormat;

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<T>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<T>) -> Self;
}

impl<P: PixelValue> Texture1dData<P> for Vec<P> {
    fn get_format(_: Option<Vec<P>>) -> ClientFormat {
        PixelValue::get_format(None::<P>)
    }

    fn into_vec(self) -> Vec<P> {
        self
    }

    fn from_vec(data: Vec<P>) -> Vec<P> {
        data
    }
}

impl<'a, P: PixelValue + Clone> Texture1dData<P> for &'a [P] {
    fn get_format(_: Option<&'a [P]>) -> ClientFormat {
        PixelValue::get_format(None::<P>)
    }

    fn into_vec(self) -> Vec<P> {
        self.to_vec()
    }

    fn from_vec(_: Vec<P>) -> &'a [P] {
        panic!()        // TODO: what to do here?
    }
}

/// Trait that describes data for a two-dimensional texture.
#[experimental = "Will be rewritten to use an associated type"]
pub trait Texture2dData<P> {
    /// Returns the format of the pixels.
    fn get_format(Option<Self>) -> ClientFormat;

    /// Returns the dimensions of the texture.
    fn get_dimensions(&self) -> (u32, u32);

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<P>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<P>, width: u32) -> Self;
}

impl<P: PixelValue + Clone> Texture2dData<P> for Vec<Vec<P>> {      // TODO: remove Clone
    fn get_format(_: Option<Vec<Vec<P>>>) -> ClientFormat {
        PixelValue::get_format(None::<P>)
    }

    fn get_dimensions(&self) -> (u32, u32) {
        (self.iter().next().map(|e| e.len()).unwrap_or(0) as u32, self.len() as u32)
    }

    fn into_vec(self) -> Vec<P> {
        self.into_iter().flat_map(|e| e.into_iter()).collect()
    }

    fn from_vec(data: Vec<P>, width: u32) -> Vec<Vec<P>> {
        data.as_slice().chunks(width as uint).map(|e| e.to_vec()).collect()
    }
}

#[cfg(feature = "image")]
impl<T, P> Texture2dData<T> for image::ImageBuffer<Vec<T>, T, P> where T: image::Primitive + Send,
    P: PixelValue + image::Pixel<T> + Clone + Copy
{
    fn get_format(_: Option<image::ImageBuffer<Vec<T>, T, P>>) -> ClientFormat {
        PixelValue::get_format(None::<P>)
    }

    fn get_dimensions(&self) -> (u32, u32) {
        use image::GenericImage;
        self.dimensions()
    }

    fn into_vec(self) -> Vec<T> {
        use image::GenericImage;
        let (width, _) = self.dimensions();

        let raw_data = self.into_vec();

        // the image library gives use rows from bottom to top, so we need to flip them
        raw_data
            .as_slice()
            .chunks(width as uint * image::Pixel::channel_count(None::<&P>) as uint)
            .rev()
            .flat_map(|row| row.iter())
            .map(|p| p.clone())
            .collect()
    }

    fn from_vec(data: Vec<T>, width: u32) -> image::ImageBuffer<Vec<T>, T, P> {
        let pixels_size = image::Pixel::channel_count(None::<&P>);
        let height = data.len() as u32 / (width * pixels_size as u32);

        // opengl gives use rows from bottom to top, so we need to flip them
        let data = data
            .as_slice()
            .chunks(width as uint * image::Pixel::channel_count(None::<&P>) as uint)
            .rev()
            .flat_map(|row| row.iter())
            .map(|p| p.clone())
            .collect();

        image::ImageBuffer::from_raw(width, height, data).unwrap()
    }
}

#[cfg(feature = "image")]
impl Texture2dData<u8> for image::DynamicImage {
    fn get_format(_: Option<image::DynamicImage>) -> ClientFormat {
        ClientFormat::U8U8U8U8
    }

    fn get_dimensions(&self) -> (u32, u32) {
        use image::GenericImage;
        self.dimensions()
    }

    fn into_vec(self) -> Vec<u8> {
        Texture2dData::into_vec(self.to_rgba())
    }

    fn from_vec(data: Vec<u8>, width: u32) -> image::DynamicImage {
        image::DynamicImage::ImageRgba8(Texture2dData::from_vec(data, width))
    }
}

/// Trait that describes data for a three-dimensional texture.
#[experimental = "Will be rewritten to use an associated type"]
pub trait Texture3dData<P> {
    /// Returns the format of the pixels.
    fn get_format(Option<Self>) -> ClientFormat;

    /// Returns the dimensions of the texture.
    fn get_dimensions(&self) -> (u32, u32, u32);

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<P>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<P>, width: u32, height: u32) -> Self;
}

impl<P: PixelValue> Texture3dData<P> for Vec<Vec<Vec<P>>> {
    fn get_format(_: Option<Vec<Vec<Vec<P>>>>) -> ClientFormat {
        PixelValue::get_format(None::<P>)
    }

    fn get_dimensions(&self) -> (u32, u32, u32) {
        (self.iter().next().and_then(|e| e.iter().next()).map(|e| e.len()).unwrap_or(0) as u32,
            self.iter().next().map(|e| e.len()).unwrap_or(0) as u32, self.len() as u32)
    }

    fn into_vec(self) -> Vec<P> {
        self.into_iter().flat_map(|e| e.into_iter()).flat_map(|e| e.into_iter()).collect()
    }

    fn from_vec(data: Vec<P>, width: u32, height: u32) -> Vec<Vec<Vec<P>>> {
        unimplemented!()        // TODO:
    }
}

/// Buffer that stores the content of a texture.
///
/// The generic type represents the type of pixels that the buffer contains.
///
/// **Note**: pixel buffers are unusable for the moment (they are not yet implemented).
pub struct PixelBuffer<T> {
    buffer: Buffer,
}

impl<T> PixelBuffer<T> where T: PixelValue {
    /// Builds a new buffer with an uninitialized content.
    pub fn new_empty(display: &super::Display, capacity: uint) -> PixelBuffer<T> {
        PixelBuffer {
            buffer: Buffer::new_empty::<buffer::PixelUnpackBuffer>(display, 1, capacity,
                                                                   gl::DYNAMIC_READ),
        }
    }

    /// Turns a `PixelBuffer<T>` into a `PixelBuffer<U>` without any check.
    pub unsafe fn transmute<U>(self) -> PixelBuffer<U> where U: PixelValue {
        PixelBuffer { buffer: self.buffer }
    }
}

/// Struct that allows you to draw on a texture.
///
/// To obtain such an object, call `texture.as_surface()`.
pub struct TextureSurface<'a>(framebuffer::SimpleFrameBuffer<'a>);

impl<'a> Surface for TextureSurface<'a> {
    fn clear_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
        self.0.clear_color(red, green, blue, alpha)
    }

    fn clear_depth(&mut self, value: f32) {
        self.0.clear_depth(value)
    }

    fn clear_stencil(&mut self, value: int) {
        self.0.clear_stencil(value)
    }

    fn get_dimensions(&self) -> (uint, uint) {
        self.0.get_dimensions()
    }

    fn get_depth_buffer_bits(&self) -> Option<u16> {
        self.0.get_depth_buffer_bits()
    }

    fn get_stencil_buffer_bits(&self) -> Option<u16> {
        self.0.get_stencil_buffer_bits()
    }

    fn draw<'b, 'v, V, I, ID, U>(&mut self, vb: V, ib: &I, program: &::Program,
        uniforms: U, draw_parameters: &::DrawParameters)
        where I: ::index_buffer::ToIndicesSource<ID>,
        U: ::uniforms::Uniforms, V: ::vertex_buffer::IntoVerticesSource<'v>
    {
        self.0.draw(vb, ib, program, uniforms, draw_parameters)
    }

    fn get_blit_helper(&self) -> ::BlitHelper {
        self.0.get_blit_helper()
    }
}
<commit_msg>Improve the texture module's documentation<commit_after>/*!
A texture is an image loaded in video memory and that can be sampled in your shaders.

Textures come in ten different dimensions:

 - Textures with one dimension.
 - Textures with two dimensions.
 - Textures with two dimensions and multisampling enabled.
 - Textures with three dimensions.
 - Cube textures, which are arrays of six two-dimensional textures
   corresponding to the six faces of a cube.
 - Arrays of one-dimensional textures.
 - Arrays of two-dimensional textures.
 - Arrays of two-dimensional textures with multisampling enabled.
 - Arrays of cube textures.
 - Buffer textures, which are one-dimensional textures that are mapped to a buffer.

In addition to this, there are six kinds of texture formats:

 - The texture contains floating-point data,
   with either the `Compressed` prefix or no prefix at all.
 - The texture contains signed integers, with the `Integral` prefix.
 - The texture contains unsigned integers, with the `Unsigned` prefix.
 - The texture contains depth informations, with the `Depth` prefix.
 - The texture contains stencil informations, with the `Stencil` prefix.
 - The texture contains depth and stencil informations, with the `DepthStencil` prefix.

Each combinaison of dimensions and format corresponds to a sampler type in GLSL. For example
a `IntegralTexture3d` can only be binded to a `isampler3D` uniform in GLSL. Some combinaisons
don't exist, like `DepthBufferTexture`.

The difference between compressed textures and non-compressed textures is that you can't do
render-to-texture on the former.

The most common types of textures are `CompressedTexture2d` and `Texture2d` (the two dimensions
being the width and height), it is what you will use most of the time.

*/
use {gl, framebuffer};

#[cfg(feature = "image")]
use image;

use buffer::{mod, Buffer};
use uniforms::{UniformValue, IntoUniformValue, Sampler};
use {Surface, GlObject, ToGlEnum};

use self::tex_impl::TextureImplementation;

pub use self::format::{ClientFormat, TextureFormat};
pub use self::format::{UncompressedFloatFormat, UncompressedIntFormat, UncompressedUintFormat};
pub use self::format::{CompressedFormat, DepthFormat, DepthStencilFormat, StencilFormat};
pub use self::pixel::PixelValue;

mod format;
mod pixel;
mod tex_impl;

include!(concat!(env!("OUT_DIR"), "/textures.rs"));

/// Trait that describes a texture.
pub trait Texture {
    /// Returns the width in pixels of the texture.
    fn get_width(&self) -> u32;

    /// Returns the height in pixels of the texture, or `None` for one dimension textures.
    fn get_height(&self) -> Option<u32>;

    /// Returns the depth in pixels of the texture, or `None` for one or two dimension textures.
    fn get_depth(&self) -> Option<u32>;

    /// Returns the number of textures in the array, or `None` for non-arrays.
    fn get_array_size(&self) -> Option<u32>;
}

/// Trait that describes data for a one-dimensional texture.
#[experimental = "Will be rewritten to use an associated type"]
pub trait Texture1dData<T> {
    /// Returns the format of the pixels.
    fn get_format(Option<Self>) -> ClientFormat;

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<T>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<T>) -> Self;
}

impl<P: PixelValue> Texture1dData<P> for Vec<P> {
    fn get_format(_: Option<Vec<P>>) -> ClientFormat {
        PixelValue::get_format(None::<P>)
    }

    fn into_vec(self) -> Vec<P> {
        self
    }

    fn from_vec(data: Vec<P>) -> Vec<P> {
        data
    }
}

impl<'a, P: PixelValue + Clone> Texture1dData<P> for &'a [P] {
    fn get_format(_: Option<&'a [P]>) -> ClientFormat {
        PixelValue::get_format(None::<P>)
    }

    fn into_vec(self) -> Vec<P> {
        self.to_vec()
    }

    fn from_vec(_: Vec<P>) -> &'a [P] {
        panic!()        // TODO: what to do here?
    }
}

/// Trait that describes data for a two-dimensional texture.
#[experimental = "Will be rewritten to use an associated type"]
pub trait Texture2dData<P> {
    /// Returns the format of the pixels.
    fn get_format(Option<Self>) -> ClientFormat;

    /// Returns the dimensions of the texture.
    fn get_dimensions(&self) -> (u32, u32);

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<P>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<P>, width: u32) -> Self;
}

impl<P: PixelValue + Clone> Texture2dData<P> for Vec<Vec<P>> {      // TODO: remove Clone
    fn get_format(_: Option<Vec<Vec<P>>>) -> ClientFormat {
        PixelValue::get_format(None::<P>)
    }

    fn get_dimensions(&self) -> (u32, u32) {
        (self.iter().next().map(|e| e.len()).unwrap_or(0) as u32, self.len() as u32)
    }

    fn into_vec(self) -> Vec<P> {
        self.into_iter().flat_map(|e| e.into_iter()).collect()
    }

    fn from_vec(data: Vec<P>, width: u32) -> Vec<Vec<P>> {
        data.as_slice().chunks(width as uint).map(|e| e.to_vec()).collect()
    }
}

#[cfg(feature = "image")]
impl<T, P> Texture2dData<T> for image::ImageBuffer<Vec<T>, T, P> where T: image::Primitive + Send,
    P: PixelValue + image::Pixel<T> + Clone + Copy
{
    fn get_format(_: Option<image::ImageBuffer<Vec<T>, T, P>>) -> ClientFormat {
        PixelValue::get_format(None::<P>)
    }

    fn get_dimensions(&self) -> (u32, u32) {
        use image::GenericImage;
        self.dimensions()
    }

    fn into_vec(self) -> Vec<T> {
        use image::GenericImage;
        let (width, _) = self.dimensions();

        let raw_data = self.into_vec();

        // the image library gives use rows from bottom to top, so we need to flip them
        raw_data
            .as_slice()
            .chunks(width as uint * image::Pixel::channel_count(None::<&P>) as uint)
            .rev()
            .flat_map(|row| row.iter())
            .map(|p| p.clone())
            .collect()
    }

    fn from_vec(data: Vec<T>, width: u32) -> image::ImageBuffer<Vec<T>, T, P> {
        let pixels_size = image::Pixel::channel_count(None::<&P>);
        let height = data.len() as u32 / (width * pixels_size as u32);

        // opengl gives use rows from bottom to top, so we need to flip them
        let data = data
            .as_slice()
            .chunks(width as uint * image::Pixel::channel_count(None::<&P>) as uint)
            .rev()
            .flat_map(|row| row.iter())
            .map(|p| p.clone())
            .collect();

        image::ImageBuffer::from_raw(width, height, data).unwrap()
    }
}

#[cfg(feature = "image")]
impl Texture2dData<u8> for image::DynamicImage {
    fn get_format(_: Option<image::DynamicImage>) -> ClientFormat {
        ClientFormat::U8U8U8U8
    }

    fn get_dimensions(&self) -> (u32, u32) {
        use image::GenericImage;
        self.dimensions()
    }

    fn into_vec(self) -> Vec<u8> {
        Texture2dData::into_vec(self.to_rgba())
    }

    fn from_vec(data: Vec<u8>, width: u32) -> image::DynamicImage {
        image::DynamicImage::ImageRgba8(Texture2dData::from_vec(data, width))
    }
}

/// Trait that describes data for a three-dimensional texture.
#[experimental = "Will be rewritten to use an associated type"]
pub trait Texture3dData<P> {
    /// Returns the format of the pixels.
    fn get_format(Option<Self>) -> ClientFormat;

    /// Returns the dimensions of the texture.
    fn get_dimensions(&self) -> (u32, u32, u32);

    /// Returns a vec where each element is a pixel of the texture.
    fn into_vec(self) -> Vec<P>;

    /// Builds a new object from raw data.
    fn from_vec(Vec<P>, width: u32, height: u32) -> Self;
}

impl<P: PixelValue> Texture3dData<P> for Vec<Vec<Vec<P>>> {
    fn get_format(_: Option<Vec<Vec<Vec<P>>>>) -> ClientFormat {
        PixelValue::get_format(None::<P>)
    }

    fn get_dimensions(&self) -> (u32, u32, u32) {
        (self.iter().next().and_then(|e| e.iter().next()).map(|e| e.len()).unwrap_or(0) as u32,
            self.iter().next().map(|e| e.len()).unwrap_or(0) as u32, self.len() as u32)
    }

    fn into_vec(self) -> Vec<P> {
        self.into_iter().flat_map(|e| e.into_iter()).flat_map(|e| e.into_iter()).collect()
    }

    fn from_vec(data: Vec<P>, width: u32, height: u32) -> Vec<Vec<Vec<P>>> {
        unimplemented!()        // TODO:
    }
}

/// Buffer that stores the content of a texture.
///
/// The generic type represents the type of pixels that the buffer contains.
///
/// **Note**: pixel buffers are unusable for the moment (they are not yet implemented).
pub struct PixelBuffer<T> {
    buffer: Buffer,
}

impl<T> PixelBuffer<T> where T: PixelValue {
    /// Builds a new buffer with an uninitialized content.
    pub fn new_empty(display: &super::Display, capacity: uint) -> PixelBuffer<T> {
        PixelBuffer {
            buffer: Buffer::new_empty::<buffer::PixelUnpackBuffer>(display, 1, capacity,
                                                                   gl::DYNAMIC_READ),
        }
    }

    /// Turns a `PixelBuffer<T>` into a `PixelBuffer<U>` without any check.
    pub unsafe fn transmute<U>(self) -> PixelBuffer<U> where U: PixelValue {
        PixelBuffer { buffer: self.buffer }
    }
}

/// Struct that allows you to draw on a texture.
///
/// To obtain such an object, call `texture.as_surface()`.
pub struct TextureSurface<'a>(framebuffer::SimpleFrameBuffer<'a>);

impl<'a> Surface for TextureSurface<'a> {
    fn clear_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
        self.0.clear_color(red, green, blue, alpha)
    }

    fn clear_depth(&mut self, value: f32) {
        self.0.clear_depth(value)
    }

    fn clear_stencil(&mut self, value: int) {
        self.0.clear_stencil(value)
    }

    fn get_dimensions(&self) -> (uint, uint) {
        self.0.get_dimensions()
    }

    fn get_depth_buffer_bits(&self) -> Option<u16> {
        self.0.get_depth_buffer_bits()
    }

    fn get_stencil_buffer_bits(&self) -> Option<u16> {
        self.0.get_stencil_buffer_bits()
    }

    fn draw<'b, 'v, V, I, ID, U>(&mut self, vb: V, ib: &I, program: &::Program,
        uniforms: U, draw_parameters: &::DrawParameters)
        where I: ::index_buffer::ToIndicesSource<ID>,
        U: ::uniforms::Uniforms, V: ::vertex_buffer::IntoVerticesSource<'v>
    {
        self.0.draw(vb, ib, program, uniforms, draw_parameters)
    }

    fn get_blit_helper(&self) -> ::BlitHelper {
        self.0.get_blit_helper()
    }
}
<|endoftext|>


<commit_before>use core::fmt;

use shared::descriptor;
use shared::PrivilegeLevel;

/// Specifies which element to load into a segment from
/// descriptor tables (i.e., is a index to LDT or GDT table
/// with some additional flags).
///
/// See Intel 3a, Section 3.4.2 "Segment Selectors"
bitflags! {
    #[repr(C, packed)]
    pub flags SegmentSelector: u16 {
        /// Requestor Privilege Level
        const RPL_0 = 0b00,
        const RPL_1 = 0b01,
        const RPL_2 = 0b10,
        const RPL_3 = 0b11,

        /// Table Indicator (TI) 0 means GDT is used.
        const TI_GDT = 0 << 3,
        /// Table Indicator (TI) 1 means LDT is used.
        const TI_LDT = 1 << 3,
    }
}

/// Reload code segment register.
/// Note this is special since we can not directly move
/// to %cs. Instead we push the new segment selector
/// and return value on the stack and use lretq
/// to reload cs and continue at 1:.
pub unsafe fn set_cs(sel: SegmentSelector) {

    #[cfg(target_arch="x86")]
    #[inline(always)]
    unsafe fn inner(sel: SegmentSelector) {
        asm!("pushl $0; \
              pushl $$1f; \
              lretl; \
              1:" :: "ri" (sel.bits() as usize) : "{rax}" "memory");
    }

    #[cfg(target_arch="x86_64")]
    #[inline(always)]
    unsafe fn inner(sel: SegmentSelector) {
        asm!("pushq $0; \
              leaq  1f(%rip), %rax; \
              pushq %rax; \
              lretq; \
              1:" :: "ri" (sel.bits() as usize) : "{rax}" "memory");
    }

    inner(sel)
}

impl SegmentSelector {
    /// Create a new SegmentSelector
    ///
    /// # Arguments
    ///  * `index` index in GDT or LDT array.
    ///
    pub const fn new(index: u16, rpl: PrivilegeLevel) -> SegmentSelector {
        SegmentSelector { bits: index << 3 | (rpl as u16) }
    }

    pub const fn from_raw(bits: u16) -> SegmentSelector {
        SegmentSelector { bits: bits }
    }
}

impl fmt::Display for SegmentSelector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r0 = match self.contains(RPL_0) {
            false => "",
            true => "Ring 0 segment selector.",
        };
        let r1 = match self.contains(RPL_1) {
            false => "",
            true => "Ring 1 segment selector.",
        };
        let r2 = match self.contains(RPL_2) {
            false => "",
            true => "Ring 2 segment selector.",
        };
        let r3 = match self.contains(RPL_3) {
            false => "",
            true => "Ring 3 segment selector.",
        };
        let tbl = match self.contains(TI_LDT) {
            false => "GDT Table",
            true => "LDT Table",
        };

        write!(f,
               "Index {} in {}, {}{}{}{}",
               self.bits >> 3,
               tbl,
               r0,
               r1,
               r2,
               r3)
        // write!(f, "Index")
    }
}

/// Reload stack segment register.
pub unsafe fn load_ss(sel: SegmentSelector) {
    asm!("movw $0, %ss " :: "r" (sel) : "memory");
}

/// Reload data segment register.
pub unsafe fn load_ds(sel: SegmentSelector) {
    asm!("movw $0, %ds " :: "r" (sel) : "memory");
}

/// Reload es segment register.
pub unsafe fn load_es(sel: SegmentSelector) {
    asm!("movw $0, %es " :: "r" (sel) : "memory");
}

/// Reload fs segment register.
pub unsafe fn load_fs(sel: SegmentSelector) {
    asm!("movw $0, %fs " :: "r" (sel) : "memory");
}

/// Reload gs segment register.
pub unsafe fn load_gs(sel: SegmentSelector) {
    asm!("movw $0, %gs " :: "r" (sel) : "memory");
}

/// Returns the current value of the code segment register.
pub fn cs() -> SegmentSelector {
    let segment: u16;
    unsafe { asm!("mov %cs, $0" : "=r" (segment) ) };
    SegmentSelector::from_raw(segment)
}

bitflags! {
    /// Data segment types. All are readable.
    ///
    /// See Table 3-1, "Code- and Data-Segment Types"
    pub flags DataAccess: u8 {
        /// Segment is writable
        const DATA_WRITE = 1 << 1,
        /// Segment grows down, for stack
        const DATA_EXPAND_DOWN = 1 << 2,
    }
}

bitflags! {
    /// Code segment types. All are executable.
    ///
    /// See Table 3-1, "Code- and Data-Segment Types"
    pub flags CodeAccess: u8 {
        /// Segment is readable
        const CODE_READ = 1 << 1,
        /// Segment is callable from segment with fewer privileges.
        const CODE_CONFORMING = 1 << 2,
    }
}

/// Umbrella Segment Type.
///
/// See Table 3-1, "Code- and Data-Segment Types"
#[repr(u8)]
pub enum Type {
    Data(DataAccess),
    Code(CodeAccess),
}

impl Type {
    pub fn pack(self) -> u8 {
        match self {
            Type::Data(d) => d.bits | 0b0_000,
            Type::Code(c) => c.bits | 0b1_000,
        }
    }
}

/// Entry for GDT or LDT. Provides size and location of a segment.
///
/// See Intel 3a, Section 3.4.5 "Segment Descriptors", and Section 3.5.2
/// "Segment Descriptor Tables in IA-32e Mode", especially Figure 3-8.
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct SegmentDescriptor {
    limit1: u16,
    base1: u16,
    base2: u8,
    access: descriptor::Flags,
    limit2_flags: Flags,
    base3: u8,
}

/// This is data-structure is a ugly mess thing so we provide some
/// convenience function to program it.
impl SegmentDescriptor {
    pub const NULL: SegmentDescriptor = SegmentDescriptor {
        base1: 0,
        base2: 0,
        base3: 0,
        access: descriptor::Flags::BLANK,
        limit1: 0,
        limit2_flags: Flags::BLANK,
    };

    pub fn new(base: u32, limit: u32,
               ty: Type, accessed: bool, dpl: PrivilegeLevel) -> SegmentDescriptor
    {
        let fine_grained = limit < 0x100000;
        let (limit1, limit2) = if fine_grained {
            ((limit & 0xFFFF) as u16, ((limit & 0xF0000) >> 16) as u8)
        } else {
            if ((limit - 0xFFF) & 0xFFF) > 0 {
                panic!("bad segment limit for GDT entry");
            }
            (((limit & 0xFFFF000) >> 12) as u16, ((limit & 0xF0000000) >> 28) as u8)
        };
        let ty1 = descriptor::Type::SegmentDescriptor {
            ty: ty,
            accessed: accessed
        };
        SegmentDescriptor {
            base1: base as u16,
            base2: ((base as usize & 0xFF0000) >> 16) as u8,
            base3: ((base as usize & 0xFF000000) >> 24) as u8,
            access: descriptor::Flags::from_type(ty1)
                |   descriptor::Flags::from_priv(dpl),
            limit1: limit1,
            limit2_flags: FLAGS_DB
                | if fine_grained { FLAGS_G } else { Flags::empty() }
                | Flags::from_limit2(limit2),
        }
    }
}

bitflags! {
    pub flags Flags: u8 {
        /// Available for use by system software.
        const FLAGS_AVL  = 1 << 4,
        /// 64-bit code segment (IA-32e mode only).
        const FLAGS_L    = 1 << 5,
        /// Default operation size (0 = 16-bit segment, 1 = 32-bit segment).
        const FLAGS_DB   = 1 << 6,
        /// Granularity (0 = limit in bytes, 1 = limt in 4 KiB Pages).
        const FLAGS_G    = 1 << 7,

    }
}

impl Flags {
    pub const BLANK: Flags = Flags { bits: 0 };

    pub fn from_limit2(limit2: u8) -> Flags {
        assert_eq!(limit2 & !0b111, 0);
        Flags { bits: limit2 }
    }
}
<commit_msg>Fix clobber syntax<commit_after>use core::fmt;

use shared::descriptor;
use shared::PrivilegeLevel;

/// Specifies which element to load into a segment from
/// descriptor tables (i.e., is a index to LDT or GDT table
/// with some additional flags).
///
/// See Intel 3a, Section 3.4.2 "Segment Selectors"
bitflags! {
    #[repr(C, packed)]
    pub flags SegmentSelector: u16 {
        /// Requestor Privilege Level
        const RPL_0 = 0b00,
        const RPL_1 = 0b01,
        const RPL_2 = 0b10,
        const RPL_3 = 0b11,

        /// Table Indicator (TI) 0 means GDT is used.
        const TI_GDT = 0 << 3,
        /// Table Indicator (TI) 1 means LDT is used.
        const TI_LDT = 1 << 3,
    }
}

/// Reload code segment register.
/// Note this is special since we can not directly move
/// to %cs. Instead we push the new segment selector
/// and return value on the stack and use lretq
/// to reload cs and continue at 1:.
pub unsafe fn set_cs(sel: SegmentSelector) {

    #[cfg(target_arch="x86")]
    #[inline(always)]
    unsafe fn inner(sel: SegmentSelector) {
        asm!("pushl $0; \
              pushl $$1f; \
              lretl; \
              1:" :: "ri" (sel.bits() as usize) : "rax" "memory");
    }

    #[cfg(target_arch="x86_64")]
    #[inline(always)]
    unsafe fn inner(sel: SegmentSelector) {
        asm!("pushq $0; \
              leaq  1f(%rip), %rax; \
              pushq %rax; \
              lretq; \
              1:" :: "ri" (sel.bits() as usize) : "rax" "memory");
    }

    inner(sel)
}

impl SegmentSelector {
    /// Create a new SegmentSelector
    ///
    /// # Arguments
    ///  * `index` index in GDT or LDT array.
    ///
    pub const fn new(index: u16, rpl: PrivilegeLevel) -> SegmentSelector {
        SegmentSelector { bits: index << 3 | (rpl as u16) }
    }

    pub const fn from_raw(bits: u16) -> SegmentSelector {
        SegmentSelector { bits: bits }
    }
}

impl fmt::Display for SegmentSelector {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let r0 = match self.contains(RPL_0) {
            false => "",
            true => "Ring 0 segment selector.",
        };
        let r1 = match self.contains(RPL_1) {
            false => "",
            true => "Ring 1 segment selector.",
        };
        let r2 = match self.contains(RPL_2) {
            false => "",
            true => "Ring 2 segment selector.",
        };
        let r3 = match self.contains(RPL_3) {
            false => "",
            true => "Ring 3 segment selector.",
        };
        let tbl = match self.contains(TI_LDT) {
            false => "GDT Table",
            true => "LDT Table",
        };

        write!(f,
               "Index {} in {}, {}{}{}{}",
               self.bits >> 3,
               tbl,
               r0,
               r1,
               r2,
               r3)
        // write!(f, "Index")
    }
}

/// Reload stack segment register.
pub unsafe fn load_ss(sel: SegmentSelector) {
    asm!("movw $0, %ss " :: "r" (sel) : "memory");
}

/// Reload data segment register.
pub unsafe fn load_ds(sel: SegmentSelector) {
    asm!("movw $0, %ds " :: "r" (sel) : "memory");
}

/// Reload es segment register.
pub unsafe fn load_es(sel: SegmentSelector) {
    asm!("movw $0, %es " :: "r" (sel) : "memory");
}

/// Reload fs segment register.
pub unsafe fn load_fs(sel: SegmentSelector) {
    asm!("movw $0, %fs " :: "r" (sel) : "memory");
}

/// Reload gs segment register.
pub unsafe fn load_gs(sel: SegmentSelector) {
    asm!("movw $0, %gs " :: "r" (sel) : "memory");
}

/// Returns the current value of the code segment register.
pub fn cs() -> SegmentSelector {
    let segment: u16;
    unsafe { asm!("mov %cs, $0" : "=r" (segment) ) };
    SegmentSelector::from_raw(segment)
}

bitflags! {
    /// Data segment types. All are readable.
    ///
    /// See Table 3-1, "Code- and Data-Segment Types"
    pub flags DataAccess: u8 {
        /// Segment is writable
        const DATA_WRITE = 1 << 1,
        /// Segment grows down, for stack
        const DATA_EXPAND_DOWN = 1 << 2,
    }
}

bitflags! {
    /// Code segment types. All are executable.
    ///
    /// See Table 3-1, "Code- and Data-Segment Types"
    pub flags CodeAccess: u8 {
        /// Segment is readable
        const CODE_READ = 1 << 1,
        /// Segment is callable from segment with fewer privileges.
        const CODE_CONFORMING = 1 << 2,
    }
}

/// Umbrella Segment Type.
///
/// See Table 3-1, "Code- and Data-Segment Types"
#[repr(u8)]
pub enum Type {
    Data(DataAccess),
    Code(CodeAccess),
}

impl Type {
    pub fn pack(self) -> u8 {
        match self {
            Type::Data(d) => d.bits | 0b0_000,
            Type::Code(c) => c.bits | 0b1_000,
        }
    }
}

/// Entry for GDT or LDT. Provides size and location of a segment.
///
/// See Intel 3a, Section 3.4.5 "Segment Descriptors", and Section 3.5.2
/// "Segment Descriptor Tables in IA-32e Mode", especially Figure 3-8.
#[derive(Copy, Clone, Debug)]
#[repr(C, packed)]
pub struct SegmentDescriptor {
    limit1: u16,
    base1: u16,
    base2: u8,
    access: descriptor::Flags,
    limit2_flags: Flags,
    base3: u8,
}

/// This is data-structure is a ugly mess thing so we provide some
/// convenience function to program it.
impl SegmentDescriptor {
    pub const NULL: SegmentDescriptor = SegmentDescriptor {
        base1: 0,
        base2: 0,
        base3: 0,
        access: descriptor::Flags::BLANK,
        limit1: 0,
        limit2_flags: Flags::BLANK,
    };

    pub fn new(base: u32, limit: u32,
               ty: Type, accessed: bool, dpl: PrivilegeLevel) -> SegmentDescriptor
    {
        let fine_grained = limit < 0x100000;
        let (limit1, limit2) = if fine_grained {
            ((limit & 0xFFFF) as u16, ((limit & 0xF0000) >> 16) as u8)
        } else {
            if ((limit - 0xFFF) & 0xFFF) > 0 {
                panic!("bad segment limit for GDT entry");
            }
            (((limit & 0xFFFF000) >> 12) as u16, ((limit & 0xF0000000) >> 28) as u8)
        };
        let ty1 = descriptor::Type::SegmentDescriptor {
            ty: ty,
            accessed: accessed
        };
        SegmentDescriptor {
            base1: base as u16,
            base2: ((base as usize & 0xFF0000) >> 16) as u8,
            base3: ((base as usize & 0xFF000000) >> 24) as u8,
            access: descriptor::Flags::from_type(ty1)
                |   descriptor::Flags::from_priv(dpl),
            limit1: limit1,
            limit2_flags: FLAGS_DB
                | if fine_grained { FLAGS_G } else { Flags::empty() }
                | Flags::from_limit2(limit2),
        }
    }
}

bitflags! {
    pub flags Flags: u8 {
        /// Available for use by system software.
        const FLAGS_AVL  = 1 << 4,
        /// 64-bit code segment (IA-32e mode only).
        const FLAGS_L    = 1 << 5,
        /// Default operation size (0 = 16-bit segment, 1 = 32-bit segment).
        const FLAGS_DB   = 1 << 6,
        /// Granularity (0 = limit in bytes, 1 = limt in 4 KiB Pages).
        const FLAGS_G    = 1 << 7,

    }
}

impl Flags {
    pub const BLANK: Flags = Flags { bits: 0 };

    pub fn from_limit2(limit2: u8) -> Flags {
        assert_eq!(limit2 & !0b111, 0);
        Flags { bits: limit2 }
    }
}
<|endoftext|>


<commit_before>#![crate_name = "uu_uniq"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Chirag B Jadwani <chirag.jadwani@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 */

extern crate getopts;

#[macro_use]
extern crate uucore;

use getopts::{Matches, Options};
use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use std::path::Path;
use std::str::FromStr;

static NAME: &'static str = "uniq";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(PartialEq)]
enum Delimiters {
    Prepend,
    Separate,
    None,
}

struct Uniq {
    repeats_only: bool,
    uniques_only: bool,
    all_repeated: bool,
    delimiters: Delimiters,
    show_counts: bool,
    skip_fields: Option<usize>,
    slice_start: Option<usize>,
    slice_stop: Option<usize>,
    ignore_case: bool,
    zero_terminated: bool,
}

fn iter_ne<'a>(lhs: Box<Iterator<Item = char> + 'a>, rhs: Box<Iterator<Item = char> + 'a>) -> bool {
    lhs.ne(rhs)
}

impl Uniq {
    pub fn print_uniq<R: Read, W: Write>(
        &self,
        reader: &mut BufReader<R>,
        writer: &mut BufWriter<W>,
    ) {
        let mut lines: Vec<String> = vec![];
        let mut first_line_printed = false;
        let delimiters = &self.delimiters;
        let line_terminator = self.get_line_terminator();

        for io_line in reader.split(line_terminator) {
            let line = String::from_utf8(crash_if_err!(1, io_line)).unwrap();
            if !lines.is_empty() && self.cmp_keys(&lines[0], &line) {
                let print_delimiter = delimiters == &Delimiters::Prepend
                    || (delimiters == &Delimiters::Separate && first_line_printed);
                first_line_printed |= self.print_lines(writer, &lines, print_delimiter);
                lines.truncate(0);
            }
            lines.push(line);
        }
        if !lines.is_empty() {
            let print_delimiter = delimiters == &Delimiters::Prepend
                || (delimiters == &Delimiters::Separate && first_line_printed);
            self.print_lines(writer, &lines, print_delimiter);
        }
    }

    fn skip_fields<'a>(&self, line: &'a str) -> &'a str {
        if let Some(skip_fields) = self.skip_fields {
            if line.split_whitespace().count() > skip_fields {
                let mut field = 0;
                let mut i = 0;
                while field < skip_fields && i < line.len() {
                    while i < line.len() && line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    while i < line.len() && !line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    field = field + 1;
                }
                &line[i..]
            } else {
                ""
            }
        } else {
            line
        }
    }

    fn get_line_terminator(&self) -> u8 {
        if self.zero_terminated {
            0
        } else {
            '\n' as u8
        }
    }

    fn cmp_key<'a>(&'a self, line: &'a str) -> Box<Iterator<Item = char> + 'a> {
        let fields_to_check = self.skip_fields(line);
        let len = fields_to_check.len();
        let slice_start = self.slice_start.unwrap_or(0);
        let slice_stop = self.slice_stop.unwrap_or(len);
        if len > 0 {
            // fast path: avoid doing any work if there is no need to skip or map to lower-case
            if !self.ignore_case && slice_start == 0 && slice_stop == len {
                return Box::new(fields_to_check.chars());
            }

            // fast path: avoid skipping
            if self.ignore_case && slice_start == 0 && slice_stop == len {
                return Box::new(fields_to_check.chars().map(|c| match c {
                    'a'...'z' => ((c as u8) - 32) as char,
                    _ => c,
                }));
            }

            // fast path: we can avoid mapping chars to upper-case, if we don't want to ignore the case
            if !self.ignore_case {
                return Box::new(fields_to_check.chars().skip(slice_start).take(slice_stop));
            }

            Box::new(
                fields_to_check
                    .chars()
                    .skip(slice_start)
                    .take(slice_stop)
                    .map(|c| match c {
                        'a'...'z' => ((c as u8) - 32) as char,
                        _ => c,
                    }),
            )
        } else {
            Box::new(fields_to_check.chars())
        }
    }

    fn print_lines<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        lines: &[String],
        print_delimiter: bool,
    ) -> bool {
        let mut first_line_printed = false;
        let mut count = if self.all_repeated { 1 } else { lines.len() };
        if lines.len() == 1 && !self.repeats_only || lines.len() > 1 && !self.uniques_only {
            self.print_line(writer, &lines[0], count, print_delimiter);
            first_line_printed = true;
            count += 1;
        }
        if self.all_repeated {
            for line in lines[1..].iter() {
                self.print_line(writer, line, count, print_delimiter && !first_line_printed);
                first_line_printed = true;
                count += 1;
            }
        }
        first_line_printed
    }

    fn print_line<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        line: &str,
        count: usize,
        print_delimiter: bool,
    ) {
        let line_terminator = self.get_line_terminator();

        if print_delimiter {
            crash_if_err!(1, writer.write_all(&[line_terminator]));
        }

        crash_if_err!(
            1,
            if self.show_counts {
                writer.write_all(format!("{:7} {}", count, line).as_bytes())
            } else {
                writer.write_all(line.as_bytes())
            }
        );
        crash_if_err!(1, writer.write_all(&[line_terminator]));
    }
}

fn opt_parsed<T: FromStr>(opt_name: &str, matches: &Matches) -> Option<T> {
    matches.opt_str(opt_name).map(|arg_str| {
        let opt_val: Option<T> = arg_str.parse().ok();
        opt_val.unwrap_or_else(|| crash!(1, "Invalid argument for {}: {}", opt_name, arg_str))
    })
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();

    opts.optflag("c", "count", "prefix lines by the number of occurrences");
    opts.optflag("d", "repeated", "only print duplicate lines");
    opts.optflagopt(
        "D",
        "all-repeated",
        "print all duplicate lines delimit-method={none(default),prepend,separate} Delimiting is done with blank lines",
        "delimit-method"
    );
    opts.optopt(
        "f",
        "skip-fields",
        "avoid comparing the first N fields",
        "N",
    );
    opts.optopt(
        "s",
        "skip-chars",
        "avoid comparing the first N characters",
        "N",
    );
    opts.optopt(
        "w",
        "check-chars",
        "compare no more than N characters in lines",
        "N",
    );
    opts.optflag(
        "i",
        "ignore-case",
        "ignore differences in case when comparing",
    );
    opts.optflag("u", "unique", "only print unique lines");
    opts.optflag("z", "zero-terminated", "end lines with 0 byte, not newline");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f),
    };

    if matches.opt_present("help") {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {0} [OPTION]... [FILE]...", NAME);
        println!("");
        print!(
            "{}",
            opts.usage(
                "Filter adjacent matching lines from INPUT (or standard input),\n\
                 writing to OUTPUT (or standard output)."
            )
        );
        println!("");
        println!(
            "Note: '{0}' does not detect repeated lines unless they are adjacent.\n\
             You may want to sort the input first, or use 'sort -u' without '{0}'.\n",
            NAME
        );
    } else if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
    } else {
        let (in_file_name, out_file_name) = match matches.free.len() {
            0 => ("-".to_owned(), "-".to_owned()),
            1 => (matches.free[0].clone(), "-".to_owned()),
            2 => (matches.free[0].clone(), matches.free[1].clone()),
            _ => {
                crash!(1, "Extra operand: {}", matches.free[2]);
            }
        };
        let uniq = Uniq {
            repeats_only: matches.opt_present("repeated") || matches.opt_present("all-repeated"),
            uniques_only: matches.opt_present("unique"),
            all_repeated: matches.opt_present("all-repeated"),
            delimiters: match matches.opt_default("all-repeated", "none") {
                Some(ref opt_arg) if opt_arg != "none" => match &(*opt_arg.as_str()) {
                    "prepend" => Delimiters::Prepend,
                    "separate" => Delimiters::Separate,
                    _ => crash!(1, "Incorrect argument for all-repeated: {}", opt_arg),
                },
                _ => Delimiters::None,
            },
            show_counts: matches.opt_present("count"),
            skip_fields: opt_parsed("skip-fields", &matches),
            slice_start: opt_parsed("skip-chars", &matches),
            slice_stop: opt_parsed("check-chars", &matches),
            ignore_case: matches.opt_present("ignore-case"),
            zero_terminated: matches.opt_present("zero-terminated"),
        };
        uniq.print_uniq(
            &mut open_input_file(in_file_name),
            &mut open_output_file(out_file_name),
        );
    }
    0
}

fn open_input_file(in_file_name: String) -> BufReader<Box<Read + 'static>> {
    let in_file = if in_file_name == "-" {
        Box::new(stdin()) as Box<Read>
    } else {
        let path = Path::new(&in_file_name[..]);
        let in_file = File::open(&path);
        let r = crash_if_err!(1, in_file);
        Box::new(r) as Box<Read>
    };
    BufReader::new(in_file)
}

fn open_output_file(out_file_name: String) -> BufWriter<Box<Write + 'static>> {
    let out_file = if out_file_name == "-" {
        Box::new(stdout()) as Box<Write>
    } else {
        let path = Path::new(&out_file_name[..]);
        let in_file = File::create(&path);
        let w = crash_if_err!(1, in_file);
        Box::new(w) as Box<Write>
    };
    BufWriter::new(out_file)
}
<commit_msg>uniq: avoid allocations for the iterator<commit_after>#![crate_name = "uu_uniq"]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Chirag B Jadwani <chirag.jadwani@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 */

extern crate getopts;

#[macro_use]
extern crate uucore;

use getopts::{Matches, Options};
use std::fs::File;
use std::io::{stdin, stdout, BufRead, BufReader, BufWriter, Read, Write};
use std::path::Path;
use std::str::FromStr;

static NAME: &'static str = "uniq";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

#[derive(PartialEq)]
enum Delimiters {
    Prepend,
    Separate,
    None,
}

struct Uniq {
    repeats_only: bool,
    uniques_only: bool,
    all_repeated: bool,
    delimiters: Delimiters,
    show_counts: bool,
    skip_fields: Option<usize>,
    slice_start: Option<usize>,
    slice_stop: Option<usize>,
    ignore_case: bool,
    zero_terminated: bool,
}

impl Uniq {
    pub fn print_uniq<R: Read, W: Write>(
        &self,
        reader: &mut BufReader<R>,
        writer: &mut BufWriter<W>,
    ) {
        let mut lines: Vec<String> = vec![];
        let mut first_line_printed = false;
        let delimiters = &self.delimiters;
        let line_terminator = self.get_line_terminator();

        for io_line in reader.split(line_terminator) {
            let line = String::from_utf8(crash_if_err!(1, io_line)).unwrap();
            if !lines.is_empty() && self.cmp_keys(&lines[0], &line) {
                let print_delimiter = delimiters == &Delimiters::Prepend
                    || (delimiters == &Delimiters::Separate && first_line_printed);
                first_line_printed |= self.print_lines(writer, &lines, print_delimiter);
                lines.truncate(0);
            }
            lines.push(line);
        }
        if !lines.is_empty() {
            let print_delimiter = delimiters == &Delimiters::Prepend
                || (delimiters == &Delimiters::Separate && first_line_printed);
            self.print_lines(writer, &lines, print_delimiter);
        }
    }

    fn skip_fields<'a>(&self, line: &'a str) -> &'a str {
        if let Some(skip_fields) = self.skip_fields {
            if line.split_whitespace().count() > skip_fields {
                let mut field = 0;
                let mut i = 0;
                while field < skip_fields && i < line.len() {
                    while i < line.len() && line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    while i < line.len() && !line.chars().nth(i).unwrap().is_whitespace() {
                        i = i + 1;
                    }
                    field = field + 1;
                }
                &line[i..]
            } else {
                ""
            }
        } else {
            line
        }
    }

    fn get_line_terminator(&self) -> u8 {
        if self.zero_terminated {
            0
        } else {
            '\n' as u8
        }
    }

    fn cmp_keys(&self, first: &str, second: &str) -> bool {
        self.cmp_key(first, |first_iter| {
            self.cmp_key(second, |second_iter| first_iter.ne(second_iter))
        })
    }

    fn cmp_key<F>(&self, line: &str, mut closure: F) -> bool
    where
        F: FnMut(&mut Iterator<Item = char>) -> bool,
    {
        let fields_to_check = self.skip_fields(line);
        let len = fields_to_check.len();
        let slice_start = self.slice_start.unwrap_or(0);
        let slice_stop = self.slice_stop.unwrap_or(len);
        if len > 0 {
            // fast path: avoid doing any work if there is no need to skip or map to lower-case
            if !self.ignore_case && slice_start == 0 && slice_stop == len {
                return closure(&mut fields_to_check.chars());
            }

            // fast path: avoid skipping
            if self.ignore_case && slice_start == 0 && slice_stop == len {
                return closure(&mut fields_to_check.chars().map(|c| match c {
                    'a'...'z' => ((c as u8) - 32) as char,
                    _ => c,
                }));
            }

            // fast path: we can avoid mapping chars to upper-case, if we don't want to ignore the case
            if !self.ignore_case {
                return closure(&mut fields_to_check.chars().skip(slice_start).take(slice_stop));
            }

            closure(
                &mut fields_to_check
                    .chars()
                    .skip(slice_start)
                    .take(slice_stop)
                    .map(|c| match c {
                        'a'...'z' => ((c as u8) - 32) as char,
                        _ => c,
                    }),
            )
        } else {
            closure(&mut fields_to_check.chars())
        }
    }

    fn print_lines<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        lines: &[String],
        print_delimiter: bool,
    ) -> bool {
        let mut first_line_printed = false;
        let mut count = if self.all_repeated { 1 } else { lines.len() };
        if lines.len() == 1 && !self.repeats_only || lines.len() > 1 && !self.uniques_only {
            self.print_line(writer, &lines[0], count, print_delimiter);
            first_line_printed = true;
            count += 1;
        }
        if self.all_repeated {
            for line in lines[1..].iter() {
                self.print_line(writer, line, count, print_delimiter && !first_line_printed);
                first_line_printed = true;
                count += 1;
            }
        }
        first_line_printed
    }

    fn print_line<W: Write>(
        &self,
        writer: &mut BufWriter<W>,
        line: &str,
        count: usize,
        print_delimiter: bool,
    ) {
        let line_terminator = self.get_line_terminator();

        if print_delimiter {
            crash_if_err!(1, writer.write_all(&[line_terminator]));
        }

        crash_if_err!(
            1,
            if self.show_counts {
                writer.write_all(format!("{:7} {}", count, line).as_bytes())
            } else {
                writer.write_all(line.as_bytes())
            }
        );
        crash_if_err!(1, writer.write_all(&[line_terminator]));
    }
}

fn opt_parsed<T: FromStr>(opt_name: &str, matches: &Matches) -> Option<T> {
    matches.opt_str(opt_name).map(|arg_str| {
        let opt_val: Option<T> = arg_str.parse().ok();
        opt_val.unwrap_or_else(|| crash!(1, "Invalid argument for {}: {}", opt_name, arg_str))
    })
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();

    opts.optflag("c", "count", "prefix lines by the number of occurrences");
    opts.optflag("d", "repeated", "only print duplicate lines");
    opts.optflagopt(
        "D",
        "all-repeated",
        "print all duplicate lines delimit-method={none(default),prepend,separate} Delimiting is done with blank lines",
        "delimit-method"
    );
    opts.optopt(
        "f",
        "skip-fields",
        "avoid comparing the first N fields",
        "N",
    );
    opts.optopt(
        "s",
        "skip-chars",
        "avoid comparing the first N characters",
        "N",
    );
    opts.optopt(
        "w",
        "check-chars",
        "compare no more than N characters in lines",
        "N",
    );
    opts.optflag(
        "i",
        "ignore-case",
        "ignore differences in case when comparing",
    );
    opts.optflag("u", "unique", "only print unique lines");
    opts.optflag("z", "zero-terminated", "end lines with 0 byte, not newline");
    opts.optflag("h", "help", "display this help and exit");
    opts.optflag("V", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}", f),
    };

    if matches.opt_present("help") {
        println!("{} {}", NAME, VERSION);
        println!("");
        println!("Usage:");
        println!("  {0} [OPTION]... [FILE]...", NAME);
        println!("");
        print!(
            "{}",
            opts.usage(
                "Filter adjacent matching lines from INPUT (or standard input),\n\
                 writing to OUTPUT (or standard output)."
            )
        );
        println!("");
        println!(
            "Note: '{0}' does not detect repeated lines unless they are adjacent.\n\
             You may want to sort the input first, or use 'sort -u' without '{0}'.\n",
            NAME
        );
    } else if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
    } else {
        let (in_file_name, out_file_name) = match matches.free.len() {
            0 => ("-".to_owned(), "-".to_owned()),
            1 => (matches.free[0].clone(), "-".to_owned()),
            2 => (matches.free[0].clone(), matches.free[1].clone()),
            _ => {
                crash!(1, "Extra operand: {}", matches.free[2]);
            }
        };
        let uniq = Uniq {
            repeats_only: matches.opt_present("repeated") || matches.opt_present("all-repeated"),
            uniques_only: matches.opt_present("unique"),
            all_repeated: matches.opt_present("all-repeated"),
            delimiters: match matches.opt_default("all-repeated", "none") {
                Some(ref opt_arg) if opt_arg != "none" => match &(*opt_arg.as_str()) {
                    "prepend" => Delimiters::Prepend,
                    "separate" => Delimiters::Separate,
                    _ => crash!(1, "Incorrect argument for all-repeated: {}", opt_arg),
                },
                _ => Delimiters::None,
            },
            show_counts: matches.opt_present("count"),
            skip_fields: opt_parsed("skip-fields", &matches),
            slice_start: opt_parsed("skip-chars", &matches),
            slice_stop: opt_parsed("check-chars", &matches),
            ignore_case: matches.opt_present("ignore-case"),
            zero_terminated: matches.opt_present("zero-terminated"),
        };
        uniq.print_uniq(
            &mut open_input_file(in_file_name),
            &mut open_output_file(out_file_name),
        );
    }
    0
}

fn open_input_file(in_file_name: String) -> BufReader<Box<Read + 'static>> {
    let in_file = if in_file_name == "-" {
        Box::new(stdin()) as Box<Read>
    } else {
        let path = Path::new(&in_file_name[..]);
        let in_file = File::open(&path);
        let r = crash_if_err!(1, in_file);
        Box::new(r) as Box<Read>
    };
    BufReader::new(in_file)
}

fn open_output_file(out_file_name: String) -> BufWriter<Box<Write + 'static>> {
    let out_file = if out_file_name == "-" {
        Box::new(stdout()) as Box<Write>
    } else {
        let path = Path::new(&out_file_name[..]);
        let in_file = File::create(&path);
        let w = crash_if_err!(1, in_file);
        Box::new(w) as Box<Write>
    };
    BufWriter::new(out_file)
}
<|endoftext|>


<commit_before>extern crate time;

use std::fmt;
use std::io;
use std::io::{Error, Write};
use std::cmp::{Ord, Ordering};

pub enum LogLevel {
    ERROR,
    WARN,
    INFO,
    VERBOSE
}

// ERROR > WARN > INFO > VERBOSE
impl Ord for LogLevel {
    fn cmp(&self, other: &Self) -> Ordering {
        match *self {
            LogLevel::ERROR => match *other {
                        LogLevel::ERROR => Ordering::Equal,
                        _ => Ordering::Greater,
                    },
            LogLevel::WARN => match *other {
                        LogLevel::ERROR => Ordering::Less,
                        LogLevel::WARN => Ordering::Equal,
                        _ => Ordering::Greater,
                    },
            LogLevel::INFO => match *other {
                        LogLevel::VERBOSE => Ordering::Greater,
                        LogLevel::INFO => Ordering::Equal,
                        _ => Ordering::Less,
                    },
            LogLevel::VERBOSE => match *other {
                        LogLevel::VERBOSE => Ordering::Equal,
                        _ => Ordering::Less,
                    },
        }
    }
}

impl Eq for LogLevel {}

impl PartialEq for LogLevel {

    fn eq(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Equal
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }

}

impl PartialOrd for LogLevel {

    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }

    fn lt(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Less
    }

    fn le(&self, other: &Self) -> bool {
        self.cmp(other) != Ordering::Greater
    }

    fn gt(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Greater
    }

    fn ge(&self, other: &Self) -> bool {
        self.cmp(other) != Ordering::Less
    }
}

/// Set global log level here
static LOG_LEVEL: LogLevel = LogLevel::INFO;

/// the log function returning a result
///
/// # Examples
/// '''
/// log(LogLevel::ERROR, format_args!("This is bad!")).unwrap();
/// '''
pub fn log(level: LogLevel, args: fmt::Arguments) -> Result<(), Error> {

    if level < LOG_LEVEL {
        return Ok(());
    }

    let stderr = io::stderr();
    let stdout = io::stdout();

    let mut stderr_lock = stderr.lock();
    let mut stdout_lock = stdout.lock();

    let cur_time = time::now();

    match level {
        LogLevel::ERROR => writeln!(stderr_lock, "[ERROR] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::WARN => writeln!(stdout_lock, "[WARN] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::INFO => writeln!(stdout_lock, "[INFO] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::VERBOSE => writeln!(stdout_lock, "[VERBOSE] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
    }

}

/// a log function ignoring any failure
/// "log something, if possible"
///
/// # Examples
/// '''
/// try_log(LogLevel::ERROR, format_args!("This is bad!"));
/// '''
pub fn try_log(level: LogLevel, args: fmt::Arguments) {
    let _ = log(level, args);
}

// Helper Macro

/// Error Macro
///
/// # Examples
/// '''
/// error!("This is bad!");
/// '''
macro_rules! log_error {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::ERROR, format_args!($($arg)*)));
}

/// Warning Macro
///
/// # Examples
/// '''
/// log_warn!("This is maybe bad?!");
/// '''
macro_rules! log_warn {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::WARN, format_args!($($arg)*)));
}

/// Info Macro
///
/// # Examples
/// '''
/// log_info!("This is just to let you know!");
/// '''
macro_rules! log_info {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::INFO, format_args!($($arg)*)));
}

/// Verbose Macro
///
/// # Examples
/// '''
/// log_verbose!("You must really like spam!");
/// '''
macro_rules! log_verbose {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::VERBOSE, format_args!($($arg)*)));
}

#[test]
fn test() {
    log_info!("Test!");
}

//To-Do add a way to check the result automatically
#[test]
fn multi_thread_test() {
    let mut joins = Vec::new();
    for _ in 0..10 {
        joins.push(std::thread::spawn(move || {
            log_info!("No corruption should happen in this ultra-extra-super-long string output even if run in multiple threads.");
        }));
    }
    for handle in joins {
        let _ = handle.join();
    }
}
<commit_msg>util/log: Fix ALL documentation comments<commit_after>extern crate time;

use std::fmt;
use std::io;
use std::io::{Error, Write};
use std::cmp::{Ord, Ordering};

pub enum LogLevel {
    ERROR,
    WARN,
    INFO,
    VERBOSE
}

// ERROR > WARN > INFO > VERBOSE
impl Ord for LogLevel {
    fn cmp(&self, other: &Self) -> Ordering {
        match *self {
            LogLevel::ERROR => match *other {
                        LogLevel::ERROR => Ordering::Equal,
                        _ => Ordering::Greater,
                    },
            LogLevel::WARN => match *other {
                        LogLevel::ERROR => Ordering::Less,
                        LogLevel::WARN => Ordering::Equal,
                        _ => Ordering::Greater,
                    },
            LogLevel::INFO => match *other {
                        LogLevel::VERBOSE => Ordering::Greater,
                        LogLevel::INFO => Ordering::Equal,
                        _ => Ordering::Less,
                    },
            LogLevel::VERBOSE => match *other {
                        LogLevel::VERBOSE => Ordering::Equal,
                        _ => Ordering::Less,
                    },
        }
    }
}

impl Eq for LogLevel {}

impl PartialEq for LogLevel {

    fn eq(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Equal
    }

    fn ne(&self, other: &Self) -> bool {
        !self.eq(other)
    }

}

impl PartialOrd for LogLevel {

    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }

    fn lt(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Less
    }

    fn le(&self, other: &Self) -> bool {
        self.cmp(other) != Ordering::Greater
    }

    fn gt(&self, other: &Self) -> bool {
        self.cmp(other) == Ordering::Greater
    }

    fn ge(&self, other: &Self) -> bool {
        self.cmp(other) != Ordering::Less
    }
}

/// Set global log level here
static LOG_LEVEL: LogLevel = LogLevel::INFO;

/// the log function returning a result
///
/// # Examples
/// '''
/// log(LogLevel::ERROR, format_args!("This is bad!")).unwrap();
/// '''
pub fn log(level: LogLevel, args: fmt::Arguments) -> Result<(), Error> {

    if level < LOG_LEVEL {
        return Ok(());
    }

    let stderr = io::stderr();
    let stdout = io::stdout();

    let mut stderr_lock = stderr.lock();
    let mut stdout_lock = stdout.lock();

    let cur_time = time::now();

    match level {
        LogLevel::ERROR => writeln!(stderr_lock, "[ERROR] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::WARN => writeln!(stdout_lock, "[WARN] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::INFO => writeln!(stdout_lock, "[INFO] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
        LogLevel::VERBOSE => writeln!(stdout_lock, "[VERBOSE] {}:{}:{} - {}", cur_time.tm_hour, cur_time.tm_min, cur_time.tm_sec, args),
    }

}

/// a log function ignoring any failure
/// "log something, if possible"
///
/// # Examples
/// '''
/// try_log(LogLevel::ERROR, format_args!("This is bad!"));
/// '''
pub fn try_log(level: LogLevel, args: fmt::Arguments) {
    let _ = log(level, args);
}

// Helper Macro

/// Error Macro
///
/// # Examples
/// '''
/// log_error!("This is bad!");
/// '''
macro_rules! log_error {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::ERROR, format_args!($($arg)*)));
}

/// Warning Macro
///
/// # Examples
/// '''
/// log_warn!("This is maybe bad?!");
/// '''
macro_rules! log_warn {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::WARN, format_args!($($arg)*)));
}

/// Info Macro
///
/// # Examples
/// '''
/// log_info!("This is just to let you know!");
/// '''
macro_rules! log_info {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::INFO, format_args!($($arg)*)));
}

/// Verbose Macro
///
/// # Examples
/// '''
/// log_verbose!("You must really like spam!");
/// '''
macro_rules! log_verbose {
    ($($arg:tt)*) => (::utils::log::try_log(::utils::log::LogLevel::VERBOSE, format_args!($($arg)*)));
}

#[test]
fn test() {
    log_info!("Test!");
}

//To-Do add a way to check the result automatically
#[test]
fn multi_thread_test() {
    let mut joins = Vec::new();
    for _ in 0..10 {
        joins.push(std::thread::spawn(move || {
            log_info!("No corruption should happen in this ultra-extra-super-long string output even if run in multiple threads.");
        }));
    }
    for handle in joins {
        let _ = handle.join();
    }
}
<|endoftext|>


<commit_before>#![crate_name = "users"]
#![feature(collections, core, old_io, rustc_private, std_misc)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) KokaKiwi <kokakiwi@kokakiwi.net>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: whoami (GNU coreutils) 8.22 */

// Allow dead code here in order to keep all fields, constants here, for consistency.
#![allow(dead_code, non_camel_case_types)]

extern crate getopts;
extern crate libc;

use std::ffi::{CStr, CString};
use std::old_io::print;
use std::mem;
use std::ptr;
use utmpx::*;

#[path = "../common/util.rs"]
#[macro_use]
mod util;

#[path = "../common/utmpx.rs"]
mod utmpx;

extern {
    fn getutxent() -> *const c_utmp;
    fn getutxid(ut: *const c_utmp) -> *const c_utmp;
    fn getutxline(ut: *const c_utmp) -> *const c_utmp;

    fn pututxline(ut: *const c_utmp) -> *const c_utmp;

    fn setutxent();
    fn endutxent();

    #[cfg(any(target_os = "macos", target_os = "linux"))]
    fn utmpxname(file: *const libc::c_char) -> libc::c_int;
}

#[cfg(target_os = "freebsd")]
unsafe extern fn utmpxname(_file: *const libc::c_char) -> libc::c_int {
    0
}

static NAME: &'static str = "users";

pub fn uumain(args: Vec<String>) -> i32 {
    let program = args[0].as_slice();
    let opts = [
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];

    let matches = match getopts::getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => panic!("{}", f),
    };

    if matches.opt_present("help") {
        println!("users 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {} [OPTION]... [FILE]", program);
        println!("");
        print(getopts::usage("Output who is currently logged in according to FILE.", &opts).as_slice());
        return 0;
    }

    if matches.opt_present("version") {
        println!("users 1.0.0");
        return 0;
    }

    let mut filename = DEFAULT_FILE;
    if matches.free.len() > 0 {
        filename = matches.free[0].as_slice();
    }

    exec(filename);

    0
}

fn exec(filename: &str) {
    unsafe {
        utmpxname(CString::new(filename).unwrap().as_ptr());
    }

    let mut users = vec!();

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == ptr::null() {
                break;
            }

            if (*line).ut_type == USER_PROCESS {
                let user = String::from_utf8_lossy(CStr::from_ptr(mem::transmute(&(*line).ut_user)).to_bytes()).to_string();
                users.push(user);
            }
        }

        endutxent();
    }

    if users.len() > 0 {
        users.sort();
        println!("{}", users.connect(" "));
    }
}
<commit_msg>fix `users`<commit_after>#![crate_name = "users"]
#![feature(rustc_private)]

/*
 * This file is part of the uutils coreutils package.
 *
 * (c) KokaKiwi <kokakiwi@kokakiwi.net>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

/* last synced with: whoami (GNU coreutils) 8.22 */

// Allow dead code here in order to keep all fields, constants here, for consistency.
#![allow(dead_code)]

extern crate getopts;
extern crate libc;

use std::ffi::{CStr, CString};
use std::mem;
use std::ptr;
use utmpx::*;

#[path = "../common/util.rs"]
#[macro_use]
mod util;

#[path = "../common/utmpx.rs"]
mod utmpx;

extern {
    fn getutxent() -> *const c_utmp;
    fn getutxid(ut: *const c_utmp) -> *const c_utmp;
    fn getutxline(ut: *const c_utmp) -> *const c_utmp;

    fn pututxline(ut: *const c_utmp) -> *const c_utmp;

    fn setutxent();
    fn endutxent();

    #[cfg(any(target_os = "macos", target_os = "linux"))]
    fn utmpxname(file: *const libc::c_char) -> libc::c_int;
}

#[cfg(target_os = "freebsd")]
unsafe extern fn utmpxname(_file: *const libc::c_char) -> libc::c_int {
    0
}

static NAME: &'static str = "users";

pub fn uumain(args: Vec<String>) -> i32 {
    let opts = [
        getopts::optflag("h", "help", "display this help and exit"),
        getopts::optflag("V", "version", "output version information and exit"),
    ];

    let matches = match getopts::getopts(&args[1..], &opts) {
        Ok(m) => m,
        Err(f) => panic!("{}", f),
    };

    if matches.opt_present("help") {
        println!("users 1.0.0");
        println!("");
        println!("Usage:");
        println!("  {} [OPTION]... [FILE]", args[0]);
        println!("");
        println!("{}", getopts::usage("Output who is currently logged in according to FILE.", &opts));
        return 0;
    }

    if matches.opt_present("version") {
        println!("users 1.0.0");
        return 0;
    }

    let filename = if matches.free.len() > 0 {
        matches.free[0].as_ref()
    } else {
        DEFAULT_FILE
    };

    exec(filename);

    0
}

fn exec(filename: &str) {
    unsafe {
        utmpxname(CString::new(filename).unwrap().as_ptr());
    }

    let mut users = vec!();

    unsafe {
        setutxent();

        loop {
            let line = getutxent();

            if line == ptr::null() {
                break;
            }

            if (*line).ut_type == USER_PROCESS {
                let user = String::from_utf8_lossy(CStr::from_ptr(mem::transmute(&(*line).ut_user)).to_bytes()).to_string();
                users.push(user);
            }
        }

        endutxent();
    }

    if users.len() > 0 {
        users.sort();
        println!("{}", users.connect(" "));
    }
}
<|endoftext|>