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

use voodoo::color::ColorValue;
use voodoo::window::{Point, TermCell, Window};

use level::{CellContents, Level};
use program::{ProgramRef, Team};

pub struct MapView {
    window: Window,
    highlight: Option<ProgramRef>,
    highlight_range: Option<usize>,
    overlay: Vec<(Point, TermCell)>,
    named_overlay: HashMap<String, (Point, TermCell)>,
    help: Option<String>,
}

impl MapView {
    pub fn new(mut window: Window) -> MapView {
        window.border();
        MapView {
            window: window,
            highlight: None,
            highlight_range: None,
            overlay: Vec::new(),
            named_overlay: HashMap::new(),
            help: None,
        }
    }

    pub fn reset(&mut self) {
        self.overlay.clear();
        self.named_overlay.clear();
        self.clear_help();
        self.clear_highlight();
    }

    pub fn get_overlay(&mut self) -> &mut HashMap<String, (Point, TermCell)> {
        &mut self.named_overlay
    }

    pub fn from_global_frame(&self, p: Point) -> Option<Point> {
        self.window.position.from_global_frame(p)
    }

    pub fn display(&mut self, level: &Level) {
        for (y, line) in level.layout.iter().enumerate() {
            let y = y + 2;
            for (x, tile) in line.iter().enumerate() {
                let x = x + 2;
                self.window.put_at(Point::new(x as u16, y as u16), match Level::convert(*tile) {
                    Some(c) => c,
                    None => ' '.into(),
                });
            }
        }

        for program in level.programs.iter() {
            let color = match program.borrow().team {
                Team::Player => ColorValue::Green,
                Team::Enemy => ColorValue::Red,
            };
            for (p, tc) in program.borrow().display_color(color) {
                self.window.put_at(Point::new(p.x + 1, p.y + 1), tc);
            }
        }

        if let Some(ref program) = self.highlight {
            for (p, tc) in program.borrow().display_color(ColorValue::Blue) {
                self.window.put_at(Point::new(p.x + 1, p.y + 1), tc);
            }
        }

        for &(p, c) in self.overlay.iter() {
            self.window.put_at(Point::new(p.x + 1, p.y + 1), c);
        }

        for &(p, c) in self.named_overlay.values() {
            self.window.put_at(Point::new(p.x + 1, p.y + 1), c);
        }

        // TODO:
        self.window.print_at(Point::new(2, 23), "                                                         ");
        if let Some(ref help) = self.help {
            self.window.print_at(Point::new(2, 23), help);
        }
    }

    pub fn refresh(&mut self, compositor: &mut ::voodoo::compositor::Compositor) {
        self.window.refresh(compositor);
    }

    pub fn highlight(&mut self, program: ProgramRef, level: &Level) {
        self.highlight = Some(program.clone());
        self.update_highlight(level);
    }

    pub fn highlight_range(&mut self, range: usize, level: &Level) {
        self.highlight_range = Some(range);
        self.update_highlight(level);
    }

    pub fn clear_range(&mut self) {
        self.highlight_range = None;
    }

    pub fn update_highlight(&mut self, level: &Level) {
        if let Some(ref program) = self.highlight {
            self.overlay.clear();
            let position = { program.borrow().position };
            let Point { x, y } = position;

            if let Some(range) = self.highlight_range {
                let range = range as isize;

                // TODO: change this to use refactored function
                for dx in -range..range + 1 {
                    for dy in -range..range + 1 {
                        if dx == 0 && dy == 0 {
                            continue;
                        }
                        if dx.abs() + dy.abs() <= range {
                            let p = Point::new((x as isize + dx) as u16, (y as isize + dy) as u16);

                            // Guard at map edges
                            if p.x <= 0 || p.y <= 0 {
                                continue;
                            }

                            if let Some(tc) = match level.contents_of(p) {
                                CellContents::Empty => Some('·'.into()),
                                CellContents::Unpassable | CellContents::Uplink => None,
                                CellContents::Program(p) => {
                                    if p.borrow().position == position {
                                        None
                                    }
                                    else {
                                        Some('X'.into())
                                    }
                                },
                            } {
                                let mut tc: TermCell = tc;
                                tc.bg = Some(ColorValue::Magenta);
                                self.overlay.push((p, tc));
                            }
                        }
                    }
                }
            }
            else {
                if !program.borrow().can_move() {
                    return;
                }

                let east = Point::new(x + 1, y);
                if level.passable(east) {
                    self.overlay.push((east, '→'.into()));
                }
                let west = Point::new(x - 1, y);
                if level.passable(west) {
                    self.overlay.push((west, '←'.into()));
                }
                let north = Point::new(x, y - 1);
                if level.passable(north) {
                    self.overlay.push((north, '↑'.into()));
                }
                let south = Point::new(x, y + 1);
                if level.passable(south) {
                    self.overlay.push((south, '↓'.into()));
                }
            }
        }
    }

    pub fn clear_highlight(&mut self) {
        self.highlight = None;
        self.overlay.clear();
    }

    pub fn get_highlight(&self) -> Option<ProgramRef> {
        self.highlight.as_ref().map(Clone::clone)
    }

    pub fn translate_click(&self, click: Point) -> Option<Point> {
        for &(point, _) in self.overlay.iter() {
            if click == point {
                return Some(point);
            }
        }
        None
    }

    pub fn set_help<S: Into<String>>(&mut self, s: S) {
        self.help = Some(s.into());
    }

    pub fn clear_help(&mut self) {
        self.help = None;
    }
}
<commit_msg>fix: don't allow friendly fire<commit_after>use std::collections::HashMap;

use voodoo::color::ColorValue;
use voodoo::window::{Point, TermCell, Window};

use level::{CellContents, Level};
use program::{ProgramRef, Team};

pub struct MapView {
    window: Window,
    highlight: Option<ProgramRef>,
    highlight_range: Option<usize>,
    overlay: Vec<(Point, TermCell)>,
    named_overlay: HashMap<String, (Point, TermCell)>,
    help: Option<String>,
}

impl MapView {
    pub fn new(mut window: Window) -> MapView {
        window.border();
        MapView {
            window: window,
            highlight: None,
            highlight_range: None,
            overlay: Vec::new(),
            named_overlay: HashMap::new(),
            help: None,
        }
    }

    pub fn reset(&mut self) {
        self.overlay.clear();
        self.named_overlay.clear();
        self.clear_help();
        self.clear_highlight();
    }

    pub fn get_overlay(&mut self) -> &mut HashMap<String, (Point, TermCell)> {
        &mut self.named_overlay
    }

    pub fn from_global_frame(&self, p: Point) -> Option<Point> {
        self.window.position.from_global_frame(p)
    }

    pub fn display(&mut self, level: &Level) {
        for (y, line) in level.layout.iter().enumerate() {
            let y = y + 2;
            for (x, tile) in line.iter().enumerate() {
                let x = x + 2;
                self.window.put_at(Point::new(x as u16, y as u16), match Level::convert(*tile) {
                    Some(c) => c,
                    None => ' '.into(),
                });
            }
        }

        for program in level.programs.iter() {
            let color = match program.borrow().team {
                Team::Player => ColorValue::Green,
                Team::Enemy => ColorValue::Red,
            };
            for (p, tc) in program.borrow().display_color(color) {
                self.window.put_at(Point::new(p.x + 1, p.y + 1), tc);
            }
        }

        if let Some(ref program) = self.highlight {
            for (p, tc) in program.borrow().display_color(ColorValue::Blue) {
                self.window.put_at(Point::new(p.x + 1, p.y + 1), tc);
            }
        }

        for &(p, c) in self.overlay.iter() {
            self.window.put_at(Point::new(p.x + 1, p.y + 1), c);
        }

        for &(p, c) in self.named_overlay.values() {
            self.window.put_at(Point::new(p.x + 1, p.y + 1), c);
        }

        // TODO:
        self.window.print_at(Point::new(2, 23), "                                                         ");
        if let Some(ref help) = self.help {
            self.window.print_at(Point::new(2, 23), help);
        }
    }

    pub fn refresh(&mut self, compositor: &mut ::voodoo::compositor::Compositor) {
        self.window.refresh(compositor);
    }

    pub fn highlight(&mut self, program: ProgramRef, level: &Level) {
        self.highlight = Some(program.clone());
        self.update_highlight(level);
    }

