<commit_before>// Copyright 2015, Paul Osborne <osbpau@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option.  This file may not be copied, modified, or distributed
// except according to those terms.
//
// Portions of this implementation are based on work by Nat Pryce:
// https://github.com/npryce/rusty-pi/blob/master/src/pi/gpio.rs

#![crate_type = "lib"]
#![crate_name = "sysfs_gpio"]

//! GPIO access under Linux using the GPIO sysfs interface
//!
//! The methods exposed by this library are centered around
//! the `Pin` struct and map pretty directly the API exposed
//! by the kernel in syfs (https://www.kernel.org/doc/Documentation/gpio/sysfs.txt).
//!
//! # Examples
//!
//! Typical usage for systems where one wants to ensure that
//! the pins in use are unexported upon completion looks like
//! the following:
//!
//! ```no_run
//! extern crate sysfs_gpio;
//!
//! use sysfs_gpio::{Direction, Pin};
//! use std::thread::sleep_ms;
//!
//! fn main() {
//!     let my_led = Pin::new(127); // number depends on chip, etc.
//!     my_led.with_exported(|| {
//!         loop {
//!             my_led.set_value(0).unwrap();
//!             sleep_ms(200);
//!             my_led.set_value(1).unwrap();
//!             sleep_ms(200);
//!         }
//!     }).unwrap();
//! }
//! ```

extern crate nix;

use nix::sys::epoll::*;
use nix::unistd::close;

use std::io::prelude::*;
use std::os::unix::prelude::*;
use std::io::{self, SeekFrom};
use std::fs;
use std::fs::{File};

mod error;
pub use error::Error;

pub struct Pin {
    pin_num : u64,
}

#[derive(Clone,Debug)]
pub enum Direction {In, Out, High, Low}

#[derive(Clone,Debug)]
pub enum Edge {NoInterrupt, RisingEdge, FallingEdge, BothEdges}

#[macro_export]
macro_rules! try_unexport {
    ($gpio:ident, $e:expr) => (match $e {
        Ok(res) => res,
        Err(e) => { try!($gpio.unexport()); return Err(e) },
    });
}

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

/// Flush up to max bytes from the provided files input buffer
///
/// Typically, one would just use seek() for this sort of thing,
/// but for certain files (e.g. in sysfs), you need to actually
/// read it.
fn flush_input_from_file(dev_file: &mut File, max : usize) -> io::Result<usize> {
    let mut s = String::with_capacity(max);
    dev_file.read_to_string(&mut s)
}

/// Get the pin value from the provided file
fn get_value_from_file(dev_file: &mut File) -> Result<u8> {
    let mut s = String::with_capacity(10);
    try!(dev_file.seek(SeekFrom::Start(0)));
    try!(dev_file.read_to_string(&mut s));
    match s[..1].parse::<u8>() {
        Ok(n) => Ok(n),
        Err(_) => Err(Error::Unexpected(format!("Unexpected value file contents: {:?}", s))),
    }
}

impl Pin {
    /// Write all of the provided contents to the specified devFile
    fn write_to_device_file(&self, dev_file_name: &str, value: &str) -> io::Result<()> {
        let gpio_path = format!("/sys/class/gpio/gpio{}/{}", self.pin_num, dev_file_name);
        let mut dev_file = try!(File::create(&gpio_path));
        try!(dev_file.write_all(value.as_bytes()));
        Ok(())
    }

    fn read_from_device_file(&self, dev_file_name: &str) -> io::Result<String> {
        let gpio_path = format!("/sys/class/gpio/gpio{}/{}", self.pin_num, dev_file_name);
        let mut dev_file = try!(File::create(&gpio_path));
        let mut s = String::new();
        try!(dev_file.read_to_string(&mut s));
        Ok(s)
    }

    /// Create a new Pin with the provided `pin_num`
    ///
    /// This function does not export the provided pin_num.
    pub fn new(pin_num : u64) -> Pin {
        Pin {
            pin_num: pin_num,
        }
    }

    /// Run a closure with the GPIO exported
    ///
    /// Prior to the provided closure being executed, the GPIO
    /// will be exported.  After the closure execution is complete,
    /// the GPIO will be unexported.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use sysfs_gpio::{Pin, Direction};
    ///
    /// let gpio = Pin::new(24);
    /// let res = gpio.with_exported(|| {
    ///     println!("At this point, the Pin is exported");
    ///     try!(gpio.set_direction(Direction::Low));
    ///     try!(gpio.set_value(1));
    ///     // ...
    ///     Ok(())
    /// });
    /// ```
    #[inline]
    pub fn with_exported<F: FnOnce() -> Result<()>>(&self, closure : F)
        -> Result<()> {

        try!(self.export());
        match closure() {
            Ok(()) => { try!(self.unexport()); Ok(()) },
            Err(err) => { try!(self.unexport()); Err(err) },
        }
    }

    /// Export the GPIO
    ///
    /// This is equivalent to `echo N > /sys/class/gpio/export` with
    /// the exception that the case where the GPIO is already exported
    /// is not an error.
    ///
    /// # Errors
    ///
    /// The main cases in which this function will fail and return an
    /// error are the following:
    /// 1. The system does not support the GPIO sysfs interface
    /// 2. The requested GPIO is out of range and cannot be exported
    /// 3. The requested GPIO is in use by the kernel and cannot
    ///    be exported by use in userspace
    ///
    /// # Example
    /// ```no_run
    /// use sysfs_gpio::Pin;
    ///
    /// let gpio = Pin::new(24);
    /// match gpio.export() {
    ///     Ok(()) => println!("Gpio {} exported!", gpio.get_pin()),
    ///     Err(err) => println!("Gpio {} could not be exported: {}", gpio.get_pin(), err),
    /// }
    /// ```
    pub fn export(&self) -> Result<()> {
        if let Err(_) = fs::metadata(&format!("/sys/class/gpio/gpio{}", self.pin_num)) {
            let mut export_file = try!(File::create("/sys/class/gpio/export"));
            try!(export_file.write_all(format!("{}", self.pin_num).as_bytes()));
        }
        Ok(())
    }

    /// Unexport the GPIO
    ///
    /// This function will unexport the provided by from syfs if
    /// it is currently exported.  If the pin is not currently
    /// exported, it will return without error.  That is, whenever
    /// this function returns Ok, the GPIO is not exported.
    pub fn unexport(&self) -> Result<()> {
        if let Ok(_) = fs::metadata(&format!("/sys/class/gpio/gpio{}", self.pin_num)) {
            let mut unexport_file = try!(File::create("/sys/class/gpio/unexport"));
            try!(unexport_file.write_all(format!("{}", self.pin_num).as_bytes()));
        }
        Ok(())
    }

    /// Get the pin number for the Pin
    pub fn get_pin(&self) -> u64 {
        self.pin_num
    }

    /// Get the direction of the Pin
    pub fn get_direction(&self) -> Result<Direction> {
        match self.read_from_device_file("direction") {
            Ok(s) => {
                match s.trim() {
                    "in" => Ok(Direction::In),
                    "out" => Ok(Direction::Out),
                    "high" => Ok(Direction::High),
                    "low" => Ok(Direction::Low),
                    other => Err(Error::Unexpected(format!("direction file contents {}", other))),
                }
            }
            Err(e) => Err(::std::convert::From::from(e))
        }
    }

    /// Set this GPIO as either an input or an output
    ///
    /// The basic values allowed here are `Direction::In` and
    /// `Direction::Out` which set the Pin as either an input
    /// or output respectively.  In addition to those, two
    /// additional settings of `Direction::High` and
    /// `Direction::Low`.  These both set the Pin as an output
    /// but do so with an initial value of high or low respectively.
    /// This allows for glitch-free operation.
    ///
    /// Note that this entry may not exist if the kernel does
    /// not support changing the direction of a pin in userspace.  If
    /// this is the case, you will get an error.
    pub fn set_direction(&self, dir : Direction) -> Result<()> {
        try!(self.write_to_device_file("direction", match dir {
            Direction::In => "in",
            Direction::Out => "out",
            Direction::High => "high",
            Direction::Low => "low",
        }));

        Ok(())
    }

    /// Get the value of the Pin (0 or 1)
    ///
    /// If successful, 1 will be returned if the pin is high
    /// and 0 will be returned if the pin is low (this may or may
    /// not match the signal level of the actual signal depending
    /// on the GPIO "active_low" entry).
    pub fn get_value(&self) -> Result<u8> {
        match self.read_from_device_file("value") {
            Ok(s) => {
                match s.trim() {
                    "1" => Ok(1),
                    "0" => Ok(0),
                    other => Err(Error::Unexpected(format!("value file contents {}", other))),
                }
            }
            Err(e) => Err(::std::convert::From::from(e))
        }
    }

    /// Set the value of the Pin
    ///
    /// This will set the value of the pin either high or low.
    /// A 0 value will set the pin low and any other value will
    /// set the pin high (1 is typical).
    pub fn set_value(&self, value : u8) -> Result<()> {
        try!(self.write_to_device_file("value", match value {
            0 => "0",
            _ => "1",
        }));

        Ok(())
    }

    /// Get the currently configured edge for this pin
    ///
    /// This value will only be present if the Pin allows
    /// for interrupts.
    pub fn get_edge(&self) -> Result<Edge> {
        match self.read_from_device_file("edge") {
            Ok(s) => {
                match s.trim() {
                    "none" => Ok(Edge::NoInterrupt),
                    "rising" => Ok(Edge::RisingEdge),
                    "falling" => Ok(Edge::FallingEdge),
                    "both" => Ok(Edge::BothEdges),
                    other => Err(Error::Unexpected(format!("Unexpected file contents {}", other))),
                }
            }
            Err(e) => Err(::std::convert::From::from(e))
        }
    }