    pub fn highlight_range(&mut self, range: usize, level: &Level) {
        self.highlight_range = Some(range);
        self.update_highlight(level);
    }

    pub fn clear_range(&mut self) {
        self.highlight_range = None;
    }

    pub fn update_highlight(&mut self, level: &Level) {
        if let Some(ref program) = self.highlight {
            self.overlay.clear();
            let position = { program.borrow().position };
            let Point { x, y } = position;

            if let Some(range) = self.highlight_range {
                let range = range as isize;

                // TODO: change this to use refactored function
                for dx in -range..range + 1 {
                    for dy in -range..range + 1 {
                        if dx == 0 && dy == 0 {
                            continue;
                        }
                        if dx.abs() + dy.abs() <= range {
                            let p = Point::new((x as isize + dx) as u16, (y as isize + dy) as u16);

                            // Guard at map edges
                            if p.x <= 0 || p.y <= 0 {
                                continue;
                            }

                            if let Some(tc) = match level.contents_of(p) {
                                CellContents::Empty => Some('·'.into()),
                                CellContents::Unpassable | CellContents::Uplink => None,
                                CellContents::Program(p) => {
                                    if p.borrow().position != position && p.borrow().team == Team::Enemy {
                                        Some('X'.into())
                                    }
                                    else {
                                        None
                                    }
                                },
                            } {
                                let mut tc: TermCell = tc;
                                tc.bg = Some(ColorValue::Magenta);
                                self.overlay.push((p, tc));
                            }
                        }
                    }
                }
            }
            else {
                if !program.borrow().can_move() {
                    return;
                }

                let east = Point::new(x + 1, y);
                if level.passable(east) {
                    self.overlay.push((east, '→'.into()));
                }
                let west = Point::new(x - 1, y);
                if level.passable(west) {
                    self.overlay.push((west, '←'.into()));
                }
                let north = Point::new(x, y - 1);
                if level.passable(north) {
                    self.overlay.push((north, '↑'.into()));
                }
                let south = Point::new(x, y + 1);
                if level.passable(south) {
                    self.overlay.push((south, '↓'.into()));
                }
            }
        }
    }

    pub fn clear_highlight(&mut self) {
        self.highlight = None;
        self.overlay.clear();
    }

    pub fn get_highlight(&self) -> Option<ProgramRef> {
        self.highlight.as_ref().map(Clone::clone)
    }

    pub fn translate_click(&self, click: Point) -> Option<Point> {
        for &(point, _) in self.overlay.iter() {
            if click == point {
                return Some(point);
            }
        }
        None
    }

    pub fn set_help<S: Into<String>>(&mut self, s: S) {
        self.help = Some(s.into());
    }

    pub fn clear_help(&mut self) {
        self.help = None;
    }
}
<|endoftext|>


<commit_before>//! This module contains the code representing Mastodon nodes and API Clients
//!
use Client;
use api::oauth::{CreateApp, OAuthApp};
use errors::*;
use hyper::header::Bearer;
use serde_json;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use url::Url;

/// `Mastodon` is used to specify the base url of a Mastodon node.
/// Only HTTPS connections are supported.
#[derive(Debug)]
pub struct Mastodon(pub Url);

/// Methods to interact with a Mastodon instance.
pub trait NodeInstance {
    /// Create a new Mastodon instance.
    fn new(url: &str) -> Result<Mastodon>;
    /// Returns the base `Url` of the Mastodon instance.
    fn url(&self) -> Result<Url>;
    /// Returns a Client for the API of the Mastodon instance.
    fn client(&self, token: &str) -> Result<Client>;
    /// Register a 3rd-party App with the Mastodon instance.
    fn register_app(&self, app: CreateApp) -> Result<OAuthApp>;
}

impl NodeInstance for Mastodon {
    fn new(url: &str) -> Result<Mastodon> {
        Ok(Mastodon(Url::parse(url).chain_err(|| "Invalid URL")?))
    }
    fn url(&self) -> Result<Url> {
        Ok(self.0.clone())
    }
    fn client(&self, token: &str) -> Result<Client> {
        Ok(Client {
            url_base: self.url().chain_err(|| "Could not set the base URL")?,
            token: Bearer::from_str(token).chain_err(|| "Could parse Bearer Token")?
        })
    }
    fn register_app(&self, app: CreateApp) -> Result<OAuthApp> {
        let out = Arc::new(Mutex::new(Vec::new()));
        app
            .register(&self.endpoint_url_string("/api/v1/apps"), out.clone())
            .chain_err(|| "Could not register App.")?;
        let out = out.lock().unwrap();
        if out.is_empty() { bail!("Invalid result. Empty") }
        serde_json::from_slice(&out).chain_err(|| "Unexpected JSON error.")
    }
}

pub trait ApiHandler {
    fn endpoint_url(&self, path: &str) -> Result<Url>;
    fn endpoint_url_string(&self, path: &str) -> String;
}

impl ApiHandler for Mastodon {
    fn endpoint_url(&self, path: &str) -> Result<Url> {
        self.0.clone().join(path).chain_err(|| "invalid endpoint URL")
    }
    fn endpoint_url_string(&self, path: &str) -> String {
        self.endpoint_url(path).chain_err(|| "invalid endpoint URL").unwrap().into_string()
    }
}
<commit_msg>oops, fix error message<commit_after>//! This module contains the code representing Mastodon nodes and API Clients
//!
use Client;
use api::oauth::{CreateApp, OAuthApp};
use errors::*;
use hyper::header::Bearer;
use serde_json;
use std::str::FromStr;
use std::sync::{Arc, Mutex};
use url::Url;

/// `Mastodon` is used to specify the base url of a Mastodon node.
/// Only HTTPS connections are supported.
#[derive(Debug)]
pub struct Mastodon(pub Url);

/// Methods to interact with a Mastodon instance.
pub trait NodeInstance {
    /// Create a new Mastodon instance.
    fn new(url: &str) -> Result<Mastodon>;
    /// Returns the base `Url` of the Mastodon instance.
    fn url(&self) -> Result<Url>;
    /// Returns a Client for the API of the Mastodon instance.
    fn client(&self, token: &str) -> Result<Client>;
    /// Register a 3rd-party App with the Mastodon instance.
    fn register_app(&self, app: CreateApp) -> Result<OAuthApp>;
}

impl NodeInstance for Mastodon {
    fn new(url: &str) -> Result<Mastodon> {
        Ok(Mastodon(Url::parse(url).chain_err(|| "Invalid URL")?))
    }
    fn url(&self) -> Result<Url> {
        Ok(self.0.clone())
    }
    fn client(&self, token: &str) -> Result<Client> {
        Ok(Client {
            url_base: self.url().chain_err(|| "Could not set the base URL")?,
            token: Bearer::from_str(token).chain_err(|| "Could not parse Bearer Token")?
        })
    }
    fn register_app(&self, app: CreateApp) -> Result<OAuthApp> {
        let out = Arc::new(Mutex::new(Vec::new()));
        app
            .register(&self.endpoint_url_string("/api/v1/apps"), out.clone())
            .chain_err(|| "Could not register App.")?;
        let out = out.lock().unwrap();
        if out.is_empty() { bail!("Invalid result. Empty") }
        serde_json::from_slice(&out).chain_err(|| "Unexpected JSON error.")
    }
}

pub trait ApiHandler {
    fn endpoint_url(&self, path: &str) -> Result<Url>;
    fn endpoint_url_string(&self, path: &str) -> String;
}

impl ApiHandler for Mastodon {
    fn endpoint_url(&self, path: &str) -> Result<Url> {
        self.0.clone().join(path).chain_err(|| "invalid endpoint URL")
    }
    fn endpoint_url_string(&self, path: &str) -> String {
        self.endpoint_url(path).chain_err(|| "invalid endpoint URL").unwrap().into_string()
    }
}
<|endoftext|>


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

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

#[cfg(unix)]
extern crate libc;
extern crate walker;

#[macro_use]
extern crate uucore;

use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::Path;
use walker::Walker;
#[cfg(not(windows))]
use uucore::mode;

const NAME: &'static str = "chmod";
static SUMMARY: &'static str = "Change the mode of each FILE to MODE.
 With --reference, change the mode of each FILE to that of RFILE.";
static LONG_HELP: &'static str = "
 Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.
";

pub fn uumain(mut args: Vec<String>) -> i32 {
    let syntax = format!(
        "[OPTION]... MODE[,MODE]... FILE...
 {0} [OPTION]... OCTAL-MODE FILE...
 {0} [OPTION]... --reference=RFILE FILE...",
        NAME
    );
    let mut opts = new_coreopts!(&syntax, SUMMARY, LONG_HELP);
    opts.optflag("c", "changes", "like verbose but report only when a change is made \
                                  (unimplemented)")
        // TODO: support --silent (can be done using clap)
        .optflag("f", "quiet", "suppress most error messages (unimplemented)")
        .optflag("v", "verbose", "output a diagnostic for every file processed (unimplemented)")
        .optflag("", "no-preserve-root", "do not treat '/' specially (the default)")
        .optflag("", "preserve-root", "fail to operate recursively on '/'")
        .optopt("", "reference", "use RFILE's mode instead of MODE values", "RFILE")
        .optflag("R", "recursive", "change files and directories recursively");

    // sanitize input for - at beginning (e.g. chmod -x testfile). Remove
    // the option and save it for later, after parsing is finished.
    let negative_option = sanitize_input(&mut args);

    let mut matches = opts.parse(args);
    if matches.free.is_empty() {
        show_error!("missing an argument");
        show_error!("for help, try '{} --help'", NAME);
        return 1;
    } else {
        let changes = matches.opt_present("changes");
        let quiet = matches.opt_present("quiet");
        let verbose = matches.opt_present("verbose");
        let preserve_root = matches.opt_present("preserve-root");
        let recursive = matches.opt_present("recursive");
        let fmode = matches
            .opt_str("reference")
            .and_then(|ref fref| match fs::metadata(fref) {
                Ok(meta) => Some(meta.mode()),
                Err(err) => crash!(1, "cannot stat attribues of '{}': {}", fref, err),
            });
        let cmode = if fmode.is_none() {
            // If there was a negative option, now it's a good time to
            // use it.
            if negative_option.is_some() {
                negative_option
            } else {
                Some(matches.free.remove(0))
            }
        } else {
            None
        };
        let chmoder = Chmoder {
            changes: changes,
            quiet: quiet,
            verbose: verbose,
            preserve_root: preserve_root,
            recursive: recursive,
            fmode: fmode,
            cmode: cmode,
        };
        match chmoder.chmod(matches.free) {
            Ok(()) => {}
            Err(e) => return e,
        }
    }

    0
}

fn sanitize_input(args: &mut Vec<String>) -> Option<String> {
    for i in 0..args.len() {
        let first = args[i].chars().nth(0).unwrap();
        if first != '-' {
            continue;
        }
        if let Some(second) = args[i].chars().nth(1) {
            match second {
                'r' | 'w' | 'x' | 'X' | 's' | 't' | 'u' | 'g' | 'o' | '0'...'7' => {
                    return Some(args.remove(i));
                }
                _ => {}
            }
        }
    }
    None
}

struct Chmoder {
    changes: bool,
    quiet: bool,
    verbose: bool,
    preserve_root: bool,
    recursive: bool,
    fmode: Option<u32>,
    cmode: Option<String>,
}

impl Chmoder {
    fn chmod(&self, files: Vec<String>) -> Result<(), i32> {
        let mut r = Ok(());

        for filename in &files {
            let filename = &filename[..];
            let file = Path::new(filename);
            if file.exists() {
                if file.is_dir() {
                    if !self.preserve_root || filename != "/" {
                        if self.recursive {
                            let walk_dir = match Walker::new(&file) {
                                Ok(m) => m,
                                Err(f) => {
                                    crash!(1, "{}", f.to_string());
                                }
                            };
                            // XXX: here (and elsewhere) we see that this impl will have issues
                            // with non-UTF-8 filenames. Using OsString won't fix this because
                            // on Windows OsStrings cannot be built out of non-UTF-8 chars. One
                            // possible fix is to use CStrings rather than Strings in the args
                            // to chmod() and chmod_file().
                            r = self.chmod(
                                walk_dir
                                    .filter_map(|x| match x {
                                        Ok(o) => match o.path().into_os_string().to_str() {
                                            Some(s) => Some(s.to_owned()),
                                            None => None,
                                        },
                                        Err(_) => None,
                                    })
                                    .collect(),
                            ).and(r);
                            r = self.chmod_file(&file, filename).and(r);
                        }
                    } else {
                        show_error!("could not change permissions of directory '{}'", filename);
                        r = Err(1);
                    }
                } else {
                    r = self.chmod_file(&file, filename).and(r);
                }
            } else {
                show_error!("no such file or directory '{}'", filename);
                r = Err(1);
            }
        }

        r
    }

    #[cfg(windows)]
    fn chmod_file(&self, file: &Path, name: &str) -> Result<(), i32> {
        // chmod is useless on Windows
        // it doesn't set any permissions at all
        // instead it just sets the readonly attribute on the file
        Err(0)
    }
    #[cfg(any(unix, target_os = "redox"))]
    fn chmod_file(&self, file: &Path, name: &str) -> Result<(), i32> {
        let mut fperm = match fs::metadata(name) {
            Ok(meta) => meta.mode() & 0o7777,
            Err(err) => {
                if !self.quiet {
                    show_error!("{}", err);
                }
                return Err(1);
            }
        };
        match self.fmode {
            Some(mode) => try!(self.change_file(fperm, mode, file, name)),
            None => {
                let cmode_unwrapped = self.cmode.clone().unwrap();
                for mode in cmode_unwrapped.split(',') {
                    // cmode is guaranteed to be Some in this case
                    let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
                    let result = if mode.contains(arr) {
                        mode::parse_numeric(fperm, mode)
                    } else {
                        mode::parse_symbolic(fperm, mode, file.is_dir())
                    };
                    match result {
                        Ok(mode) => {
                            try!(self.change_file(fperm, mode, file, name));
                            fperm = mode;
                        }
                        Err(f) => {
                            if !self.quiet {
                                show_error!("{}", f);
                            }
                            return Err(1);
                        }
                    }
                }
            }
        }

        Ok(())
    }

    fn change_file(&self, fperm: u32, mode: u32, file: &Path, path: &str) -> Result<(), i32> {
        if fperm == mode {
            if self.verbose && !self.changes {
                show_info!("mode of '{}' retained as {:o}", file.display(), fperm);
            }
            Ok(())
        } else if let Err(err) =
            fs::set_permissions(Path::new(path), fs::Permissions::from_mode(mode))
        {
            if !self.quiet {
                show_error!("{}", err);
            }
            if self.verbose {
                show_info!(
                    "failed to change mode of file '{}' from {:o} to {:o}",
                    file.display(),
                    fperm,
                    mode
                );
            }
            Err(1)
        } else {
            if self.verbose || self.changes {
                show_info!(
                    "mode of '{}' changed from {:o} to {:o}",
                    file.display(),
                    fperm,
                    mode
                );
            }
            Ok(())
        }
    }
}
<commit_msg>chmod: Remove '(unimplemented)' from the opt help.<commit_after>#![crate_name = "uu_chmod"]

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

#[cfg(unix)]
extern crate libc;
extern crate walker;

#[macro_use]
extern crate uucore;

use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::Path;
use walker::Walker;
#[cfg(not(windows))]
use uucore::mode;

const NAME: &'static str = "chmod";
static SUMMARY: &'static str = "Change the mode of each FILE to MODE.
 With --reference, change the mode of each FILE to that of RFILE.";
static LONG_HELP: &'static str = "
 Each MODE is of the form '[ugoa]*([-+=]([rwxXst]*|[ugo]))+|[-+=]?[0-7]+'.
";