    /// Set the edge on which this GPIO will trigger when polled
    ///
    /// The configured edge determines what changes to the Pin will
    /// result in `poll()` returning.  This call will return an Error
    /// if the pin does not allow interrupts.
    pub fn set_edge(&self, edge: Edge) -> Result<()> {
        try!(self.write_to_device_file("edge", match edge {
            Edge::NoInterrupt => "none",
            Edge::RisingEdge => "rising",
            Edge::FallingEdge => "falling",
            Edge::BothEdges => "both",
        }));

        Ok(())
    }

    /// Get a PinPoller object for this pin
    ///
    /// This pin poller object will register an interrupt with the
    /// kernel and allow you to poll() on it and receive notifications
    /// that an interrupt has occured with minimal delay.
    pub fn get_poller(&self) -> Result<PinPoller> {
        PinPoller::new(self.pin_num)
    }
}

pub struct PinPoller {
    pin_num : u64,
    epoll_fd : RawFd,
    devfile : File,
}

impl PinPoller {

    /// Get the pin associated with this PinPoller
    ///
    /// Note that this will be a new Pin object with the
    /// proper pin number.
    pub fn get_pin(&self) -> Pin {
        Pin::new(self.pin_num)
    }

    /// Create a new PinPoller for the provided pin number
    pub fn new(pin_num : u64) -> Result<PinPoller> {
        let devfile : File = try!(File::open(&format!("/sys/class/gpio/gpio{}/value", pin_num)));
        let devfile_fd = devfile.as_raw_fd();
        let epoll_fd = try!(epoll_create());
        let events = EPOLLPRI | EPOLLET;
        let info = EpollEvent {
            events: events,
            data: 0u64,
        };

        match epoll_ctl(epoll_fd, EpollOp::EpollCtlAdd, devfile_fd, &info) {
            Ok(_) => {
                Ok(PinPoller {
                    pin_num: pin_num,
                    devfile: devfile,
                    epoll_fd: epoll_fd,
                })
            },
            Err(err) => {
                let _ = close(epoll_fd); // cleanup
                Err(::std::convert::From::from(err))
            }
        }
    }

    /// Block until an interrupt occurs
    ///
    /// This call will block until an interrupt occurs.  The types
    /// of interrupts which may result in this call returning
    /// may be configured by calling `set_edge()` prior to
    /// making this call.  This call makes use of epoll under the
    /// covers.  If it is desirable to poll on multiple GPIOs or
    /// other event source, you will need to implement that logic
    /// yourself.
    ///
    /// This function will return Some(value) of the pin if a change is
    /// detected or None if a timeout occurs.  Note that the value provided
    /// is the value of the pin as soon as we get to handling the interrupt
    /// in userspace.  Each time this function returns with a value, a change
    /// has occurred, but you could end up reading the same value multiple
    /// times as the value has changed back between when the interrupt
    /// occurred and the current time.
    pub fn poll(&mut self, timeout_ms: isize) -> Result<Option<u8>> {
        try!(flush_input_from_file(&mut self.devfile, 255));
        let dummy_event = EpollEvent { events: EPOLLPRI | EPOLLET, data: 0u64};
        let mut events: [EpollEvent; 1] = [ dummy_event ];
        let cnt = try!(epoll_wait(self.epoll_fd, &mut events, timeout_ms));
        Ok(match cnt {
            0 => None, // timeout
            _ => Some(try!(get_value_from_file(&mut self.devfile))),
        })
    }
}

impl Drop for PinPoller {
    fn drop(&mut self) {
        // we implement drop to close the underlying epoll fd as
        // it does not implement drop itself.  This is similar to
        // how mio works
        close(self.epoll_fd).unwrap();  // panic! if close files
    }
}
<commit_msg>derive Debug for Pin and PinPoller<commit_after>// Copyright 2015, Paul Osborne <osbpau@gmail.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option.  This file may not be copied, modified, or distributed
// except according to those terms.
//
// Portions of this implementation are based on work by Nat Pryce:
// https://github.com/npryce/rusty-pi/blob/master/src/pi/gpio.rs

#![crate_type = "lib"]
#![crate_name = "sysfs_gpio"]

//! GPIO access under Linux using the GPIO sysfs interface
//!
//! The methods exposed by this library are centered around
//! the `Pin` struct and map pretty directly the API exposed
//! by the kernel in syfs (https://www.kernel.org/doc/Documentation/gpio/sysfs.txt).
//!
//! # Examples
//!
//! Typical usage for systems where one wants to ensure that
//! the pins in use are unexported upon completion looks like
//! the following:
//!
//! ```no_run
//! extern crate sysfs_gpio;
//!
//! use sysfs_gpio::{Direction, Pin};
//! use std::thread::sleep_ms;
//!
//! fn main() {
//!     let my_led = Pin::new(127); // number depends on chip, etc.
//!     my_led.with_exported(|| {
//!         loop {
//!             my_led.set_value(0).unwrap();
//!             sleep_ms(200);
//!             my_led.set_value(1).unwrap();
//!             sleep_ms(200);
//!         }
//!     }).unwrap();
//! }
//! ```

extern crate nix;

use nix::sys::epoll::*;
use nix::unistd::close;

use std::io::prelude::*;
use std::os::unix::prelude::*;
use std::io::{self, SeekFrom};
use std::fs;
use std::fs::{File};

mod error;
pub use error::Error;

#[derive(Debug)]
pub struct Pin {
    pin_num : u64,
}

#[derive(Clone,Debug)]
pub enum Direction {In, Out, High, Low}

#[derive(Clone,Debug)]
pub enum Edge {NoInterrupt, RisingEdge, FallingEdge, BothEdges}

#[macro_export]
macro_rules! try_unexport {
    ($gpio:ident, $e:expr) => (match $e {
        Ok(res) => res,
        Err(e) => { try!($gpio.unexport()); return Err(e) },
    });
}

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

/// Flush up to max bytes from the provided files input buffer
///
/// Typically, one would just use seek() for this sort of thing,
/// but for certain files (e.g. in sysfs), you need to actually
/// read it.
fn flush_input_from_file(dev_file: &mut File, max : usize) -> io::Result<usize> {
    let mut s = String::with_capacity(max);
    dev_file.read_to_string(&mut s)
}

/// Get the pin value from the provided file
fn get_value_from_file(dev_file: &mut File) -> Result<u8> {
    let mut s = String::with_capacity(10);
    try!(dev_file.seek(SeekFrom::Start(0)));
    try!(dev_file.read_to_string(&mut s));
    match s[..1].parse::<u8>() {
        Ok(n) => Ok(n),
        Err(_) => Err(Error::Unexpected(format!("Unexpected value file contents: {:?}", s))),
    }
}

impl Pin {
    /// Write all of the provided contents to the specified devFile
    fn write_to_device_file(&self, dev_file_name: &str, value: &str) -> io::Result<()> {
        let gpio_path = format!("/sys/class/gpio/gpio{}/{}", self.pin_num, dev_file_name);
        let mut dev_file = try!(File::create(&gpio_path));
        try!(dev_file.write_all(value.as_bytes()));
        Ok(())
    }

    fn read_from_device_file(&self, dev_file_name: &str) -> io::Result<String> {
        let gpio_path = format!("/sys/class/gpio/gpio{}/{}", self.pin_num, dev_file_name);
        let mut dev_file = try!(File::create(&gpio_path));
        let mut s = String::new();
        try!(dev_file.read_to_string(&mut s));
        Ok(s)
    }

    /// Create a new Pin with the provided `pin_num`
    ///
    /// This function does not export the provided pin_num.
    pub fn new(pin_num : u64) -> Pin {
        Pin {
            pin_num: pin_num,
        }
    }

    /// Run a closure with the GPIO exported
    ///
    /// Prior to the provided closure being executed, the GPIO
    /// will be exported.  After the closure execution is complete,
    /// the GPIO will be unexported.
    ///
    /// # Example
    ///
    /// ```no_run
    /// use sysfs_gpio::{Pin, Direction};
    ///
    /// let gpio = Pin::new(24);
    /// let res = gpio.with_exported(|| {
    ///     println!("At this point, the Pin is exported");
    ///     try!(gpio.set_direction(Direction::Low));
    ///     try!(gpio.set_value(1));
    ///     // ...
    ///     Ok(())
    /// });
    /// ```
    #[inline]
    pub fn with_exported<F: FnOnce() -> Result<()>>(&self, closure : F)
        -> Result<()> {

        try!(self.export());
        match closure() {
            Ok(()) => { try!(self.unexport()); Ok(()) },
            Err(err) => { try!(self.unexport()); Err(err) },
        }
    }

    /// Export the GPIO
    ///
    /// This is equivalent to `echo N > /sys/class/gpio/export` with
    /// the exception that the case where the GPIO is already exported
    /// is not an error.
    ///
    /// # Errors
    ///
    /// The main cases in which this function will fail and return an
    /// error are the following:
    /// 1. The system does not support the GPIO sysfs interface
    /// 2. The requested GPIO is out of range and cannot be exported
    /// 3. The requested GPIO is in use by the kernel and cannot
    ///    be exported by use in userspace
    ///
    /// # Example
    /// ```no_run
    /// use sysfs_gpio::Pin;
    ///
    /// let gpio = Pin::new(24);
    /// match gpio.export() {
    ///     Ok(()) => println!("Gpio {} exported!", gpio.get_pin()),
    ///     Err(err) => println!("Gpio {} could not be exported: {}", gpio.get_pin(), err),
    /// }
    /// ```
    pub fn export(&self) -> Result<()> {
        if let Err(_) = fs::metadata(&format!("/sys/class/gpio/gpio{}", self.pin_num)) {
            let mut export_file = try!(File::create("/sys/class/gpio/export"));
            try!(export_file.write_all(format!("{}", self.pin_num).as_bytes()));
        }
        Ok(())
    }

    /// Unexport the GPIO
    ///
    /// This function will unexport the provided by from syfs if
    /// it is currently exported.  If the pin is not currently
    /// exported, it will return without error.  That is, whenever
    /// this function returns Ok, the GPIO is not exported.
    pub fn unexport(&self) -> Result<()> {
        if let Ok(_) = fs::metadata(&format!("/sys/class/gpio/gpio{}", self.pin_num)) {
            let mut unexport_file = try!(File::create("/sys/class/gpio/unexport"));
            try!(unexport_file.write_all(format!("{}", self.pin_num).as_bytes()));
        }
        Ok(())
    }