pub fn uumain(mut args: Vec<String>) -> i32 {
    let syntax = format!(
        "[OPTION]... MODE[,MODE]... FILE...
 {0} [OPTION]... OCTAL-MODE FILE...
 {0} [OPTION]... --reference=RFILE FILE...",
        NAME
    );
    let mut opts = new_coreopts!(&syntax, SUMMARY, LONG_HELP);
    opts.optflag("c", "changes", "like verbose but report only when a change is made")
        // TODO: support --silent (can be done using clap)
        .optflag("f", "quiet", "suppress most error messages")
        .optflag("v", "verbose", "output a diagnostic for every file processed")
        .optflag("", "no-preserve-root", "do not treat '/' specially (the default)")
        .optflag("", "preserve-root", "fail to operate recursively on '/'")
        .optopt("", "reference", "use RFILE's mode instead of MODE values", "RFILE")
        .optflag("R", "recursive", "change files and directories recursively");

    // sanitize input for - at beginning (e.g. chmod -x testfile). Remove
    // the option and save it for later, after parsing is finished.
    let negative_option = sanitize_input(&mut args);

    let mut matches = opts.parse(args);
    if matches.free.is_empty() {
        show_error!("missing an argument");
        show_error!("for help, try '{} --help'", NAME);
        return 1;
    } else {
        let changes = matches.opt_present("changes");
        let quiet = matches.opt_present("quiet");
        let verbose = matches.opt_present("verbose");
        let preserve_root = matches.opt_present("preserve-root");
        let recursive = matches.opt_present("recursive");
        let fmode = matches
            .opt_str("reference")
            .and_then(|ref fref| match fs::metadata(fref) {
                Ok(meta) => Some(meta.mode()),
                Err(err) => crash!(1, "cannot stat attribues of '{}': {}", fref, err),
            });
        let cmode = if fmode.is_none() {
            // If there was a negative option, now it's a good time to
            // use it.
            if negative_option.is_some() {
                negative_option
            } else {
                Some(matches.free.remove(0))
            }
        } else {
            None
        };
        let chmoder = Chmoder {
            changes: changes,
            quiet: quiet,
            verbose: verbose,
            preserve_root: preserve_root,
            recursive: recursive,
            fmode: fmode,
            cmode: cmode,
        };
        match chmoder.chmod(matches.free) {
            Ok(()) => {}
            Err(e) => return e,
        }
    }

    0
}

fn sanitize_input(args: &mut Vec<String>) -> Option<String> {
    for i in 0..args.len() {
        let first = args[i].chars().nth(0).unwrap();
        if first != '-' {
            continue;
        }
        if let Some(second) = args[i].chars().nth(1) {
            match second {
                'r' | 'w' | 'x' | 'X' | 's' | 't' | 'u' | 'g' | 'o' | '0'...'7' => {
                    return Some(args.remove(i));
                }
                _ => {}
            }
        }
    }
    None
}

struct Chmoder {
    changes: bool,
    quiet: bool,
    verbose: bool,
    preserve_root: bool,
    recursive: bool,
    fmode: Option<u32>,
    cmode: Option<String>,
}

impl Chmoder {
    fn chmod(&self, files: Vec<String>) -> Result<(), i32> {
        let mut r = Ok(());

        for filename in &files {
            let filename = &filename[..];
            let file = Path::new(filename);
            if file.exists() {
                if file.is_dir() {
                    if !self.preserve_root || filename != "/" {
                        if self.recursive {
                            let walk_dir = match Walker::new(&file) {
                                Ok(m) => m,
                                Err(f) => {
                                    crash!(1, "{}", f.to_string());
                                }
                            };
                            // XXX: here (and elsewhere) we see that this impl will have issues
                            // with non-UTF-8 filenames. Using OsString won't fix this because
                            // on Windows OsStrings cannot be built out of non-UTF-8 chars. One
                            // possible fix is to use CStrings rather than Strings in the args
                            // to chmod() and chmod_file().
                            r = self.chmod(
                                walk_dir
                                    .filter_map(|x| match x {
                                        Ok(o) => match o.path().into_os_string().to_str() {
                                            Some(s) => Some(s.to_owned()),
                                            None => None,
                                        },
                                        Err(_) => None,
                                    })
                                    .collect(),
                            ).and(r);
                            r = self.chmod_file(&file, filename).and(r);
                        }
                    } else {
                        show_error!("could not change permissions of directory '{}'", filename);
                        r = Err(1);
                    }
                } else {
                    r = self.chmod_file(&file, filename).and(r);
                }
            } else {
                show_error!("no such file or directory '{}'", filename);
                r = Err(1);
            }
        }

        r
    }

    #[cfg(windows)]
    fn chmod_file(&self, file: &Path, name: &str) -> Result<(), i32> {
        // chmod is useless on Windows
        // it doesn't set any permissions at all
        // instead it just sets the readonly attribute on the file
        Err(0)
    }
    #[cfg(any(unix, target_os = "redox"))]
    fn chmod_file(&self, file: &Path, name: &str) -> Result<(), i32> {
        let mut fperm = match fs::metadata(name) {
            Ok(meta) => meta.mode() & 0o7777,
            Err(err) => {
                if !self.quiet {
                    show_error!("{}", err);
                }
                return Err(1);
            }
        };
        match self.fmode {
            Some(mode) => try!(self.change_file(fperm, mode, file, name)),
            None => {
                let cmode_unwrapped = self.cmode.clone().unwrap();
                for mode in cmode_unwrapped.split(',') {
                    // cmode is guaranteed to be Some in this case
                    let arr: &[char] = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
                    let result = if mode.contains(arr) {
                        mode::parse_numeric(fperm, mode)
                    } else {
                        mode::parse_symbolic(fperm, mode, file.is_dir())
                    };
                    match result {
                        Ok(mode) => {
                            try!(self.change_file(fperm, mode, file, name));
                            fperm = mode;
                        }
                        Err(f) => {
                            if !self.quiet {
                                show_error!("{}", f);
                            }
                            return Err(1);
                        }
                    }
                }
            }
        }

        Ok(())
    }

    fn change_file(&self, fperm: u32, mode: u32, file: &Path, path: &str) -> Result<(), i32> {
        if fperm == mode {
            if self.verbose && !self.changes {
                show_info!("mode of '{}' retained as {:o}", file.display(), fperm);
            }
            Ok(())
        } else if let Err(err) =
            fs::set_permissions(Path::new(path), fs::Permissions::from_mode(mode))
        {
            if !self.quiet {
                show_error!("{}", err);
            }
            if self.verbose {
                show_info!(
                    "failed to change mode of file '{}' from {:o} to {:o}",
                    file.display(),
                    fperm,
                    mode
                );
            }
            Err(1)
        } else {
            if self.verbose || self.changes {
                show_info!(
                    "mode of '{}' changed from {:o} to {:o}",
                    file.display(),
                    fperm,
                    mode
                );
            }
            Ok(())
        }
    }
}
<|endoftext|>


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

/*===============================================================================================*/
/*------RGBA STRUCT------------------------------------------------------------------------------*/
/*===============================================================================================*/

/// Stores a RGBA colour value.
pub struct RGBA {

    // Public
    /// Red channel.
    pub r: f32,
    /// Green channel.
    pub g: f32,
    /// Blue channel.
    pub b: f32,
    /// Alpha channel.
    pub a: f32,
}
<commit_msg>Added derives, new, and conversion functions<commit_after>/*===============================================================================================*/
// Copyright 2016 Kyle Finlay
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*===============================================================================================*/

// Module imports
use std::convert::From;

/*===============================================================================================*/
/*------RGBA STRUCT------------------------------------------------------------------------------*/
/*===============================================================================================*/

/// Stores a RGBA colour value.
#[cfg_attr (feature = "serde_serialize", derive (Deserialize, Serialize))]
#[derive (Copy, Clone, Debug, PartialEq)]
pub struct RGBA {

    // Public
    /// Red channel.
    pub r: f32,
    /// Green channel.
    pub g: f32,
    /// Blue channel.
    pub b: f32,
    /// Alpha channel.
    pub a: f32,
}

/*===============================================================================================*/
/*------RGBA TRAIT IMPLEMENTATIONS---------------------------------------------------------------*/
/*===============================================================================================*/

impl Default for RGBA {

    fn default () -> Self {
        RGBA::from (1.0)
    }
}

/*-----------------------------------------------------------------------------------------------*/

impl From<f32> for RGBA {

    fn from (value: f32) -> Self {
        RGBA::new (value, value, value, value)
    }
}

/*===============================================================================================*/
/*------RGBA PUBLIC METHODS----------------------------------------------------------------------*/
/*===============================================================================================*/

impl RGBA {

    /// Returns a new `RGBA` instance.
    ///
    /// # Examples
    /// ```
    /// # use ion_math::colour::RGBA;
    /// let colour = RGBA::new (0.0, 1.0, 0.5, 1.0);
    /// ```
    pub fn new (r: f32, g: f32, b: f32, a: f32) -> Self {
        RGBA {r: r, g: g, b: b, a: a}
    }
}
<|endoftext|>


<commit_before>extern {
    static dc_qlookup_Q3: [i16; 256];
    static ac_qlookup_Q3: [i16; 256];
}

pub fn dc_q(qindex: usize) -> i16 {
    unsafe {
        dc_qlookup_Q3[qindex]
    }
}

pub fn ac_q(qindex: usize) -> i16 {
    unsafe {
        ac_qlookup_Q3[qindex]
    }
}

pub fn quantize_in_place(qindex: usize, coeffs: &mut [i32]) {
    coeffs[0] /= dc_q(qindex) as i32;
    for c in coeffs[1..].iter_mut() {
        *c /= ac_q(qindex) as i32;
    }
    // workaround for bug in token coder
    *coeffs.last_mut().unwrap() = 0;
}

pub fn dequantize(qindex:usize, coeffs: &[i32], rcoeffs: &mut [i32]) {
    rcoeffs[0] = coeffs[0] * dc_q(qindex) as i32;
    for i in 1..coeffs.len() {
        rcoeffs[i] = coeffs[i] * ac_q(qindex) as i32;
    }
}
<commit_msg>Fetch the quantizer only once<commit_after>extern {
    static dc_qlookup_Q3: [i16; 256];
    static ac_qlookup_Q3: [i16; 256];
}

pub fn dc_q(qindex: usize) -> i16 {
    unsafe {
        dc_qlookup_Q3[qindex]
    }
}

pub fn ac_q(qindex: usize) -> i16 {
    unsafe {
        ac_qlookup_Q3[qindex]
    }
}

pub fn quantize_in_place(qindex: usize, coeffs: &mut [i32]) {
    coeffs[0] /= dc_q(qindex) as i32;
    let ac_quant = ac_q(qindex) as i32;

    for c in coeffs[1..].iter_mut() {
        *c /= ac_quant;
    }
    // workaround for bug in token coder
    *coeffs.last_mut().unwrap() = 0;
}

pub fn dequantize(qindex:usize, coeffs: &[i32], rcoeffs: &mut [i32]) {
    rcoeffs[0] = coeffs[0] * dc_q(qindex) as i32;
    let ac_quant = ac_q(qindex) as i32;

    for i in 1..coeffs.len() {
        rcoeffs[i] = coeffs[i] * ac_quant;
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate orbtk;

use orbtk::{Action, Button, Menu, Point, Rect, TextBox, Window, WidgetPlace};
use orbtk::callback::Click;
use orbtk::place::Place;

use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::sync::Arc;

fn main(){
    let path_option = Arc::new(env::args().nth(1));

    let title = if let Some(ref path) = *path_option {
        format!("{} - Editor", path)
    } else {
        format!("Editor")
    };

    let window = Arc::new(Window::new(Rect::new(100, 100, 576, 420), &title));

    let text_box = TextBox::new()
        .position(0, 16)
        .size(576, 404)
        .place(&window);

    if let Some(ref path) = *path_option {
        match File::open(path) {
            Ok(mut file) => {
                let mut text = String::new();
                match file.read_to_string(&mut text) {
                    Ok(_) => text_box.text.set(text),
                    Err(err) => println!("Failed to read {}: {}", path, err)
                }
            },
            Err(err) => println!("Failed to open {}: {}", path, err)
        }
    }

    let mut menu = Menu::new("File").position(0, 0).size(32, 16);

    menu.add_action(Action::new("Open").on_click(|_action: &Action, _point: Point| {
        println!("Open");
    }));

    menu.add_separator();

    let save_path_option = path_option.clone();
    menu.add_action(Action::new("Save").on_click(move |_action: &Action, _point: Point| {
        println!("Save");
        if let Some(ref path) = *save_path_option {
            match File::create(path) {
                Ok(mut file) => {
                    let text = text_box.text.get();
                    match file.write(&mut text.as_bytes()) {
                        Ok(_) => match file.set_len(text.len() as u64) {
                            Ok(_) => println!("Successfully saved {}", path),
                            Err(err) => println!("Failed to truncate {}: {}", path, err)
                        },
                        Err(err) => println!("Failed to write {}: {}", path, err)
                    }
                },
                Err(err) => println!("Failed to open {}: {}", path, err)
            }
        } else {
            println!("Need to create file!");
        }
    }));

    let save_as_path_option = path_option.clone();
    menu.add_action(Action::new("Save As").on_click(move |_action: &Action, _point: Point| {
        println!("Save As");
        let window = Arc::new(Window::new(Rect::new(100, 100, 576, 32), "Save As"));

        let text_box = TextBox::new()
            .position(0, 0)
            .size(576, 16)
            .place(&window);

        if let Some(ref path) = *save_as_path_option {
            text_box.text.set(path.clone());
        }

        let window_close = window.clone();
        Button::new()
            .position(0, 16)
            .size(576, 16)
            .text("Save As")
            .on_click(move |_button: &Button, _point: Point| {
                println!("Save {}", text_box.text.get());
                window_close.close();
            })
            .place(&window);

        window.exec();
    }));

    menu.add_separator();

    let window_close = window.clone();
    menu.add_action(Action::new("Close").on_click(move |_action: &Action, _point: Point| {
        println!("Close");
        window_close.close();
    }));

    menu.place(&window);

    window.exec();
}
<commit_msg>Add cancel button<commit_after>#![deny(warnings)]

extern crate orbtk;

use orbtk::{Action, Button, Menu, Point, Rect, TextBox, Window, WidgetPlace};
use orbtk::callback::Click;
use orbtk::place::Place;

use std::env;
use std::fs::File;
use std::io::{Read, Write};
use std::sync::Arc;

fn main(){
    let path_option = Arc::new(env::args().nth(1));

    let title = if let Some(ref path) = *path_option {
        format!("{} - Editor", path)
    } else {
        format!("Editor")
    };

    let window = Arc::new(Window::new(Rect::new(100, 100, 576, 420), &title));

    let text_box = TextBox::new()
        .position(0, 16)
        .size(576, 404)
        .place(&window);

    if let Some(ref path) = *path_option {
        match File::open(path) {
            Ok(mut file) => {
                let mut text = String::new();
                match file.read_to_string(&mut text) {
                    Ok(_) => text_box.text.set(text),
                    Err(err) => println!("Failed to read {}: {}", path, err)
                }
            },
            Err(err) => println!("Failed to open {}: {}", path, err)
        }
    }

    let mut menu = Menu::new("File").position(0, 0).size(32, 16);

    menu.add_action(Action::new("Open").on_click(|_action: &Action, _point: Point| {
        println!("Open");
    }));

    menu.add_separator();

    let save_path_option = path_option.clone();
    menu.add_action(Action::new("Save").on_click(move |_action: &Action, _point: Point| {
        println!("Save");
        if let Some(ref path) = *save_path_option {
            match File::create(path) {
                Ok(mut file) => {
                    let text = text_box.text.get();
                    match file.write(&mut text.as_bytes()) {
                        Ok(_) => match file.set_len(text.len() as u64) {
                            Ok(_) => println!("Successfully saved {}", path),
                            Err(err) => println!("Failed to truncate {}: {}", path, err)
                        },
                        Err(err) => println!("Failed to write {}: {}", path, err)
                    }
                },
                Err(err) => println!("Failed to open {}: {}", path, err)
            }
        } else {
            println!("Need to create file!");
        }
    }));

    let save_as_path_option = path_option.clone();
    menu.add_action(Action::new("Save As").on_click(move |_action: &Action, _point: Point| {
        println!("Save As");
        let window = Arc::new(Window::new(Rect::new(100, 100, 576, 32), "Save As"));

        let text_box = TextBox::new()
            .position(0, 0)
            .size(576, 16)
            .place(&window);

        if let Some(ref path) = *save_as_path_option {
            text_box.text.set(path.clone());
        }

        let window_cancel = window.clone();
        Button::new()
            .position(0, 16)
            .size(576/2, 16)
            .text("Cancel")
            .on_click(move |_button: &Button, _point: Point| {
                window_cancel.close();
            })
            .place(&window);

        let window_save_as = window.clone();
        Button::new()
            .position(576/2, 16)
            .size(576/2, 16)
            .text("Save As")
            .on_click(move |_button: &Button, _point: Point| {
                println!("Save {}", text_box.text.get());
                window_save_as.close();
            })
            .place(&window);

        window.exec();
    }));

    menu.add_separator();

    let window_close = window.clone();
    menu.add_action(Action::new("Close").on_click(move |_action: &Action, _point: Point| {
        println!("Close");
        window_close.close();
    }));

    menu.place(&window);

    window.exec();
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use memory::PAddr;
use core::fmt;

// Distinguished section indices.
pub const SHN_UNDEF: u16        = 0;
pub const SHN_LORESERVE: u16    = 0xff00;
pub const SHN_LOPROC: u16       = 0xff00;
pub const SHN_HIPROC: u16       = 0xff1f;
pub const SHN_LOOS: u16         = 0xff20;
pub const SHN_HIOS: u16         = 0xff3f;
pub const SHN_ABS: u16          = 0xfff1;
pub const SHN_COMMON: u16       = 0xfff2;
pub const SHN_XINDEX: u16       = 0xffff;
pub const SHN_HIRESERVE: u16    = 0xffff;

pub const SHT_LOOS: u32   = 0x60000000;
pub const SHT_HIOS: u32   = 0x6fffffff;
pub const SHT_LOPROC: u32 = 0x70000000;
pub const SHT_HIPROC: u32 = 0x7fffffff;
pub const SHT_LOUSER: u32 = 0x80000000;
pub const SHT_HIUSER: u32 = 0xffffffff;

/// Represents an ELF section header
///
/// Refer to the [ELF standard](http://www.sco.com/developers/gabi/latest/ch4.sheader.html)
/// for more information.
#[derive(Clone, Copy, Debug)]
pub enum Header<'a> {
    Header32(&'a HeaderRepr<u32>)
  , Header64(&'a HeaderRepr<u64>)
}

#[derive(Debug)]
#[repr(C)]
pub struct HeaderRepr<Word> {
    /// This member specifies the name of the section.
    ///
    /// Its value is an index into the section header string table section,
    /// giving the location of a null-terminated string.
    name_offset: u32
  , /// This member categorizes the section's contents and semantics.
    ty: TypeRepr
  , flags: Flags
  , address: Word
  , offset: Word
  , length: Word
  , link: u32
  , info: u32
  , address_align: Word
  , entry_length: Word
}

trait AsHeader {
    fn as_header<'a>(&'a self) -> Header<'a>;
}

impl AsHeader for HeaderRepr<u32> {
    #[inline] fn as_header<'a>(&'a self) -> Header<'a> {
        Header::Header32(self)
    }
}

impl AsHeader for HeaderRepr<u64> {
    #[inline] fn as_header<'a>(&'a self) -> Header<'a> {
        Header::Header64(self)
    }
}

bitflags! {
    flags Flags: usize {
        // Flags (SectionHeader::flags)
        const SHF_WRITE            =        0x1
      , const SHF_ALLOC            =        0x2
      , const SHF_EXECINSTR        =        0x4
      , const SHF_MERGE            =       0x10
      , const SHF_STRINGS          =       0x20
      , const SHF_INFO_LINK        =       0x40
      , const SHF_LINK_ORDER       =       0x80
      , const SHF_OS_NONCONFORMING =      0x100
      , const SHF_GROUP            =      0x200
      , const SHF_TLS              =      0x400
      , const SHF_COMPRESSED       =      0x800
      , const SHF_MASKOS           = 0x0ff00000
      , const SHF_MASKPROC         = 0xf0000000
    }
}

impl fmt::LowerHex for Flags {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.bits.fmt(f)
    }
}