    /// Get the pin number for the Pin
    pub fn get_pin(&self) -> u64 {
        self.pin_num
    }

    /// Get the direction of the Pin
    pub fn get_direction(&self) -> Result<Direction> {
        match self.read_from_device_file("direction") {
            Ok(s) => {
                match s.trim() {
                    "in" => Ok(Direction::In),
                    "out" => Ok(Direction::Out),
                    "high" => Ok(Direction::High),
                    "low" => Ok(Direction::Low),
                    other => Err(Error::Unexpected(format!("direction file contents {}", other))),
                }
            }
            Err(e) => Err(::std::convert::From::from(e))
        }
    }

    /// Set this GPIO as either an input or an output
    ///
    /// The basic values allowed here are `Direction::In` and
    /// `Direction::Out` which set the Pin as either an input
    /// or output respectively.  In addition to those, two
    /// additional settings of `Direction::High` and
    /// `Direction::Low`.  These both set the Pin as an output
    /// but do so with an initial value of high or low respectively.
    /// This allows for glitch-free operation.
    ///
    /// Note that this entry may not exist if the kernel does
    /// not support changing the direction of a pin in userspace.  If
    /// this is the case, you will get an error.
    pub fn set_direction(&self, dir : Direction) -> Result<()> {
        try!(self.write_to_device_file("direction", match dir {
            Direction::In => "in",
            Direction::Out => "out",
            Direction::High => "high",
            Direction::Low => "low",
        }));

        Ok(())
    }

    /// Get the value of the Pin (0 or 1)
    ///
    /// If successful, 1 will be returned if the pin is high
    /// and 0 will be returned if the pin is low (this may or may
    /// not match the signal level of the actual signal depending
    /// on the GPIO "active_low" entry).
    pub fn get_value(&self) -> Result<u8> {
        match self.read_from_device_file("value") {
            Ok(s) => {
                match s.trim() {
                    "1" => Ok(1),
                    "0" => Ok(0),
                    other => Err(Error::Unexpected(format!("value file contents {}", other))),
                }
            }
            Err(e) => Err(::std::convert::From::from(e))
        }
    }

    /// Set the value of the Pin
    ///
    /// This will set the value of the pin either high or low.
    /// A 0 value will set the pin low and any other value will
    /// set the pin high (1 is typical).
    pub fn set_value(&self, value : u8) -> Result<()> {
        try!(self.write_to_device_file("value", match value {
            0 => "0",
            _ => "1",
        }));

        Ok(())
    }

    /// Get the currently configured edge for this pin
    ///
    /// This value will only be present if the Pin allows
    /// for interrupts.
    pub fn get_edge(&self) -> Result<Edge> {
        match self.read_from_device_file("edge") {
            Ok(s) => {
                match s.trim() {
                    "none" => Ok(Edge::NoInterrupt),
                    "rising" => Ok(Edge::RisingEdge),
                    "falling" => Ok(Edge::FallingEdge),
                    "both" => Ok(Edge::BothEdges),
                    other => Err(Error::Unexpected(format!("Unexpected file contents {}", other))),
                }
            }
            Err(e) => Err(::std::convert::From::from(e))
        }
    }

    /// Set the edge on which this GPIO will trigger when polled
    ///
    /// The configured edge determines what changes to the Pin will
    /// result in `poll()` returning.  This call will return an Error
    /// if the pin does not allow interrupts.
    pub fn set_edge(&self, edge: Edge) -> Result<()> {
        try!(self.write_to_device_file("edge", match edge {
            Edge::NoInterrupt => "none",
            Edge::RisingEdge => "rising",
            Edge::FallingEdge => "falling",
            Edge::BothEdges => "both",
        }));

        Ok(())
    }

    /// Get a PinPoller object for this pin
    ///
    /// This pin poller object will register an interrupt with the
    /// kernel and allow you to poll() on it and receive notifications
    /// that an interrupt has occured with minimal delay.
    pub fn get_poller(&self) -> Result<PinPoller> {
        PinPoller::new(self.pin_num)
    }
}

#[derive(Debug)]
pub struct PinPoller {
    pin_num : u64,
    epoll_fd : RawFd,
    devfile : File,
}

impl PinPoller {

    /// Get the pin associated with this PinPoller
    ///
    /// Note that this will be a new Pin object with the
    /// proper pin number.
    pub fn get_pin(&self) -> Pin {
        Pin::new(self.pin_num)
    }

    /// Create a new PinPoller for the provided pin number
    pub fn new(pin_num : u64) -> Result<PinPoller> {
        let devfile : File = try!(File::open(&format!("/sys/class/gpio/gpio{}/value", pin_num)));
        let devfile_fd = devfile.as_raw_fd();
        let epoll_fd = try!(epoll_create());
        let events = EPOLLPRI | EPOLLET;
        let info = EpollEvent {
            events: events,
            data: 0u64,
        };

        match epoll_ctl(epoll_fd, EpollOp::EpollCtlAdd, devfile_fd, &info) {
            Ok(_) => {
                Ok(PinPoller {
                    pin_num: pin_num,
                    devfile: devfile,
                    epoll_fd: epoll_fd,
                })
            },
            Err(err) => {
                let _ = close(epoll_fd); // cleanup
                Err(::std::convert::From::from(err))
            }
        }
    }

    /// Block until an interrupt occurs
    ///
    /// This call will block until an interrupt occurs.  The types
    /// of interrupts which may result in this call returning
    /// may be configured by calling `set_edge()` prior to
    /// making this call.  This call makes use of epoll under the
    /// covers.  If it is desirable to poll on multiple GPIOs or
    /// other event source, you will need to implement that logic
    /// yourself.
    ///
    /// This function will return Some(value) of the pin if a change is
    /// detected or None if a timeout occurs.  Note that the value provided
    /// is the value of the pin as soon as we get to handling the interrupt
    /// in userspace.  Each time this function returns with a value, a change
    /// has occurred, but you could end up reading the same value multiple
    /// times as the value has changed back between when the interrupt
    /// occurred and the current time.
    pub fn poll(&mut self, timeout_ms: isize) -> Result<Option<u8>> {
        try!(flush_input_from_file(&mut self.devfile, 255));
        let dummy_event = EpollEvent { events: EPOLLPRI | EPOLLET, data: 0u64};
        let mut events: [EpollEvent; 1] = [ dummy_event ];
        let cnt = try!(epoll_wait(self.epoll_fd, &mut events, timeout_ms));
        Ok(match cnt {
            0 => None, // timeout
            _ => Some(try!(get_value_from_file(&mut self.devfile))),
        })
    }
}

impl Drop for PinPoller {
    fn drop(&mut self) {
        // we implement drop to close the underlying epoll fd as
        // it does not implement drop itself.  This is similar to
        // how mio works
        close(self.epoll_fd).unwrap();  // panic! if close files
    }
}
<|endoftext|>


<commit_before><commit_msg>Add crate docs.<commit_after><|endoftext|>


<commit_before><commit_msg>src/lib.rs: added missing file<commit_after>extern crate integeriser;
extern crate log_domain;
#[macro_use]
extern crate nom;
extern crate num_traits;
extern crate time;
extern crate rand;

pub mod approximation;
#[macro_use]
pub mod recognisable;
pub mod cfg;
pub mod nfa;
pub mod pmcfg;
pub mod push_down_automaton;
pub mod tree_stack_automaton;
mod util;

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before><commit_msg>add_history_persist<commit_after><|endoftext|>


<commit_before><commit_msg>API Evolution 1<commit_after><|endoftext|>


<commit_before><commit_msg>Just fuckin about so far<commit_after>pub struct IntMap<T> {
    p: u64,
    m: u64,
    notEmpty: bool,
    c: cntnts(T),
}

enum cntnts<T> {
    Branch ([IntMap(T); 2]),
    Leaf (T),
}

impl<T> IntMap<T> {
    fn new() -> IntMap<T> {
        IntMap {
            p: 0,
            m: 0,
            notEmpty: false,
            c: cntnts<T>,
        }
    }
    fn insert<'a>(&self, k: u64, v: &'a [T]) -> IntMap {

    }
}

impl<T: Copy> Copy for IntMap<T> {

}
<|endoftext|>


<commit_before><commit_msg>Remove add_cookies - add_cookie provides better interface.<commit_after><|endoftext|>


<commit_before><commit_msg>Use Rust 2018 edition idioms.<commit_after><|endoftext|>


<commit_before><commit_msg>Add missing test case for bottom_up_iter with 2 children<commit_after><|endoftext|>


<commit_before><commit_msg>Add UnixDatagram::pair<commit_after><|endoftext|>


<commit_before><commit_msg>add convenience wrappers for var and vars<commit_after><|endoftext|>


<commit_before><commit_msg>Add code commenting to lib.rs<commit_after><|endoftext|>


<commit_before><commit_msg>New 4bpp decoding method.<commit_after><|endoftext|>


<commit_before><commit_msg>make struct fields public<commit_after><|endoftext|>


<commit_before><commit_msg>Added circle overlap tests<commit_after><|endoftext|>


<commit_before><commit_msg>Add tests for backup dir<commit_after><|endoftext|>


<commit_before><commit_msg>Check in benchmark that I haven't run (requires nightly) so I don't lose it.<commit_after>#![feature(test)]

extern crate rand;
extern crate splittable_random as splittable;
extern crate test;

const RAND_BENCH_N: u64 = 1000;

use std::mem::size_of;
use test::{black_box, Bencher};
use rand::{Rng, OsRng};
use splittable::siprng::SipRng;

#[bench]
fn rand_siprng(b: &mut Bencher) {
    let mut rng: SipRng = OsRng::new().unwrap().gen();
    b.iter(|| {
        for _ in 0..RAND_BENCH_N {
            black_box(rng.gen::<usize>());
        }
    });
    b.bytes = size_of::<usize>() as u64 * RAND_BENCH_N;
}
<|endoftext|>