bitflags! {
    flags GroupFlags: u32 {
        const GRP_COMDAT	=        0x1
      , const GRP_MASKOS	= 0x0ff00000
      , const GRP_MASKPROC	= 0xf0000000
    }
}

macro_rules! get {
    ($s: expr, $name: ident) => {
        match *$s {
            Header::Header32(x) => x.$name
          , Header::Header64(x) => x.$name
        }
    }
}

macro_rules! impl_getters {
    ( pub $name: ident : $ty: ident, $( $rest: tt )* ) => {
        #[inline] pub fn $name(&self) -> $ty {
            match *self {
                Header::Header32(x) => x.$name as $ty
              , Header::Header64(x) => x.$name as $ty
            }
        }
        impl_getters!{ $( $rest )* }
    };
    ( $name: ident : $ty: ident,  $( $rest: tt )* ) => {
        #[inline] fn $name(&self) -> $ty {
            match *self {
                Header::Header32(x) => x.$name as $ty
              , Header::Header64(x) => x.$name as $ty
            }
        }
        impl_getters!{ $( $rest )* }
    };
    ( $name: ident : $ty: ident ) => {
        #[inline] fn $name(&self) -> $ty {
            match *self {
                Header::Header32(x) => x.$name as $ty
              , Header::Header64(x) => x.$name as $ty
            }
        }
    };
    ( pub $name: ident : $ty: ident ) => {
        #[inline] pub fn $name(&self) -> $ty {
            match *self {
                Header::Header32(x) => x.$name as $ty
              , Header::Header64(x) => x.$name as $ty
            }
        }
    };
}

impl<'a> Header<'a> {
    impl_getters! { address: u64
                  , pub offset: u64
                  , pub length: u64
                  , pub link: u32
                  , pub info: u32
                  , pub address_align: u64
                  , pub entry_length: u64
                  }

    /// Returns the start address of this section
    #[inline] pub fn addr(&self) -> PAddr { PAddr::from(self.address()) }

    /// Returns the end address of this section
    #[inline] pub fn end_addr(&self) -> PAddr {
        PAddr::from(self.address() + self.length())
    }

    /// Returns the type of this section
    #[inline] pub fn flags(&self) -> Flags { get!(self, flags) }

    /// Returns the type of this section
    #[inline] pub fn get_type(&self) -> Type { get!(self, ty).as_type() }

    /// Returns true if this section is writable.
    #[inline] pub fn is_writable(&self) -> bool {
        get!(self, flags).contains(SHF_WRITE)
    }

    /// Returns true if this section occupies memory during program execution.
    #[inline] pub fn is_allocated(&self) -> bool {
        get!(self, flags).contains(SHF_ALLOC)
    }

    /// Returns true if this section contains executable instructions.
    #[inline] pub fn is_executable(&self) -> bool {
        get!(self, flags).contains(SHF_EXECINSTR)
    }

    /// Returns true if this section can be merged.
    #[inline] pub fn is_mergeable(&self) -> bool {
        get!(self, flags).contains(SHF_MERGE)
    }

    /// Returns true if this section contains data that is of a uniform size.
    #[inline] pub fn is_uniform(&self) -> bool {
        get!(self, flags).contains(SHF_MERGE) &&
        !get!(self, flags).contains(SHF_STRINGS)
    }
}

pub enum Contents<'a> {
    Empty
  , Undefined(&'a [u8])
  , Group { flags: &'a u32, indicies: &'a[u32] }
}

#[derive(Debug, Copy, Clone)]
struct TypeRepr(u32);

impl TypeRepr {
    #[inline] fn as_type(&self) -> Type {
        match self.0 {
            0 => Type::Null
          , 1 => Type::ProgramBits
          , 2 => Type::SymbolTable
          , 3 => Type::StringTable
          , 4 => Type::Rela
          , 5 => Type::HashTable
          , 6 => Type::Dynamic
          , 7 => Type::Notes
          , 8 => Type::NoBits
          , 9 => Type::Rel
          , 10 => Type::Shlib
          , 11 => Type::DynSymTable
          , 14 => Type::InitArray
          , 15 => Type::FiniArray
          , 16 => Type::PreInitArray
          , x @ SHT_LOOS ... SHT_HIOS => Type::OSSpecific(x)
          , x @ SHT_LOPROC ... SHT_HIPROC => Type::ProcessorSpecific(x)
          , x @ SHT_LOUSER ... SHT_HIUSER => Type::User(x)
          , _ => panic!("Invalid section type!")
        }
    }
}