<commit_before><commit_msg>Ensure scanner state is correct upon completion<commit_after><|endoftext|>


<commit_before><commit_msg>Removed ChistResult. Errors are now pushed to the stack. Stack now holds Elements not Values.<commit_after><|endoftext|>


<commit_before><commit_msg>version-helper: copy git.rs from gtk-rs/gir<commit_after>use std::path::Path;
use std::process::Command;

pub fn repo_hash<P: AsRef<Path>>(path: P) -> Option<String> {
    let git_path = path.as_ref().to_str();
    let mut args = match git_path {
        Some(path) => vec!["-C", path],
        None => vec![],
    };
    args.extend(&["rev-parse", "--short", "HEAD"]);
    let output = Command::new("git").args(&args).output().ok()?;
    if !output.status.success() {
        return None;
    }
    let hash = String::from_utf8(output.stdout).ok()?;
    let hash = hash.trim_end_matches('\n');

    if dirty(path) {
        Some(format!("{}+", hash))
    } else {
        Some(hash.into())
    }
}

fn dirty<P: AsRef<Path>>(path: P) -> bool {
    let path = path.as_ref().to_str();
    let mut args = match path {
        Some(path) => vec!["-C", path],
        None => vec![],
    };
    args.extend(&["ls-files", "-m"]);
    match Command::new("git").args(&args).output() {
        Ok(modified_files) => !modified_files.stdout.is_empty(),
        Err(_) => false,
    }
}
<|endoftext|>


<commit_before>//! Implementation of `cargo config` subcommand.

use crate::drop_println;
use crate::util::config::{Config, ConfigKey, ConfigValue as CV, Definition};
use crate::util::errors::CargoResult;
use anyhow::{bail, format_err, Error};
use serde_json::json;
use std::borrow::Cow;
use std::fmt;
use std::str::FromStr;

pub enum ConfigFormat {
    Toml,
    Json,
    JsonValue,
}

impl ConfigFormat {
    /// For clap.
    pub const POSSIBLE_VALUES: &'static [&'static str] = &["toml", "json", "json-value"];
}

impl FromStr for ConfigFormat {
    type Err = Error;
    fn from_str(s: &str) -> CargoResult<Self> {
        match s {
            "toml" => Ok(ConfigFormat::Toml),
            "json" => Ok(ConfigFormat::Json),
            "json-value" => Ok(ConfigFormat::JsonValue),
            f => bail!("unknown config format `{}`", f),
        }
    }
}

impl fmt::Display for ConfigFormat {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ConfigFormat::Toml => write!(f, "toml"),
            ConfigFormat::Json => write!(f, "json"),
            ConfigFormat::JsonValue => write!(f, "json-value"),
        }
    }
}

/// Options for `cargo config get`.
pub struct GetOptions<'a> {
    pub key: Option<&'a str>,
    pub format: ConfigFormat,
    pub show_origin: bool,
    pub merged: bool,
}

pub fn get(config: &Config, opts: &GetOptions<'_>) -> CargoResult<()> {
    if opts.show_origin {
        if !matches!(opts.format, ConfigFormat::Toml) {
            bail!(
                "the `{}` format does not support --show-origin, try the `toml` format instead",
                opts.format
            );
        }
    }
    let key = match opts.key {
        Some(key) => ConfigKey::from_str(key),
        None => ConfigKey::new(),
    };
    if opts.merged {
        let cv = config
            .get_cv_with_env(&key)?
            .ok_or_else(|| format_err!("config value `{}` is not set", key))?;
        match opts.format {
            ConfigFormat::Toml => {
                print_toml(config, opts, &key, &cv);
                if let Some(env) = maybe_env(config, &key, &cv) {
                    print_toml_env(config, &env);
                }
            }
            ConfigFormat::Json => print_json(config, &key, &cv, true),
            ConfigFormat::JsonValue => print_json(config, &key, &cv, false),
        }
    } else {
        match &opts.format {
            ConfigFormat::Toml => print_toml_unmerged(config, opts, &key)?,
            format => bail!(
                "the `{}` format does not support --merged=no, try the `toml` format instead",
                format
            ),
        }
    }
    Ok(())
}

/// Checks for environment variables that might be used.
fn maybe_env<'config>(
    config: &'config Config,
    key: &ConfigKey,
    cv: &CV,
) -> Option<Vec<(&'config String, &'config String)>> {
    // Only fetching a table is unable to load env values. Leaf entries should
    // work properly.
    match cv {
        CV::Table(_map, _def) => {}
        _ => return None,
    }
    let mut env: Vec<_> = config
        .env()
        .iter()
        .filter(|(env_key, _val)| env_key.starts_with(&format!("{}_", key.as_env_key())))
        .collect();
    env.sort_by_key(|x| x.0);
    if env.is_empty() {
        None
    } else {
        Some(env)
    }
}

fn print_toml(config: &Config, opts: &GetOptions<'_>, key: &ConfigKey, cv: &CV) {
    let origin = |def: &Definition| -> String {
        if !opts.show_origin {
            return "".to_string();
        }
        format!(" # {}", def)
    };
    match cv {
        CV::Boolean(val, def) => drop_println!(config, "{} = {}{}", key, val, origin(&def)),
        CV::Integer(val, def) => drop_println!(config, "{} = {}{}", key, val, origin(&def)),
        CV::String(val, def) => drop_println!(
            config,
            "{} = {}{}",
            key,
            toml::to_string(&val).unwrap(),
            origin(&def)
        ),
        CV::List(vals, _def) => {
            if opts.show_origin {
                drop_println!(config, "{} = [", key);
                for (val, def) in vals {
                    drop_println!(config, "    {}, # {}", toml::to_string(&val).unwrap(), def);
                }
                drop_println!(config, "]");
            } else {
                let vals: Vec<&String> = vals.iter().map(|x| &x.0).collect();
                drop_println!(config, "{} = {}", key, toml::to_string(&vals).unwrap());
            }
        }
        CV::Table(table, _def) => {
            let mut key_vals: Vec<_> = table.into_iter().collect();
            key_vals.sort_by(|a, b| a.0.cmp(&b.0));
            for (table_key, val) in key_vals {
                let mut subkey = key.clone();
                // push or push_sensitive shouldn't matter here, since this is
                // not dealing with environment variables.
                subkey.push(&table_key);
                print_toml(config, opts, &subkey, val);
            }
        }
    }
}

fn print_toml_env(config: &Config, env: &[(&String, &String)]) {
    drop_println!(
        config,
        "# The following environment variables may affect the loaded values."
    );
    for (env_key, env_value) in env {
        let val = shell_escape::escape(Cow::Borrowed(env_value));
        drop_println!(config, "# {}={}", env_key, val);
    }
}

fn print_json(config: &Config, key: &ConfigKey, cv: &CV, include_key: bool) {
    let json_value = if key.is_root() || !include_key {
        match cv {
            CV::Boolean(val, _def) => json!(val),
            CV::Integer(val, _def) => json!(val),
            CV::String(val, _def) => json!(val),
            CV::List(vals, _def) => {
                let jvals: Vec<_> = vals.into_iter().map(|(val, _def)| json!(val)).collect();
                json!(jvals)
            }
            CV::Table(map, _def) => {
                let mut root_table = json!({});
                for (key, val) in map {
                    json_add(&mut root_table, key, val);
                }
                root_table
            }
        }
    } else {
        let mut parts: Vec<_> = key.parts().collect();
        let last_part = parts.pop().unwrap();
        let mut root_table = json!({});
        // Create a JSON object with nested keys up to the value being displayed.
        let mut table = &mut root_table;
        for part in parts {
            table[part] = json!({});
            table = table.get_mut(part).unwrap();
        }
        json_add(table, last_part, cv);
        root_table
    };
    drop_println!(config, "{}", serde_json::to_string(&json_value).unwrap());

    // Helper for recursively converting a CV to JSON.
    fn json_add(table: &mut serde_json::Value, key: &str, cv: &CV) {
        match cv {
            CV::Boolean(val, _def) => table[key] = json!(val),
            CV::Integer(val, _def) => table[key] = json!(val),
            CV::String(val, _def) => table[key] = json!(val),
            CV::List(vals, _def) => {
                let jvals: Vec<_> = vals.into_iter().map(|(val, _def)| json!(val)).collect();
                table[key] = json!(jvals);
            }
            CV::Table(val, _def) => {
                table
                    .as_object_mut()
                    .unwrap()
                    .insert(key.to_string(), json!({}));
                let inner_table = &mut table[&key];
                for (t_key, t_cv) in val {
                    json_add(inner_table, t_key, t_cv);
                }
            }
        }
    }
}

fn print_toml_unmerged(config: &Config, opts: &GetOptions<'_>, key: &ConfigKey) -> CargoResult<()> {
    let print_table = |cv: &CV| {
        drop_println!(config, "# {}", cv.definition());
        print_toml(config, opts, &ConfigKey::new(), cv);
        drop_println!(config, "");
    };
    // This removes entries from the given CV so that all that remains is the
    // given key. Returns false if no entries were found.
    fn trim_cv(mut cv: &mut CV, key: &ConfigKey) -> CargoResult<bool> {
        for (i, part) in key.parts().enumerate() {
            match cv {
                CV::Table(map, _def) => {
                    map.retain(|key, _value| key == part);
                    match map.get_mut(part) {
                        Some(val) => cv = val,
                        None => return Ok(false),
                    }
                }
                _ => {
                    let mut key_so_far = ConfigKey::new();
                    for part in key.parts().take(i) {
                        key_so_far.push(part);
                    }
                    bail!(
                        "expected table for configuration key `{}`, \
                         but found {} in {}",
                        key_so_far,
                        cv.desc(),
                        cv.definition()
                    )
                }
            }
        }
        Ok(match cv {
            CV::Table(map, _def) => !map.is_empty(),
            _ => true,
        })
    }

    let mut cli_args = config.cli_args_as_table()?;
    if trim_cv(&mut cli_args, key)? {
        print_table(&cli_args);
    }

    // This slurps up some extra env vars that aren't technically part of the
    // "config" (or are special-cased). I'm personally fine with just keeping
    // them here, though it might be confusing. The vars I'm aware of:
    //
    // * CARGO
    // * CARGO_HOME
    // * CARGO_NAME
    // * CARGO_EMAIL
    // * CARGO_INCREMENTAL
    // * CARGO_TARGET_DIR
    // * CARGO_CACHE_RUSTC_INFO
    //
    // All of these except CARGO, CARGO_HOME, and CARGO_CACHE_RUSTC_INFO are
    // actually part of the config, but they are special-cased in the code.
    //
    // TODO: It might be a good idea to teach the Config loader to support
    // environment variable aliases so that these special cases are less
    // special, and will just naturally get loaded as part of the config.
    let mut env: Vec<_> = config
        .env()
        .iter()
        .filter(|(env_key, _val)| env_key.starts_with(key.as_env_key()))
        .collect();
    if !env.is_empty() {
        env.sort_by_key(|x| x.0);
        drop_println!(config, "# Environment variables");
        for (key, value) in env {
            // Displaying this in "shell" syntax instead of TOML, since that
            // somehow makes more sense to me.
            let val = shell_escape::escape(Cow::Borrowed(value));
            drop_println!(config, "# {}={}", key, val);
        }
        drop_println!(config, "");
    }

    let unmerged = config.load_values_unmerged()?;
    for mut cv in unmerged {
        if trim_cv(&mut cv, key)? {
            print_table(&cv);
        }
    }
    Ok(())
}
<commit_msg>Remove duplicate code.<commit_after>//! Implementation of `cargo config` subcommand.

use crate::drop_println;
use crate::util::config::{Config, ConfigKey, ConfigValue as CV, Definition};
use crate::util::errors::CargoResult;
use anyhow::{bail, format_err, Error};
use serde_json::json;
use std::borrow::Cow;
use std::fmt;
use std::str::FromStr;

pub enum ConfigFormat {
    Toml,
    Json,
    JsonValue,
}

impl ConfigFormat {
    /// For clap.
    pub const POSSIBLE_VALUES: &'static [&'static str] = &["toml", "json", "json-value"];
}

impl FromStr for ConfigFormat {
    type Err = Error;
    fn from_str(s: &str) -> CargoResult<Self> {
        match s {
            "toml" => Ok(ConfigFormat::Toml),
            "json" => Ok(ConfigFormat::Json),
            "json-value" => Ok(ConfigFormat::JsonValue),
            f => bail!("unknown config format `{}`", f),
        }
    }
}

impl fmt::Display for ConfigFormat {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            ConfigFormat::Toml => write!(f, "toml"),
            ConfigFormat::Json => write!(f, "json"),
            ConfigFormat::JsonValue => write!(f, "json-value"),
        }
    }
}

/// Options for `cargo config get`.
pub struct GetOptions<'a> {
    pub key: Option<&'a str>,
    pub format: ConfigFormat,
    pub show_origin: bool,
    pub merged: bool,
}

pub fn get(config: &Config, opts: &GetOptions<'_>) -> CargoResult<()> {
    if opts.show_origin {
        if !matches!(opts.format, ConfigFormat::Toml) {
            bail!(
                "the `{}` format does not support --show-origin, try the `toml` format instead",
                opts.format
            );
        }
    }
    let key = match opts.key {
        Some(key) => ConfigKey::from_str(key),
        None => ConfigKey::new(),
    };
    if opts.merged {
        let cv = config
            .get_cv_with_env(&key)?
            .ok_or_else(|| format_err!("config value `{}` is not set", key))?;
        match opts.format {
            ConfigFormat::Toml => {
                print_toml(config, opts, &key, &cv);
                if let Some(env) = maybe_env(config, &key, &cv) {
                    print_toml_env(config, &env);
                }
            }
            ConfigFormat::Json => print_json(config, &key, &cv, true),
            ConfigFormat::JsonValue => print_json(config, &key, &cv, false),
        }
    } else {
        match &opts.format {
            ConfigFormat::Toml => print_toml_unmerged(config, opts, &key)?,
            format => bail!(
                "the `{}` format does not support --merged=no, try the `toml` format instead",
                format
            ),
        }
    }
    Ok(())
}

/// Checks for environment variables that might be used.
fn maybe_env<'config>(
    config: &'config Config,
    key: &ConfigKey,
    cv: &CV,
) -> Option<Vec<(&'config String, &'config String)>> {
    // Only fetching a table is unable to load env values. Leaf entries should
    // work properly.
    match cv {
        CV::Table(_map, _def) => {}
        _ => return None,
    }
    let mut env: Vec<_> = config
        .env()
        .iter()
        .filter(|(env_key, _val)| env_key.starts_with(&format!("{}_", key.as_env_key())))
        .collect();
    env.sort_by_key(|x| x.0);
    if env.is_empty() {
        None
    } else {
        Some(env)
    }
}

fn print_toml(config: &Config, opts: &GetOptions<'_>, key: &ConfigKey, cv: &CV) {
    let origin = |def: &Definition| -> String {
        if !opts.show_origin {
            return "".to_string();
        }
        format!(" # {}", def)
    };
    match cv {
        CV::Boolean(val, def) => drop_println!(config, "{} = {}{}", key, val, origin(&def)),
        CV::Integer(val, def) => drop_println!(config, "{} = {}{}", key, val, origin(&def)),
        CV::String(val, def) => drop_println!(
            config,
            "{} = {}{}",
            key,
            toml::to_string(&val).unwrap(),
            origin(&def)
        ),
        CV::List(vals, _def) => {
            if opts.show_origin {
                drop_println!(config, "{} = [", key);
                for (val, def) in vals {
                    drop_println!(config, "    {}, # {}", toml::to_string(&val).unwrap(), def);
                }
                drop_println!(config, "]");
            } else {
                let vals: Vec<&String> = vals.iter().map(|x| &x.0).collect();
                drop_println!(config, "{} = {}", key, toml::to_string(&vals).unwrap());
            }
        }
        CV::Table(table, _def) => {
            let mut key_vals: Vec<_> = table.into_iter().collect();
            key_vals.sort_by(|a, b| a.0.cmp(&b.0));
            for (table_key, val) in key_vals {
                let mut subkey = key.clone();
                // push or push_sensitive shouldn't matter here, since this is
                // not dealing with environment variables.
                subkey.push(&table_key);
                print_toml(config, opts, &subkey, val);
            }
        }
    }
}

fn print_toml_env(config: &Config, env: &[(&String, &String)]) {
    drop_println!(
        config,
        "# The following environment variables may affect the loaded values."
    );
    for (env_key, env_value) in env {
        let val = shell_escape::escape(Cow::Borrowed(env_value));
        drop_println!(config, "# {}={}", env_key, val);
    }
}

fn print_json(config: &Config, key: &ConfigKey, cv: &CV, include_key: bool) {
    let json_value = if key.is_root() || !include_key {
        cv_to_json(cv)
    } else {
        let mut parts: Vec<_> = key.parts().collect();
        let last_part = parts.pop().unwrap();
        let mut root_table = json!({});
        // Create a JSON object with nested keys up to the value being displayed.
        let mut table = &mut root_table;
        for part in parts {
            table[part] = json!({});
            table = table.get_mut(part).unwrap();
        }
        table[last_part] = cv_to_json(cv);
        root_table
    };
    drop_println!(config, "{}", serde_json::to_string(&json_value).unwrap());

    // Helper for recursively converting a CV to JSON.
    fn cv_to_json(cv: &CV) -> serde_json::Value {
        match cv {
            CV::Boolean(val, _def) => json!(val),
            CV::Integer(val, _def) => json!(val),
            CV::String(val, _def) => json!(val),
            CV::List(vals, _def) => {
                let jvals: Vec<_> = vals.into_iter().map(|(val, _def)| json!(val)).collect();
                json!(jvals)
            }
            CV::Table(map, _def) => {
                let mut table = json!({});
                for (key, val) in map {
                    table[key] = cv_to_json(val);
                }
                table
            }
        }
    }
}