/// Enum representing an ELF file section type.
///
/// Refer to Figure 1-10: "Section Types, sh_type" in Section 1 of the
/// [ELF standard](http://www.sco.com/developers/gabi/latest/ch4.sheader.html)
/// for more information.
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum Type {
    /// Section type 0: `SHT_NULL`
    ///
    /// This value marks the section header as inactive; it does not have an
    /// associated section. Other members of the section header have
    /// undefined values.
    Null
  , /// Section type 1: `SHT_PROGBITS`
    ///
    /// The section holds information defined by the program, whose format and
    /// meaning are determined solely by the program.
    ProgramBits
  , /// Section type 2: `SHT_SYMTAB`
    ///
    /// Typically, `SHT_SYMTAB` provides symbols for link editing, though it
    /// may also be used for dynamic linking. As a complete symbol table, it
    /// may contain many symbols unneces- sary for dynamic linking.
    ///
    /// Consequently, an object file may also contain a `SHT_DYNSYM` section,
    /// which holds a minimal set of dynamic linking symbols, to save space.
    SymbolTable
  , /// Section type 3: `SHT_STRTAB`
    ///
    /// The section holds a string table. An object file may have multiple
    /// string table sections.
    StringTable
  , /// Section type 4: `SHT_RELA`
    ///
    /// The section holds relocation entries with explicit addends, such as
    /// type `Elf32_Rela` for the 32-bit class of object files. An object file
    /// may have multiple relocation sections.
    Rela
  , /// Section type 5: `SHT_HASH`
    ///
    /// The section holds a symbol hash table. All objects participating in
    /// dynamic linking must contain a symbol hash table. Currently, an object
    /// file may have only one hash table, but this restriction may be relaxed
    /// in the future.
    HashTable
  , /// Section type 6: `SHT_DYNAMIC`
    ///
    /// The section holds information for dynamic linking. Currently, an object
    /// file may have only one dynamic section, but this restriction may be
    ///  relaxed in the future.
    Dynamic
  , /// Section type 7: `SHT_NOTE`
    ///
    /// The section holds information that marks the file in some way.
    Notes
  , /// Section type 8: `SHT_NOBITS`
    ///
    /// A section of this type occupies no space in the file but otherwise
    /// resembles `SHT_PROGBITS`. Although this section contains no bytes, the
    /// `sh_offset` member contains the conceptual file offset.
    NoBits
  , /// Section type 9: `SHT_REL`
    ///
    /// The section holds relocation entries without explicit addends, such as
    /// type `Elf32_Rel` for the 32-bit class of object files. An object file
    /// may have multiple reloca- tion sections.
    Rel
  , /// Section type 10: `SHT_SHLIB`
    ///
    /// This section type is reserved but has unspecified semantics. Programs
    /// that contain a section of this type do not conform to the ABI.
    Shlib
  , /// Section type 11: `SHT_DYNSYM`
    ///
    /// Typically, `SHT_SYMTAB` provides symbols for link editing, though it
    /// may also be used for dynamic linking. As a complete symbol table, it
    /// may contain many symbols unneces- sary for dynamic linking.
    ///
    /// Consequently, an object file may also contain a `SHT_DYNSYM` section,
    /// which holds a minimal set of dynamic linking symbols, to save space.
    DynSymTable
  , InitArray
  , FiniArray
  , PreInitArray
  , Group
  , SymbolTableShIndex
  , OSSpecific(u32)
  , ProcessorSpecific(u32)
  , User(u32)
}

/// Iterator over ELF64 sections
#[derive(Clone,Debug)]
pub struct Sections<'a, W: 'a> { curr: &'a HeaderRepr<W>
                               , remaining: u32
                               , size: u32
                               }

impl<'a, W: 'a> Sections<'a, W> {
    pub fn new(curr: &'a HeaderRepr<W>, remaining: u32, size: u32)
               -> Sections<'a, W>
    {
        Sections { curr: curr, remaining: remaining, size: size }

    }
}

impl<'a, W> Iterator for Sections<'a, W>
where HeaderRepr<W>: AsHeader {
    type Item = Header<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.remaining == 0 {
            None
        } else {
            let current = self.curr.as_header();
            self.curr = unsafe {
                &*(((self.curr as *const HeaderRepr<W>) as u32 + self.size)
                    as *const HeaderRepr<W>)
            };
            self.remaining -= 1;
            if current.get_type() == Type::Null {
                self.next()
            } else {
                Some(current)
            }
        }
    }
}

//
// #[derive(Debug)]
// #[repr(u32)]
// pub enum Flags { Writable    = 0x1
//                , Allocated   = 0x2
//                , Executable  = 0x4
//                }
<commit_msg>[elf] Section header variant name style tweaks<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use memory::PAddr;
use core::fmt;

// Distinguished section indices.
pub const SHN_UNDEF: u16        = 0;
pub const SHN_LORESERVE: u16    = 0xff00;
pub const SHN_LOPROC: u16       = 0xff00;
pub const SHN_HIPROC: u16       = 0xff1f;
pub const SHN_LOOS: u16         = 0xff20;
pub const SHN_HIOS: u16         = 0xff3f;
pub const SHN_ABS: u16          = 0xfff1;
pub const SHN_COMMON: u16       = 0xfff2;
pub const SHN_XINDEX: u16       = 0xffff;
pub const SHN_HIRESERVE: u16    = 0xffff;

pub const SHT_LOOS: u32   = 0x60000000;
pub const SHT_HIOS: u32   = 0x6fffffff;
pub const SHT_LOPROC: u32 = 0x70000000;
pub const SHT_HIPROC: u32 = 0x7fffffff;
pub const SHT_LOUSER: u32 = 0x80000000;
pub const SHT_HIUSER: u32 = 0xffffffff;

/// Represents an ELF section header
///
/// Refer to the [ELF standard](http://www.sco.com/developers/gabi/latest/ch4.sheader.html)
/// for more information.
#[derive(Clone, Copy, Debug)]
pub enum Header<'a> {
    ThirtyTwo(&'a HeaderRepr<u32>)
  , SixtyFour(&'a HeaderRepr<u64>)
}

#[derive(Debug)]
#[repr(C)]
pub struct HeaderRepr<Word> {
    /// This member specifies the name of the section.
    ///
    /// Its value is an index into the section header string table section,
    /// giving the location of a null-terminated string.
    name_offset: u32
  , /// This member categorizes the section's contents and semantics.
    ty: TypeRepr
  , flags: Flags
  , address: Word
  , offset: Word
  , length: Word
  , link: u32
  , info: u32
  , address_align: Word
  , entry_length: Word
}

trait AsHeader {
    fn as_header<'a>(&'a self) -> Header<'a>;
}

impl AsHeader for HeaderRepr<u32> {
    #[inline] fn as_header<'a>(&'a self) -> Header<'a> {
        Header::ThirtyTwo(self)
    }
}

impl AsHeader for HeaderRepr<u64> {
    #[inline] fn as_header<'a>(&'a self) -> Header<'a> {
        Header::SixtyFour(self)
    }
}

bitflags! {
    flags Flags: usize {
        // Flags (SectionHeader::flags)
        const SHF_WRITE            =        0x1
      , const SHF_ALLOC            =        0x2
      , const SHF_EXECINSTR        =        0x4
      , const SHF_MERGE            =       0x10
      , const SHF_STRINGS          =       0x20
      , const SHF_INFO_LINK        =       0x40
      , const SHF_LINK_ORDER       =       0x80
      , const SHF_OS_NONCONFORMING =      0x100
      , const SHF_GROUP            =      0x200
      , const SHF_TLS              =      0x400
      , const SHF_COMPRESSED       =      0x800
      , const SHF_MASKOS           = 0x0ff00000
      , const SHF_MASKPROC         = 0xf0000000
    }
}

impl fmt::LowerHex for Flags {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.bits.fmt(f)
    }
}

bitflags! {
    flags GroupFlags: u32 {
        const GRP_COMDAT	=        0x1
      , const GRP_MASKOS	= 0x0ff00000
      , const GRP_MASKPROC	= 0xf0000000
    }
}

macro_rules! get {
    ($s: expr, $name: ident) => {
        match *$s {
            Header::ThirtyTwo(x) => x.$name
          , Header::SixtyFour(x) => x.$name
        }
    }
}

macro_rules! impl_getters {
    ( pub $name: ident : $ty: ident, $( $rest: tt )* ) => {
        #[inline] pub fn $name(&self) -> $ty {
            match *self {
                Header::ThirtyTwo(x) => x.$name as $ty
              , Header::SixtyFour(x) => x.$name as $ty
            }
        }
        impl_getters!{ $( $rest )* }
    };
    ( $name: ident : $ty: ident,  $( $rest: tt )* ) => {
        #[inline] fn $name(&self) -> $ty {
            match *self {
                Header::ThirtyTwo(x) => x.$name as $ty
              , Header::SixtyFour(x) => x.$name as $ty
            }
        }
        impl_getters!{ $( $rest )* }
    };
    ( $name: ident : $ty: ident ) => {
        #[inline] fn $name(&self) -> $ty {
            match *self {
                Header::ThirtyTwo(x) => x.$name as $ty
              , Header::SixtyFour(x) => x.$name as $ty
            }
        }
    };
    ( pub $name: ident : $ty: ident ) => {
        #[inline] pub fn $name(&self) -> $ty {
            match *self {
                Header::ThirtyTwo(x) => x.$name as $ty
              , Header::SixtyFour(x) => x.$name as $ty
            }
        }
    };
}

impl<'a> Header<'a> {
    impl_getters! { address: u64
                  , pub offset: u64
                  , pub length: u64
                  , pub link: u32
                  , pub info: u32
                  , pub address_align: u64
                  , pub entry_length: u64
                  }

    /// Returns the start address of this section
    #[inline] pub fn addr(&self) -> PAddr { PAddr::from(self.address()) }

    /// Returns the end address of this section
    #[inline] pub fn end_addr(&self) -> PAddr {
        PAddr::from(self.address() + self.length())
    }

    /// Returns the type of this section
    #[inline] pub fn flags(&self) -> Flags { get!(self, flags) }

    /// Returns the type of this section
    #[inline] pub fn get_type(&self) -> Type { get!(self, ty).as_type() }

    /// Returns true if this section is writable.
    #[inline] pub fn is_writable(&self) -> bool {
        get!(self, flags).contains(SHF_WRITE)
    }

    /// Returns true if this section occupies memory during program execution.
    #[inline] pub fn is_allocated(&self) -> bool {
        get!(self, flags).contains(SHF_ALLOC)
    }

    /// Returns true if this section contains executable instructions.
    #[inline] pub fn is_executable(&self) -> bool {
        get!(self, flags).contains(SHF_EXECINSTR)
    }

    /// Returns true if this section can be merged.
    #[inline] pub fn is_mergeable(&self) -> bool {
        get!(self, flags).contains(SHF_MERGE)
    }

    /// Returns true if this section contains data that is of a uniform size.
    #[inline] pub fn is_uniform(&self) -> bool {
        get!(self, flags).contains(SHF_MERGE) &&
        !get!(self, flags).contains(SHF_STRINGS)
    }
}

pub enum Contents<'a> {
    Empty
  , Undefined(&'a [u8])
  , Group { flags: &'a u32, indicies: &'a[u32] }
}

#[derive(Debug, Copy, Clone)]
struct TypeRepr(u32);

impl TypeRepr {
    #[inline] fn as_type(&self) -> Type {
        match self.0 {
            0 => Type::Null
          , 1 => Type::ProgramBits
          , 2 => Type::SymbolTable
          , 3 => Type::StringTable
          , 4 => Type::Rela
          , 5 => Type::HashTable
          , 6 => Type::Dynamic
          , 7 => Type::Notes
          , 8 => Type::NoBits
          , 9 => Type::Rel
          , 10 => Type::Shlib
          , 11 => Type::DynSymTable
          , 14 => Type::InitArray
          , 15 => Type::FiniArray
          , 16 => Type::PreInitArray
          , x @ SHT_LOOS ... SHT_HIOS => Type::OSSpecific(x)
          , x @ SHT_LOPROC ... SHT_HIPROC => Type::ProcessorSpecific(x)
          , x @ SHT_LOUSER ... SHT_HIUSER => Type::User(x)
          , _ => panic!("Invalid section type!")
        }
    }
}

/// Enum representing an ELF file section type.
///
/// Refer to Figure 1-10: "Section Types, sh_type" in Section 1 of the
/// [ELF standard](http://www.sco.com/developers/gabi/latest/ch4.sheader.html)
/// for more information.
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum Type {
    /// Section type 0: `SHT_NULL`
    ///
    /// This value marks the section header as inactive; it does not have an
    /// associated section. Other members of the section header have
    /// undefined values.
    Null
  , /// Section type 1: `SHT_PROGBITS`
    ///
    /// The section holds information defined by the program, whose format and
    /// meaning are determined solely by the program.
    ProgramBits
  , /// Section type 2: `SHT_SYMTAB`
    ///
    /// Typically, `SHT_SYMTAB` provides symbols for link editing, though it
    /// may also be used for dynamic linking. As a complete symbol table, it
    /// may contain many symbols unneces- sary for dynamic linking.
    ///
    /// Consequently, an object file may also contain a `SHT_DYNSYM` section,
    /// which holds a minimal set of dynamic linking symbols, to save space.
    SymbolTable
  , /// Section type 3: `SHT_STRTAB`
    ///
    /// The section holds a string table. An object file may have multiple
    /// string table sections.
    StringTable
  , /// Section type 4: `SHT_RELA`
    ///
    /// The section holds relocation entries with explicit addends, such as
    /// type `Elf32_Rela` for the 32-bit class of object files. An object file
    /// may have multiple relocation sections.
    Rela
  , /// Section type 5: `SHT_HASH`
    ///
    /// The section holds a symbol hash table. All objects participating in
    /// dynamic linking must contain a symbol hash table. Currently, an object
    /// file may have only one hash table, but this restriction may be relaxed
    /// in the future.
    HashTable
  , /// Section type 6: `SHT_DYNAMIC`
    ///
    /// The section holds information for dynamic linking. Currently, an object
    /// file may have only one dynamic section, but this restriction may be
    ///  relaxed in the future.
    Dynamic
  , /// Section type 7: `SHT_NOTE`
    ///
    /// The section holds information that marks the file in some way.
    Notes
  , /// Section type 8: `SHT_NOBITS`
    ///
    /// A section of this type occupies no space in the file but otherwise
    /// resembles `SHT_PROGBITS`. Although this section contains no bytes, the
    /// `sh_offset` member contains the conceptual file offset.
    NoBits
  , /// Section type 9: `SHT_REL`
    ///
    /// The section holds relocation entries without explicit addends, such as
    /// type `Elf32_Rel` for the 32-bit class of object files. An object file
    /// may have multiple reloca- tion sections.
    Rel
  , /// Section type 10: `SHT_SHLIB`
    ///
    /// This section type is reserved but has unspecified semantics. Programs
    /// that contain a section of this type do not conform to the ABI.
    Shlib
  , /// Section type 11: `SHT_DYNSYM`
    ///
    /// Typically, `SHT_SYMTAB` provides symbols for link editing, though it
    /// may also be used for dynamic linking. As a complete symbol table, it
    /// may contain many symbols unneces- sary for dynamic linking.
    ///
    /// Consequently, an object file may also contain a `SHT_DYNSYM` section,
    /// which holds a minimal set of dynamic linking symbols, to save space.
    DynSymTable
  , InitArray
  , FiniArray
  , PreInitArray
  , Group
  , SymbolTableShIndex
  , OSSpecific(u32)
  , ProcessorSpecific(u32)
  , User(u32)
}

/// Iterator over ELF64 sections
#[derive(Clone,Debug)]
pub struct Sections<'a, W: 'a> { curr: &'a HeaderRepr<W>
                               , remaining: u32
                               , size: u32
                               }

impl<'a, W: 'a> Sections<'a, W> {
    pub fn new(curr: &'a HeaderRepr<W>, remaining: u32, size: u32)
               -> Sections<'a, W>
    {
        Sections { curr: curr, remaining: remaining, size: size }

    }
}

impl<'a, W> Iterator for Sections<'a, W>
where HeaderRepr<W>: AsHeader {
    type Item = Header<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if self.remaining == 0 {
            None
        } else {
            let current = self.curr.as_header();
            self.curr = unsafe {
                &*(((self.curr as *const HeaderRepr<W>) as u32 + self.size)
                    as *const HeaderRepr<W>)
            };
            self.remaining -= 1;
            if current.get_type() == Type::Null {
                self.next()
            } else {
                Some(current)
            }
        }
    }
}

//
// #[derive(Debug)]
// #[repr(u32)]
// pub enum Flags { Writable    = 0x1
//                , Allocated   = 0x2
//                , Executable  = 0x4
//                }
<|endoftext|>