fn print_toml_unmerged(config: &Config, opts: &GetOptions<'_>, key: &ConfigKey) -> CargoResult<()> {
    let print_table = |cv: &CV| {
        drop_println!(config, "# {}", cv.definition());
        print_toml(config, opts, &ConfigKey::new(), cv);
        drop_println!(config, "");
    };
    // This removes entries from the given CV so that all that remains is the
    // given key. Returns false if no entries were found.
    fn trim_cv(mut cv: &mut CV, key: &ConfigKey) -> CargoResult<bool> {
        for (i, part) in key.parts().enumerate() {
            match cv {
                CV::Table(map, _def) => {
                    map.retain(|key, _value| key == part);
                    match map.get_mut(part) {
                        Some(val) => cv = val,
                        None => return Ok(false),
                    }
                }
                _ => {
                    let mut key_so_far = ConfigKey::new();
                    for part in key.parts().take(i) {
                        key_so_far.push(part);
                    }
                    bail!(
                        "expected table for configuration key `{}`, \
                         but found {} in {}",
                        key_so_far,
                        cv.desc(),
                        cv.definition()
                    )
                }
            }
        }
        Ok(match cv {
            CV::Table(map, _def) => !map.is_empty(),
            _ => true,
        })
    }

    let mut cli_args = config.cli_args_as_table()?;
    if trim_cv(&mut cli_args, key)? {
        print_table(&cli_args);
    }

    // This slurps up some extra env vars that aren't technically part of the
    // "config" (or are special-cased). I'm personally fine with just keeping
    // them here, though it might be confusing. The vars I'm aware of:
    //
    // * CARGO
    // * CARGO_HOME
    // * CARGO_NAME
    // * CARGO_EMAIL
    // * CARGO_INCREMENTAL
    // * CARGO_TARGET_DIR
    // * CARGO_CACHE_RUSTC_INFO
    //
    // All of these except CARGO, CARGO_HOME, and CARGO_CACHE_RUSTC_INFO are
    // actually part of the config, but they are special-cased in the code.
    //
    // TODO: It might be a good idea to teach the Config loader to support
    // environment variable aliases so that these special cases are less
    // special, and will just naturally get loaded as part of the config.
    let mut env: Vec<_> = config
        .env()
        .iter()
        .filter(|(env_key, _val)| env_key.starts_with(key.as_env_key()))
        .collect();
    if !env.is_empty() {
        env.sort_by_key(|x| x.0);
        drop_println!(config, "# Environment variables");
        for (key, value) in env {
            // Displaying this in "shell" syntax instead of TOML, since that
            // somehow makes more sense to me.
            let val = shell_escape::escape(Cow::Borrowed(value));
            drop_println!(config, "# {}={}", key, val);
        }
        drop_println!(config, "");
    }

    let unmerged = config.load_values_unmerged()?;
    for mut cv in unmerged {
        if trim_cv(&mut cv, key)? {
            print_table(&cv);
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before><commit_msg>Auto merge of #9616 - danieleades:refactor/unnecessary-collect, r=alexcrichton<commit_after><|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

//! Tidy check to ensure that there are no binaries checked into the source tree
//! by accident.
//!
//! In the past we've accidentally checked in test binaries and such which add a
//! huge amount of bloat to the git history, so it's good to just ensure we
//! don't do that again :)

use std::path::Path;

// All files are executable on Windows, so just check on Unix
#[cfg(windows)]
pub fn check(_path: &Path, _bad: &mut bool) {}

#[cfg(unix)]
pub fn check(path: &Path, bad: &mut bool) {
    use std::fs;
    use std::process::{Command, Stdio};
    use std::os::unix::prelude::*;

    super::walk(path,
                &mut |path| super::filter_dirs(path) || path.ends_with("src/etc"),
                &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        let extensions = [".py", ".sh"];
        if extensions.iter().any(|e| filename.ends_with(e)) {
            return
        }

        let metadata = t!(fs::symlink_metadata(&file), &file);
        if metadata.mode() & 0o111 != 0 {
            let rel_path = file.strip_prefix(path).unwrap();
            let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/");
            let ret_code = Command::new("git")
                                        .arg("ls-files")
                                        .arg(&git_friendly_path)
                                        .current_dir(path)
                                        .stdout(Stdio::null())
                                        .stderr(Stdio::null())
                                        .status()
                                        .unwrap_or_else(|e| {
                                            panic!("could not run git ls-files: {}", e);
                                        });
            if ret_code.success() {
                println!("binary checked into source: {}", file.display());
                *bad = true;
            }
        }
    })
}

<commit_msg>Auto merge of #36709 - Mark-Simulacrum:fix-wsl-tidy, r=Aatch<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// 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. This file may not be copied, modified, or distributed
// except according to those terms.

//! Tidy check to ensure that there are no binaries checked into the source tree
//! by accident.
//!
//! In the past we've accidentally checked in test binaries and such which add a
//! huge amount of bloat to the git history, so it's good to just ensure we
//! don't do that again :)

use std::path::Path;

// All files are executable on Windows, so just check on Unix
#[cfg(windows)]
pub fn check(_path: &Path, _bad: &mut bool) {}

#[cfg(unix)]
pub fn check(path: &Path, bad: &mut bool) {
    use std::fs;
    use std::io::Read;
    use std::process::{Command, Stdio};
    use std::os::unix::prelude::*;

    if let Ok(mut file) = fs::File::open("/proc/version") {
        let mut contents = String::new();
        file.read_to_string(&mut contents).unwrap();
        // Probably on Windows Linux Subsystem, all files will be marked as
        // executable, so skip checking.
        if contents.contains("Microsoft") {
            return;
        }
    }

    super::walk(path,
                &mut |path| super::filter_dirs(path) || path.ends_with("src/etc"),
                &mut |file| {
        let filename = file.file_name().unwrap().to_string_lossy();
        let extensions = [".py", ".sh"];
        if extensions.iter().any(|e| filename.ends_with(e)) {
            return
        }

        let metadata = t!(fs::symlink_metadata(&file), &file);
        if metadata.mode() & 0o111 != 0 {
            let rel_path = file.strip_prefix(path).unwrap();
            let git_friendly_path = rel_path.to_str().unwrap().replace("\\", "/");
            let ret_code = Command::new("git")
                                        .arg("ls-files")
                                        .arg(&git_friendly_path)
                                        .current_dir(path)
                                        .stdout(Stdio::null())
                                        .stderr(Stdio::null())
                                        .status()
                                        .unwrap_or_else(|e| {
                                            panic!("could not run git ls-files: {}", e);
                                        });
            if ret_code.success() {
                println!("binary checked into source: {}", file.display());
                *bad = true;
            }
        }
    })
}

<|endoftext|>


<commit_before><commit_msg>Tighten up the encapsulation in ShaderGlsl<commit_after><|endoftext|>


<commit_before><commit_msg>rust plugin sketch<commit_after>extern crate libloading as lib;

use super::probe::Probe;
use ::logging::{Logger};
use logging::logger::syslog::Severity;

#[derive(Debug)]
pub struct RustPlugin {
    logger: Logger
}

impl RustPlugin {
    pub fn new(logger: Logger) -> RustPlugin {
        let mem = RustPlugin { logger: logger };
        mem.register_probe();
        mem
    }
}

fn call_dynamic() -> lib::Result<String> {
    let lib = try!(lib::Library::new("/tmp/librustexampleplugin.so"));
    unsafe {
        let func: lib::Symbol<unsafe extern fn() -> String> = try!(lib.get(b"run_probe"));
        Ok(func())
    }
}

impl Probe for RustPlugin {
    fn exec(&self) -> () {
        match call_dynamic() {
            Ok(json_str) => {
                let msg = format!("@Thread: {} - json_string: {}",
                                  self.get_thread_id(),
                                  json_str
                );
                self.logger.log(Severity::LOG_INFO, &msg);
            }

            Err(err) => {
                let msg = format!("{:?}", err);
                self.logger.log(Severity::LOG_ERR, &msg);
            }
        }
    }

    fn get_logger(&self) -> &Logger {
        &self.logger
    }
}<|endoftext|>


<commit_before>// Tuples can be used as function arguments and as return values
fn reverse(pair: (i32, bool)) -> (bool, i32) {
    // `let` can be used to bind the members of a tuple to variables
    let (integer, boolean) = pair;

    (boolean, integer)
}

fn main() {
    // A tuple with a bunch of different types
    let long_tuple = (1u8, 2u16, 3u32, 4u64,
                      -1i8, -2i16, -3i32, -4i64,
                      0.1f32, 0.2f64,
                      'a', true);

    // Values can be extracted from the tuple using tuple indexing
    println!("long tuple first value: {}", long_tuple.0);
    println!("long tuple second value: {}", long_tuple.1);

    // Tuples can be tuple members
    let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);

    // Tuples are printable
    println!("tuple of tuples: {:?}", tuple_of_tuples);

    let pair = (1, true);
    println!("pair is {:?}", pair);

    println!("the reversed pair is {:?}", reverse(pair));

    // To create one element tuples, the comma is required to tell them apart
    // from a literal surrounded by parentheses
    println!("one element tuple: {:?}", (5u32,));
    println!("just an integer: {:?}", (5u32));
}
<commit_msg>Added tuple destruct<commit_after>// Tuples can be used as function arguments and as return values
fn reverse(pair: (i32, bool)) -> (bool, i32) {
    // `let` can be used to bind the members of a tuple to variables
    let (integer, boolean) = pair;

    (boolean, integer)
}

fn main() {
    // A tuple with a bunch of different types
    let long_tuple = (1u8, 2u16, 3u32, 4u64,
                      -1i8, -2i16, -3i32, -4i64,
                      0.1f32, 0.2f64,
                      'a', true);

    // Values can be extracted from the tuple using tuple indexing
    println!("long tuple first value: {}", long_tuple.0);
    println!("long tuple second value: {}", long_tuple.1);

    // Tuples can be tuple members
    let tuple_of_tuples = ((1u8, 2u16, 2u32), (4u64, -1i8), -2i16);

    // Tuples are printable
    println!("tuple of tuples: {:?}", tuple_of_tuples);

    let pair = (1, true);
    println!("pair is {:?}", pair);

    println!("the reversed pair is {:?}", reverse(pair));

    // To create one element tuples, the comma is required to tell them apart
    // from a literal surrounded by parentheses
    println!("one element tuple: {:?}", (5u32,));
    println!("just an integer: {:?}", (5u32));

    //tuples can be destructured to create bindings
    let tuple = (1, "hello", 4.5, true);

    let (a, b, c, d) = tuple;
    println!("{:?}, {:?}, {:?}, {:?}", a, b, c, d);
}
<|endoftext|>


<commit_before><commit_msg>Expose a single function in codegen to docs build.<commit_after><|endoftext|>


<commit_before>struct Book {
    author: ~str,
    title: ~str,
    year: uint,
}

// & means a reference to a Book, no ownership is taken
fn borrow_book(book: &Book) {
    println!("I borrowed {} {} edition", book.title, book.year);
}

// &mut means a mutable reference, meaning the fields of the struct can be
// modified
fn new_edition(book: &mut Book) {
    book.year = 2014;
}

fn main() {
    // an immutable Book
    let geb = Book {
        author: ~"Douglas Hofstadter",
        title: ~"Gödel, Escher, Bach",
        year: 1979,
    };

    // borrow geb, geb can still be used afterwards
    borrow_book(&geb);

    // geb can be borrowed again, and again, and again ...
    borrow_book(&geb);

    // a mutable Book
    let mut mutable_geb = Book {
        author: ~"Douglas Hofstadter",
        title: ~"Gödel, Escher, Bach",
        year: 1979,
    };

    // Error: can't borrow immutable object as mutable
    //new_edition(&mut geb);

    // Ok: borrow a mutable object as mutable
    new_edition(&mut mutable_geb);

    // Ok: mutable objects can be immutably borrowed
    borrow_book(&mutable_geb);

    // when an object is mutably borrowed, the original can't be used
    // until the end of the borrowed copy's lifetime
    if true {
        let borrowed_geb = &mut mutable_geb;

        // Error: mutable_geb has been mutably borrowed.
        //println!("Can no longer access {}", mutable_geb.title);

        println!("The borrowed copy of {} is available", borrowed_geb.title);
 	    // now borrowed_geb goes out of scope
    }
    println!("Once again, I can access {}", mutable_geb.title);

    // immutable borrows place no restrictions on the original owner
    if true {
        let borrowed_geb = &mutable_geb;
        println!("The original is still accessible: {}", mutable_geb.title);
        println!("and so is the borrowed copy: {}", borrowed_geb.title);
    }

    // ref can be used to take references when destructuring
    // Here geb_title and geb_author are references to ~str, i.e. &~str
    // geb_year is a copy of the year field
    let Book {
        author: ref geb_author,
        title: ref geb_title,
        year: geb_year
    } = geb;
}
<commit_msg>Updated wording and formatting as requested.<commit_after>struct Book {
    author: ~str,
    title: ~str,
    year: uint,
}

// & means a reference to a Book, no ownership is taken
fn borrow_book(book: &Book) {
    println!("I borrowed {} {} edition", book.title, book.year);
}

// &mut means a mutable reference, meaning the fields of the struct can be
// modified
fn new_edition(book: &mut Book) {
    book.year = 2014;
}

fn main() {
    // an immutable Book
    let geb = Book {
        author: ~"Douglas Hofstadter",
        title: ~"Gödel, Escher, Bach",
        year: 1979,
    };

    // borrow geb, geb can still be used afterwards
    borrow_book(&geb);

    // geb can be borrowed again, and again, and again ...
    borrow_book(&geb);

    // a mutable Book
    let mut mutable_geb = Book {
        author: ~"Douglas Hofstadter",
        title: ~"Gödel, Escher, Bach",
        year: 1979,
    };

    // Error: can't borrow immutable object as mutable
    //new_edition(&mut geb);

    // Ok: borrow a mutable object as mutable
    new_edition(&mut mutable_geb);

    // Ok: mutable objects can be immutably borrowed
    borrow_book(&mutable_geb);

    // when an object is mutably borrowed, the original can't be used
    // until its mutable reference goes out of scope.
    if true {
        let borrowed_geb = &mut mutable_geb;

        // Error: mutable_geb has been mutably borrowed.
        //println!("Can no longer access {}", mutable_geb.title);

        println!("The mutable reference of {} is available",
                 borrowed_geb.title);
        // now borrowed_geb goes out of scope
    }
    println!("Once again, I can access {}", mutable_geb.title);

    // immutable borrows place no restrictions on the original owner
    if true {
        let borrowed_geb = &mutable_geb;
        println!("The original is still accessible: {}",
                 mutable_geb.title);
        println!("and so is the mutable reference: {}",
                 borrowed_geb.title);
    }

    // ref can be used to take references when destructuring
    // Here geb_title and geb_author are references to ~str, i.e. &~str
    // geb_year is a copy of the year field
    let Book {
        author: ref geb_author,
        title: ref geb_title,
        year: geb_year
    } = geb;
}
<|endoftext|>


<commit_before><commit_msg>Adding the chapter about closures.<commit_after><|endoftext|>


<commit_before>#![allow(dead_code)]
extern crate rusoto;
extern crate xml;
extern crate time;
extern crate regex;
extern crate rustc_serialize;
use rusoto::credentials::*;
use rusoto::error::*;
use rusoto::sqs::*;
use time::*;

fn main() {
	let mut provider = DefaultAWSCredentialsProviderChain::new();
	let creds = provider.get_credentials();

	// println!("Creds in main: {}, {}, {}.", creds.get_aws_secret_key(), creds.get_aws_secret_key(),
	// 	creds.get_token());

	match sqs_roundtrip_tests(&creds) {
		Ok(_) => { println!("Everything worked."); },
		Err(err) => { println!("Got error: {:#?}", err); }
	}
}

fn sqs_roundtrip_tests(creds: &AWSCredentials) -> Result<(), AWSError> {
	let sqs = SQSHelper::new(&creds, "us-east-1");

	// list existing queues
	let response = try!(sqs.list_queues());
	for q in response.queue_urls {
		println!("Existing queue: {}", q);
	}

	// create a new queue
	let q_name = &format!("test_q_{}", get_time().sec);
	let response = try!(sqs.create_queue(q_name));
	println!("Created queue {} with url {}", q_name, response.queue_url);

	// query it by name
	let response = try!(sqs.get_queue_url(q_name));
	let queue_url = &response.queue_url;
	println!("Verified queue url {} for queue name {}", queue_url, q_name);

	// send it a message
	let msg_str = "lorem ipsum dolor sit amet";
	let response = try!(sqs.send_message(queue_url, msg_str));
	println!("Send message with body '{}' and created message_id {}", msg_str, response.message_id);

	// receive a message
	let response = try!(sqs.receive_message(queue_url));
	for msg in response.messages {
		println!("Received message '{}' with id {}", msg.body, msg.message_id);
		try!(sqs.delete_message(queue_url, &msg.receipt_handle));
	}

	// delete the queue
	try!(sqs.delete_queue(queue_url));
	println!("Queue {} deleted", queue_url);

	Ok(())
}
<commit_msg>Switches example code to directly use get_credentials instead of storing them and reusing later.<commit_after>#![allow(dead_code)]
extern crate rusoto;
extern crate xml;
extern crate time;
extern crate regex;
extern crate rustc_serialize;
use rusoto::credentials::*;
use rusoto::error::*;
use rusoto::sqs::*;
use time::*;

fn main() {
	let mut provider = DefaultAWSCredentialsProviderChain::new();

	// println!("Creds in main: {}, {}, {}.", creds.get_aws_secret_key(), creds.get_aws_secret_key(),
	// 	creds.get_token());

	match sqs_roundtrip_tests(&provider.get_credentials()) {
		Ok(_) => { println!("Everything worked."); },
		Err(err) => { println!("Got error: {:#?}", err); }
	}
}

fn sqs_roundtrip_tests(creds: &AWSCredentials) -> Result<(), AWSError> {
	let sqs = SQSHelper::new(&creds, "us-east-1");

	// list existing queues
	let response = try!(sqs.list_queues());
	for q in response.queue_urls {
		println!("Existing queue: {}", q);
	}

	// create a new queue
	let q_name = &format!("test_q_{}", get_time().sec);
	let response = try!(sqs.create_queue(q_name));
	println!("Created queue {} with url {}", q_name, response.queue_url);

	// query it by name
	let response = try!(sqs.get_queue_url(q_name));
	let queue_url = &response.queue_url;
	println!("Verified queue url {} for queue name {}", queue_url, q_name);

	// send it a message
	let msg_str = "lorem ipsum dolor sit amet";
	let response = try!(sqs.send_message(queue_url, msg_str));
	println!("Send message with body '{}' and created message_id {}", msg_str, response.message_id);

	// receive a message
	let response = try!(sqs.receive_message(queue_url));
	for msg in response.messages {
		println!("Received message '{}' with id {}", msg.body, msg.message_id);
		try!(sqs.delete_message(queue_url, &msg.receipt_handle));
	}

	// delete the queue
	try!(sqs.delete_queue(queue_url));
	println!("Queue {} deleted", queue_url);

	Ok(())
}
<|endoftext|>


<commit_before>use redox::*;

pub struct Editor {
    url: String,
    file: Option<File>,
    string: String,
    offset: usize,
    scroll_x: isize,
    scroll_y: isize,
}

impl Editor {
    #[inline(never)]
    pub fn new() -> Self {
        Editor {
            url: String::new(),
            file: Option::None,
            string: String::new(),
            offset: 0,
            scroll_x: 0,
            scroll_y: 0,
        }
    }

    fn reload(&mut self, window: &mut Window) {
        window.set_title(&format!("{}{}{}","Editor (", &self.url, ")"));
        self.offset = 0;
        self.scroll_x = 0;
        self.scroll_y = 0;

        match self.file {
            Option::Some(ref mut file) => {
                file.seek(Seek::Start(0));
                let mut vec: Vec<u8> = Vec::new();
                file.read_to_end(&mut vec);
                self.string = unsafe { String::from_utf8_unchecked(vec) };
            }
            Option::None => self.string = String::new(),
        }
    }

    fn save(&mut self, window: &mut Window) {
        match self.file {
            Option::Some(ref mut file) => {
                window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Saved"));
                file.seek(Seek::Start(0));
                file.write(&self.string.as_bytes());
                file.sync();
            }
            Option::None => {
                //TODO: Ask for file to save to
                window.set_title(&format!("{}{}{}","Editor (", &self.url, ") No Open File"));
            }
        }
    }

    fn draw_content(&mut self, window: &mut Window) {
        let mut redraw = false;

        {
            window.set([0, 0, 0, 196]);

            let scroll_x = self.scroll_x;
            let scroll_y = self.scroll_y;

            let mut offset = 0;

            let mut col = -scroll_x;
            let cols = window.width() as isize / 8;

            let mut row = -scroll_y;
            let rows = window.height() as isize / 16;

            for c in self.string.chars() {
                if offset == self.offset {
                    if col >= 0 && col < cols && row >= 0 && row < rows {
                        window.char(8 * col, 16 * row, '_', [128, 128, 128, 255]);
                    } else {
                        if col < 0 { //Too far to the left
                            self.scroll_x += col;
                        } else if col >= cols { //Too far to the right
                            self.scroll_x += cols - col + 1;
                        }
                        if row < 0 { //Too far up
                            self.scroll_y += row;
                        } else if row >= rows { //Too far down
                            self.scroll_y += rows - row + 1;
                        }

                        redraw = true;
                    }
                }

                if c == '\n' {
                    col = -scroll_x;
                    row += 1;
                } else if c == '\t' {
                    col += 8 - col % 8;
                } else {
                    if col >= 0 && col < cols && row >= 0 && row < rows {
                        window.char(8 * col, 16 * row, c, [255, 255, 255, 255]);
                    }
                    col += 1;
                }

                offset += 1;
            }

            if offset == self.offset {
                if col >= 0 && col < cols && row >= 0 && row < rows {
                    window.char(8 * col, 16 * row, '_', [128, 128, 128, 255]);
                } else {
                    if col < 0 { //Too far to the left
                        self.scroll_x += col;
                    } else if col >= cols { //Too far to the right
                        self.scroll_x += cols - col + 1;
                    }
                    if row < 0 { //Too far up
                        self.scroll_y += row;
                    } else if row >= rows { //Too far down
                        self.scroll_y += rows - row + 1;
                    }

                    redraw = true;
                }
            }

            window.sync();
        }

        if redraw {
            self.draw_content(window);
        }
    }

    fn main(&mut self, url: &str) {
        let mut window = Window::new((rand() % 400 + 50) as isize,
                                    (rand() % 300 + 50) as isize,
                                    576,
                                    400,
                                     "Editor (Loading)");

        self.url = url.to_string();
        self.file = Option::Some(File::open(&self.url));

        self.reload(&mut window);
        self.draw_content(&mut window);

        while let Option::Some(event) = window.poll() {
            match event.to_option() {
                EventOption::Key(key_event) => {
                    if key_event.pressed {
                        match key_event.scancode {
                            K_ESC => break,
                            K_BKSP => if self.offset > 0 {
                                window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
                                self.string = self.string[0 .. self.offset - 1].to_string() +
                                              &self.string[self.offset .. self.string.len()];
                                self.offset -= 1;
                            },
                            K_DEL => if self.offset < self.string.len() {
                                window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
                                self.string = self.string[0 .. self.offset].to_string() +
                                              &self.string[self.offset + 1 .. self.string.len() - 1];
                            },
                            K_F5 => self.reload(&mut window),
                            K_F6 => self.save(&mut window),
                            K_HOME => self.offset = 0,
                            K_UP => {
                                let mut new_offset = 0;
                                for i in 2..self.offset {
                                    match self.string.as_bytes()[self.offset - i] {
                                        0 => break,
                                        10 => {
                                            new_offset = self.offset - i + 1;
                                            break;
                                        }
                                        _ => (),
                                    }
                                }
                                self.offset = new_offset;
                            }
                            K_LEFT => if self.offset > 0 {
                                self.offset -= 1;
                            },
                            K_RIGHT => if self.offset < self.string.len() {
                                self.offset += 1;
                            },
                            K_END => self.offset = self.string.len(),
                            K_DOWN => {
                                let mut new_offset = self.string.len();
                                for i in self.offset..self.string.len() {
                                    match self.string.as_bytes()[i] {
                                        0 => break,
                                        10 => {
                                            new_offset = i + 1;
                                            break;
                                        }
                                        _ => (),
                                    }
                                }
                                self.offset = new_offset;
                            }
                            _ => match key_event.character {
                                '\0' => (),
                                _ => {
                                    window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
                                    self.string = self.string[0 .. self.offset].to_string() +
                                                  &key_event.character.to_string() +
                                                  &self.string[self.offset .. self.string.len()];
                                    self.offset += 1;
                                }
                            },
                        }

                        self.draw_content(&mut window);
                    }
                }
                _ => (),
            }
        }
    }
}

pub fn main() {
    match args().get(1) {
        Option::Some(arg) => Editor::new().main(&arg),
        Option::None => Editor::new().main("none://"),
    }
}
<commit_msg>Formatize more `&str.to_string` concats<commit_after>use redox::*;

pub struct Editor {
    url: String,
    file: Option<File>,
    string: String,
    offset: usize,
    scroll_x: isize,
    scroll_y: isize,
}

impl Editor {
    #[inline(never)]
    pub fn new() -> Self {
        Editor {
            url: String::new(),
            file: Option::None,
            string: String::new(),
            offset: 0,
            scroll_x: 0,
            scroll_y: 0,
        }
    }

    fn reload(&mut self, window: &mut Window) {
        window.set_title(&format!("{}{}{}","Editor (", &self.url, ")"));
        self.offset = 0;
        self.scroll_x = 0;
        self.scroll_y = 0;

        match self.file {
            Option::Some(ref mut file) => {
                file.seek(Seek::Start(0));
                let mut vec: Vec<u8> = Vec::new();
                file.read_to_end(&mut vec);
                self.string = unsafe { String::from_utf8_unchecked(vec) };
            }
            Option::None => self.string = String::new(),
        }
    }

    fn save(&mut self, window: &mut Window) {
        match self.file {
            Option::Some(ref mut file) => {
                window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Saved"));
                file.seek(Seek::Start(0));
                file.write(&self.string.as_bytes());
                file.sync();
            }
            Option::None => {
                //TODO: Ask for file to save to
                window.set_title(&format!("{}{}{}","Editor (", &self.url, ") No Open File"));
            }
        }
    }

    fn draw_content(&mut self, window: &mut Window) {
        let mut redraw = false;

        {
            window.set([0, 0, 0, 196]);

            let scroll_x = self.scroll_x;
            let scroll_y = self.scroll_y;

            let mut offset = 0;

            let mut col = -scroll_x;
            let cols = window.width() as isize / 8;

            let mut row = -scroll_y;
            let rows = window.height() as isize / 16;

            for c in self.string.chars() {
                if offset == self.offset {
                    if col >= 0 && col < cols && row >= 0 && row < rows {
                        window.char(8 * col, 16 * row, '_', [128, 128, 128, 255]);
                    } else {
                        if col < 0 { //Too far to the left
                            self.scroll_x += col;
                        } else if col >= cols { //Too far to the right
                            self.scroll_x += cols - col + 1;
                        }
                        if row < 0 { //Too far up
                            self.scroll_y += row;
                        } else if row >= rows { //Too far down
                            self.scroll_y += rows - row + 1;
                        }

                        redraw = true;
                    }
                }

                if c == '\n' {
                    col = -scroll_x;
                    row += 1;
                } else if c == '\t' {
                    col += 8 - col % 8;
                } else {
                    if col >= 0 && col < cols && row >= 0 && row < rows {
                        window.char(8 * col, 16 * row, c, [255, 255, 255, 255]);
                    }
                    col += 1;
                }

                offset += 1;
            }

            if offset == self.offset {
                if col >= 0 && col < cols && row >= 0 && row < rows {
                    window.char(8 * col, 16 * row, '_', [128, 128, 128, 255]);
                } else {
                    if col < 0 { //Too far to the left
                        self.scroll_x += col;
                    } else if col >= cols { //Too far to the right
                        self.scroll_x += cols - col + 1;
                    }
                    if row < 0 { //Too far up
                        self.scroll_y += row;
                    } else if row >= rows { //Too far down
                        self.scroll_y += rows - row + 1;
                    }

                    redraw = true;
                }
            }

            window.sync();
        }

        if redraw {
            self.draw_content(window);
        }
    }

    fn main(&mut self, url: &str) {
        let mut window = Window::new((rand() % 400 + 50) as isize,
                                     (rand() % 300 + 50) as isize,
                                     576,
                                     400,
                                      "Editor (Loading)");

        self.url = url.to_string();
        self.file = Option::Some(File::open(&self.url));

        self.reload(&mut window);
        self.draw_content(&mut window);

        while let Option::Some(event) = window.poll() {
            match event.to_option() {
                EventOption::Key(key_event) => {
                    if key_event.pressed {
                        match key_event.scancode {
                            K_ESC => break,
                            K_BKSP => if self.offset > 0 {
                                window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
                                self.string = format!("{}{}",
                                                      &self.string[0 .. self.offset - 1],
                                                      &self.string[self.offset .. self.string.len()]);
                                self.offset -= 1;
                            },
                            K_DEL => if self.offset < self.string.len() {
                                window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
                                self.string = format!("{}{}",
                                                      &self.string[0 .. self.offset],
                                                      &self.string[self.offset + 1 .. self.string.len() - 1]);
                            },
                            K_F5 => self.reload(&mut window),
                            K_F6 => self.save(&mut window),
                            K_HOME => self.offset = 0,
                            K_UP => {
                                let mut new_offset = 0;
                                for i in 2..self.offset {
                                    match self.string.as_bytes()[self.offset - i] {
                                        0 => break,
                                        10 => {
                                            new_offset = self.offset - i + 1;
                                            break;
                                        }
                                        _ => (),
                                    }
                                }
                                self.offset = new_offset;
                            }
                            K_LEFT => if self.offset > 0 {
                                self.offset -= 1;
                            },
                            K_RIGHT => if self.offset < self.string.len() {
                                self.offset += 1;
                            },
                            K_END => self.offset = self.string.len(),
                            K_DOWN => {
                                let mut new_offset = self.string.len();
                                for i in self.offset..self.string.len() {
                                    match self.string.as_bytes()[i] {
                                        0 => break,
                                        10 => {
                                            new_offset = i + 1;
                                            break;
                                        }
                                        _ => (),
                                    }
                                }
                                self.offset = new_offset;
                            }
                            _ => match key_event.character {
                                '\0' => (),
                                _ => {
                                    window.set_title(&format!("{}{}{}","Editor (", &self.url, ") Changed"));
                                    self.string = format!("{}{}{}",
                                                          &self.string[0 .. self.offset],
                                                          key_event.character,
                                                          &self.string[self.offset .. self.string.len()]);
                                    self.offset += 1;
                                }
                            },
                        }

                        self.draw_content(&mut window);
                    }
                }
                _ => (),
            }
        }
    }
}

pub fn main() {
    match args().get(1) {
        Option::Some(arg) => Editor::new().main(&arg),
        Option::None => Editor::new().main("none://"),
    }
}
<|endoftext|>


<commit_before><commit_msg>Mark a non-exported function as static.<commit_after><|endoftext|>