<commit_before>use glium;
use cgm;

use Color;
use std::rc::Rc;
use glium::texture::Texture2d;

mod translate;
mod rotate;
mod combine;
mod image;
mod rect;
mod recolor;
mod mulcolor;

pub use self::translate::*;
pub use self::rotate::*;
pub use self::combine::*;
pub use self::image::*;
pub use self::rect::*;
pub use self::recolor::*;
pub use self::mulcolor::*;

/// Trait for structs to be drawn with `Frame::draw`
pub trait Shape: IntoIterator<Item = RendTri> {
    /// Combine shapes together so they become one shape.
    #[inline]
    fn combine<S: Shape>(self, rhs: S) -> Combine<Self, S> where Self: Sized {
        Combine(self, rhs)
    }

    /// Translate a shape using a `vector` which represents the direction and magnitude to translate it by.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5]).translate([0.1, 0.1]));
    /// ```
    #[inline]
    fn translate<V: Into<cgm::Vector2<f32>>>(&self, vector: V) -> Translate<Self> where Self: Clone {
        Translate::new(self.clone(), vector.into())
    }

    /// Rotate a shape using an angle in radians.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// use std::f32::consts::PI;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5]).rotate(PI));
    /// ```
    #[inline]
    fn rotate(&self, angle: f32) -> Rotate<Self> where Self: Clone {
        Rotate::new(self.clone(), angle)
    }

    /// Completely recolor a shape.
    ///
    /// This does not erase textures, just colors them. Calling recolor() will
    /// cause every component of the shape to change its color to the passed
    /// color and should not be used in most situations as it erases
    /// sub-component color information. This can be used to make
    /// silhouettes and some other effects, but is mostly not useful.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5]).recolor(Color::BLUE));
    /// ```
    #[inline]
    fn recolor<C: Into<Color>>(&self, color: C) -> Recolor<Self> where Self: Clone {
        Recolor::new(self.clone(), color.into())
    }

    /// Multiply all of the colors in the shape component-wise with
    /// the passed color. See `Color::multiply()`.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// // This will be drawn with Color([0.0, 0.0, 0.5, 1.0]).
    /// // It extracts only the blue and alpha components.
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5])
    ///    .recolor([0.5, 0.5, 0.5, 1.0])
    ///    .mul_color(Color::BLUE));
    /// ```
    #[inline]
    fn mul_color<C: Into<Color>>(&self, color: C) -> Mulcolor<Self> where Self: Clone {
        Mulcolor::new(self.clone(), color.into())
    }

    /// Multiply all of the colors in the shape component-wise with
    /// the passed color. See `Color::multiply()`.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// // This will be drawn with Color([0.25, 0.5, 0.5, 1.0]).
    /// // It extracts half of the color components.
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5])
    ///    .recolor([0.5, 1.0, 1.0, 1.0])
    ///    .scale_color(0.5));
    /// ```
    #[inline]
    fn scale_color(&self, scale: f32) -> Mulcolor<Self> where Self: Clone {
        Mulcolor::new(self.clone(), Color([scale, scale, scale, 1.0]))
    }

    /// Scales the transparrency/alpha value of the shape's color.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// // This will be drawn with Color([0.5, 1.0, 1.0, 0.5]).
    /// // It extracts half of the alpha component.
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5])
    ///    .recolor([0.5, 1.0, 1.0, 1.0])
    ///    .scale_alpha(0.5));
    /// ```
    #[inline]
    fn scale_alpha(&self, scale: f32) -> Mulcolor<Self> where Self: Clone {
        Mulcolor::new(self.clone(), Color([1.0, 1.0, 1.0, scale]))
    }
}

impl<S> Shape for S where S: IntoIterator<Item = RendTri> {}

/// Renderable triangle which includes color and texture information.
#[derive(Clone, Debug)]
pub struct RendTri {
    pub(crate) tri: Tri,
    pub(crate) texture: Option<Rc<Texture2d>>,
}

impl RendTri {
    #[inline]
    fn map_pos<F: FnMut(cgm::Point2<f32>) -> cgm::Point2<f32>>(mut self, f: F) -> RendTri {
        self.tri.positions = self.tri.positions.map(f);
        self
    }

    #[inline]
    fn map_tex<F: FnMut(cgm::Point2<f32>) -> cgm::Point2<f32>>(mut self, f: F) -> RendTri {
        self.tri.texcoords = self.tri.texcoords.map(f);
        self
    }

    #[inline]
    fn map_color<F: FnMut(Color) -> Color>(mut self, mut f: F) -> RendTri {
        self.tri.color = f(Color(self.tri.color)).0;
        self
    }

    #[inline]
    fn map_texture<T: Into<Option<Rc<Texture2d>>>>(mut self, t: T) -> RendTri {
        self.texture = t.into();
        self
    }
}

impl From<Tri> for RendTri {
    #[inline]
    fn from(tri: Tri) -> Self {
        RendTri {
            tri: tri,
            texture: None,
        }
    }
}

/// Three positions which form a matrix for shader purposes
#[derive(Copy, Clone, Debug)]
pub struct Positions(pub [[f32; 2]; 3]);

impl Positions {
    #[inline]
    fn map<F: FnMut(cgm::Point2<f32>) -> cgm::Point2<f32>>(self, mut f: F) -> Positions {
        Positions([f(self.0[0].into()).into(), f(self.0[1].into()).into(), f(self.0[2].into()).into()])
    }
}

/// A triangle primitive which enters the shader pipeline as a single vertex and is the only primitive in nest
#[derive(Copy, Clone, Debug)]
pub struct Tri {
    /// The three space vertices of the triangles
    pub positions: Positions,
    /// The three texture coordinates of the above vertices
    pub texcoords: Positions,
    /// The color of this triangle.
    pub color: [f32; 4],
}

impl Tri {
    /// Create a new triangle with points and tex coordinates specified
    #[inline]
    pub fn new<P: Into<cgm::Point2<f32>> + Copy, T: Into<cgm::Point2<f32>> + Copy, C: Into<Color>>(
        positions: [P; 3],
        texcoords: [T; 3],
        color: C,
    ) -> Tri {
        Tri {
            positions: Positions(
                [
                    positions[0].into().into(),
                    positions[1].into().into(),
                    positions[2].into().into(),
                ],
            ),
            texcoords: Positions(
                [
                    texcoords[0].into().into(),
                    texcoords[1].into().into(),
                    texcoords[2].into().into(),
                ],
            ),
            color: color.into().0,
        }
    }

    /// Create a new triangle with points with coordinates to create a single-color triangle
    #[inline]
    pub fn new_pos<P: Into<cgm::Point2<f32>> + Copy>(positions: [P; 3]) -> Tri {
        Tri::new(
            [
                positions[0].into(),
                positions[1].into(),
                positions[2].into(),
            ],
            [cgm::Point2::new(0.0, 0.0); 3],
            Color::WHITE,
        )
    }
}

implement_vertex!(Tri, positions, texcoords, color);

unsafe impl glium::vertex::Attribute for Positions {
    fn get_type() -> glium::vertex::AttributeType {
        glium::vertex::AttributeType::F32x2x3
    }
}
<commit_msg>change some public-facing API visibility<commit_after>use glium;
use cgm;

use Color;
use std::rc::Rc;
use glium::texture::Texture2d;

mod translate;
mod rotate;
mod combine;
mod image;
mod rect;
mod recolor;
mod mulcolor;

// Combinator helper structs
use self::translate::*;
use self::rotate::*;
use self::combine::*;
use self::recolor::*;
use self::mulcolor::*;

// User types
pub use self::image::*;
pub use self::rect::*;

/// Trait for structs to be drawn with `Frame::draw`
pub trait Shape: IntoIterator<Item = RendTri> {
    /// Combine shapes together so they become one shape.
    #[inline]
    fn combine<S: Shape>(self, rhs: S) -> Combine<Self, S> where Self: Sized {
        Combine(self, rhs)
    }

    /// Translate a shape using a `vector` which represents the direction and magnitude to translate it by.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5]).translate([0.1, 0.1]));
    /// ```
    #[inline]
    fn translate<V: Into<cgm::Vector2<f32>>>(&self, vector: V) -> Translate<Self> where Self: Clone {
        Translate::new(self.clone(), vector.into())
    }

    /// Rotate a shape using an angle in radians.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// use std::f32::consts::PI;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5]).rotate(PI));
    /// ```
    #[inline]
    fn rotate(&self, angle: f32) -> Rotate<Self> where Self: Clone {
        Rotate::new(self.clone(), angle)
    }

    /// Completely recolor a shape.
    ///
    /// This does not erase textures, just colors them. Calling recolor() will
    /// cause every component of the shape to change its color to the passed
    /// color and should not be used in most situations as it erases
    /// sub-component color information. This can be used to make
    /// silhouettes and some other effects, but is mostly not useful.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5]).recolor(Color::BLUE));
    /// ```
    #[inline]
    fn recolor<C: Into<Color>>(&self, color: C) -> Recolor<Self> where Self: Clone {
        Recolor::new(self.clone(), color.into())
    }

    /// Multiply all of the colors in the shape component-wise with
    /// the passed color. See `Color::multiply()`.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// // This will be drawn with Color([0.0, 0.0, 0.5, 1.0]).
    /// // It extracts only the blue and alpha components.
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5])
    ///    .recolor([0.5, 0.5, 0.5, 1.0])
    ///    .mul_color(Color::BLUE));
    /// ```
    #[inline]
    fn mul_color<C: Into<Color>>(&self, color: C) -> Mulcolor<Self> where Self: Clone {
        Mulcolor::new(self.clone(), color.into())
    }

    /// Multiply all of the colors in the shape component-wise with
    /// the passed color. See `Color::multiply()`.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// // This will be drawn with Color([0.25, 0.5, 0.5, 1.0]).
    /// // It extracts half of the color components.
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5])
    ///    .recolor([0.5, 1.0, 1.0, 1.0])
    ///    .scale_color(0.5));
    /// ```
    #[inline]
    fn scale_color(&self, scale: f32) -> Mulcolor<Self> where Self: Clone {
        Mulcolor::new(self.clone(), Color([scale, scale, scale, 1.0]))
    }

    /// Scales the transparrency/alpha value of the shape's color.
    ///
    /// ## Example
    /// ```rust,no_run
    /// use nest::*;
    /// let mut app = Window::new("Example", 640, 480).unwrap();
    /// // This will be drawn with Color([0.5, 1.0, 1.0, 0.5]).
    /// // It extracts half of the alpha component.
    /// app.draw(Rect([-0.5, -0.5], [0.5, 0.5])
    ///    .recolor([0.5, 1.0, 1.0, 1.0])
    ///    .scale_alpha(0.5));
    /// ```
    #[inline]
    fn scale_alpha(&self, scale: f32) -> Mulcolor<Self> where Self: Clone {
        Mulcolor::new(self.clone(), Color([1.0, 1.0, 1.0, scale]))
    }
}

impl<S> Shape for S where S: IntoIterator<Item = RendTri> {}

/// Renderable triangle which includes color and texture information.
#[derive(Clone, Debug)]
pub struct RendTri {
    pub(crate) tri: Tri,
    pub(crate) texture: Option<Rc<Texture2d>>,
}

impl RendTri {
    #[inline]
    fn map_pos<F: FnMut(cgm::Point2<f32>) -> cgm::Point2<f32>>(mut self, f: F) -> RendTri {
        self.tri.positions = self.tri.positions.map(f);
        self
    }

    #[inline]
    fn map_tex<F: FnMut(cgm::Point2<f32>) -> cgm::Point2<f32>>(mut self, f: F) -> RendTri {
        self.tri.texcoords = self.tri.texcoords.map(f);
        self
    }

    #[inline]
    fn map_color<F: FnMut(Color) -> Color>(mut self, mut f: F) -> RendTri {
        self.tri.color = f(Color(self.tri.color)).0;
        self
    }

    #[inline]
    fn map_texture<T: Into<Option<Rc<Texture2d>>>>(mut self, t: T) -> RendTri {
        self.texture = t.into();
        self
    }
}

impl From<Tri> for RendTri {
    #[inline]
    fn from(tri: Tri) -> Self {
        RendTri {
            tri: tri,
            texture: None,
        }
    }
}

/// Three positions which form a matrix for shader purposes
#[derive(Copy, Clone, Debug)]
pub struct Positions(pub [[f32; 2]; 3]);

impl Positions {
    #[inline]
    fn map<F: FnMut(cgm::Point2<f32>) -> cgm::Point2<f32>>(self, mut f: F) -> Positions {
        Positions([f(self.0[0].into()).into(), f(self.0[1].into()).into(), f(self.0[2].into()).into()])
    }
}

/// A triangle primitive which enters the shader pipeline as a single vertex and is the only primitive in nest
#[derive(Copy, Clone, Debug)]
pub struct Tri {
    /// The three space vertices of the triangles
    pub positions: Positions,
    /// The three texture coordinates of the above vertices
    pub texcoords: Positions,
    /// The color of this triangle.
    pub color: [f32; 4],
}

impl Tri {
    /// Create a new triangle with points and tex coordinates specified
    #[inline]
    pub fn new<P: Into<cgm::Point2<f32>> + Copy, T: Into<cgm::Point2<f32>> + Copy, C: Into<Color>>(
        positions: [P; 3],
        texcoords: [T; 3],
        color: C,
    ) -> Tri {
        Tri {
            positions: Positions(
                [
                    positions[0].into().into(),
                    positions[1].into().into(),
                    positions[2].into().into(),
                ],
            ),
            texcoords: Positions(
                [
                    texcoords[0].into().into(),
                    texcoords[1].into().into(),
                    texcoords[2].into().into(),
                ],
            ),
            color: color.into().0,
        }
    }

    /// Create a new triangle with points with coordinates to create a single-color triangle
    #[inline]
    pub fn new_pos<P: Into<cgm::Point2<f32>> + Copy>(positions: [P; 3]) -> Tri {
        Tri::new(
            [
                positions[0].into(),
                positions[1].into(),
                positions[2].into(),
            ],
            [cgm::Point2::new(0.0, 0.0); 3],
            Color::WHITE,
        )
    }
}

implement_vertex!(Tri, positions, texcoords, color);

unsafe impl glium::vertex::Attribute for Positions {
    fn get_type() -> glium::vertex::AttributeType {
        glium::vertex::AttributeType::F32x2x3
    }
}
<|endoftext|>


<commit_before>use {Errno, Result};
use libc::{self, c_int};
use std::os::unix::io::RawFd;
use std::ptr;
use std::mem;
use ::Error;

libc_bitflags!(
    pub struct EpollFlags: libc::c_int {
        EPOLLIN;
        EPOLLPRI;
        EPOLLOUT;
        EPOLLRDNORM;
        EPOLLRDBAND;
        EPOLLWRNORM;
        EPOLLWRBAND;
        EPOLLMSG;
        EPOLLERR;
        EPOLLHUP;
        EPOLLRDHUP;
        #[cfg(target_os = "linux")]  // Added in 4.5; not in Android.
        EPOLLEXCLUSIVE;
        #[cfg(not(target_arch = "mips"))]
        EPOLLWAKEUP;
        EPOLLONESHOT;
        EPOLLET;
    }
);

#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(C)]
pub enum EpollOp {
    EpollCtlAdd = 1,
    EpollCtlDel = 2,
    EpollCtlMod = 3
}

libc_bitflags!{
    pub struct EpollCreateFlags: c_int {
        EPOLL_CLOEXEC;
    }
}

#[derive(Clone, Copy)]
#[repr(C)]
pub struct EpollEvent {
    event: libc::epoll_event,
}

impl EpollEvent {
    pub fn new(events: EpollFlags, data: u64) -> Self {
        EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } }
    }

    pub fn empty() -> Self {
        unsafe { mem::zeroed::<EpollEvent>() }
    }

    pub fn events(&self) -> EpollFlags {
        EpollFlags::from_bits(self.event.events as libc::c_int).unwrap()
    }

    pub fn data(&self) -> u64 {
        self.event.u64
    }
}

impl<'a> Into<&'a mut EpollEvent> for Option<&'a mut EpollEvent> {
    #[inline]
    fn into(self) -> &'a mut EpollEvent {
        match self {
            Some(epoll_event) => epoll_event,
            None => unsafe { &mut *ptr::null_mut::<EpollEvent>() }
        }
    }
}

#[inline]
pub fn epoll_create() -> Result<RawFd> {
    let res = unsafe { libc::epoll_create(1024) };

    Errno::result(res)
}

#[inline]
pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
    let res = unsafe { libc::epoll_create1(flags.bits()) };

    Errno::result(res)
}

#[inline]
pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
    where T: Into<&'a mut EpollEvent>
{
    let event: &mut EpollEvent = event.into();
    if event as *const EpollEvent == ptr::null() && op != EpollOp::EpollCtlDel {
        Err(Error::Sys(Errno::EINVAL))
    } else {
        let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };
        Errno::result(res).map(drop)
    }
}

#[inline]
pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
    let res = unsafe {
        libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
    };

    Errno::result(res).map(|r| r as usize)
}
<commit_msg>Replace ffi constants with libc in epoll<commit_after>use {Errno, Result};
use libc::{self, c_int};
use std::os::unix::io::RawFd;
use std::ptr;
use std::mem;
use ::Error;

libc_bitflags!(
    pub struct EpollFlags: libc::c_int {
        EPOLLIN;
        EPOLLPRI;
        EPOLLOUT;
        EPOLLRDNORM;
        EPOLLRDBAND;
        EPOLLWRNORM;
        EPOLLWRBAND;
        EPOLLMSG;
        EPOLLERR;
        EPOLLHUP;
        EPOLLRDHUP;
        #[cfg(target_os = "linux")]  // Added in 4.5; not in Android.
        EPOLLEXCLUSIVE;
        #[cfg(not(target_arch = "mips"))]
        EPOLLWAKEUP;
        EPOLLONESHOT;
        EPOLLET;
    }
);

#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(i32)]
pub enum EpollOp {
    EpollCtlAdd = libc::EPOLL_CTL_ADD,
    EpollCtlDel = libc::EPOLL_CTL_DEL,
    EpollCtlMod = libc::EPOLL_CTL_MOD,
}

libc_bitflags!{
    pub struct EpollCreateFlags: c_int {
        EPOLL_CLOEXEC;
    }
}

#[derive(Clone, Copy)]
#[repr(C)]
pub struct EpollEvent {
    event: libc::epoll_event,
}

impl EpollEvent {
    pub fn new(events: EpollFlags, data: u64) -> Self {
        EpollEvent { event: libc::epoll_event { events: events.bits() as u32, u64: data } }
    }

    pub fn empty() -> Self {
        unsafe { mem::zeroed::<EpollEvent>() }
    }

    pub fn events(&self) -> EpollFlags {
        EpollFlags::from_bits(self.event.events as libc::c_int).unwrap()
    }

    pub fn data(&self) -> u64 {
        self.event.u64
    }
}

impl<'a> Into<&'a mut EpollEvent> for Option<&'a mut EpollEvent> {
    #[inline]
    fn into(self) -> &'a mut EpollEvent {
        match self {
            Some(epoll_event) => epoll_event,
            None => unsafe { &mut *ptr::null_mut::<EpollEvent>() }
        }
    }
}

#[inline]
pub fn epoll_create() -> Result<RawFd> {
    let res = unsafe { libc::epoll_create(1024) };

    Errno::result(res)
}

#[inline]
pub fn epoll_create1(flags: EpollCreateFlags) -> Result<RawFd> {
    let res = unsafe { libc::epoll_create1(flags.bits()) };

    Errno::result(res)
}

#[inline]
pub fn epoll_ctl<'a, T>(epfd: RawFd, op: EpollOp, fd: RawFd, event: T) -> Result<()>
    where T: Into<&'a mut EpollEvent>
{
    let event: &mut EpollEvent = event.into();
    if event as *const EpollEvent == ptr::null() && op != EpollOp::EpollCtlDel {
        Err(Error::Sys(Errno::EINVAL))
    } else {
        let res = unsafe { libc::epoll_ctl(epfd, op as c_int, fd, &mut event.event) };
        Errno::result(res).map(drop)
    }
}

#[inline]
pub fn epoll_wait(epfd: RawFd, events: &mut [EpollEvent], timeout_ms: isize) -> Result<usize> {
    let res = unsafe {
        libc::epoll_wait(epfd, events.as_mut_ptr() as *mut libc::epoll_event, events.len() as c_int, timeout_ms as c_int)
    };

    Errno::result(res).map(|r| r as usize)
}
<|endoftext|>


<commit_before>use toml::Parser;
use regex::Regex;
use std::io::prelude::*;
use std::fs::File;
use std::io::Error;

pub enum TomlError {
    parseError(&'static str),
    ioError(Error)
}

pub fn read_version(file: String) -> Option<String> {
   let file_map = Parser::new(&file).parse().unwrap();
   let package = file_map.get("package").unwrap();
   let version = package.as_table()
       .unwrap()
       .get("version");
   match version {
       Some(v) => Some(v.as_str().unwrap().into()),
       None => None
   }
}

pub fn file_with_new_version(file: String, new_version: &str) -> String {
    let re = Regex::new(r#"version\s=\s"\d+\.\d+\.\d+""#).unwrap();
    let new_version = format!("version = \"{}\"", new_version);
    re.replace(&file, &new_version[..])
}

pub fn read_from_file() -> Result<String, TomlError> {
    let cargo_file = match read_cargo_toml() {
        Ok(buffer) => buffer,
        Err(err) => return Err(TomlError::ioError(err))
    };

    match read_version(cargo_file) {
        Some(version) => Ok(version),
        None => Err(TomlError::parseError("No version field found"))
    }
}

pub fn write_new_version(new_version: String) -> Result<(), Error> {
    let cargo_toml = match read_cargo_toml() {
        Ok(file) => file,
        Err(err) => return Err(err)
    };
    let new_cargo_toml = file_with_new_version(cargo_toml, &new_version);

    let mut handle = match File::open("Cargo.toml") {
        Ok(handle) => handle,
        Err(err) => {
            return Err(err)
        }
    };

    match handle.write_all(new_cargo_toml.as_bytes()) {
        Ok(_) => Ok(()),
        Err(err) => Err(err)
    }
}

fn read_cargo_toml() -> Result<String, Error> {
    let mut handle = match File::open("Cargo.toml") {
        Ok(handle) => handle,
        Err(err) => {
            return Err(err)
        }
    };

    let mut buffer = String::new();
    match handle.read_to_string(&mut buffer) {
        Ok(_) => Ok(buffer),
        Err(err) => Err(err)
    }
}

#[cfg(test)]
mod tests {
    extern crate toml;
    extern crate regex;
    use super::*;

    fn example_file() -> String {
        "[package]
    name = \"semantic-rs\"
    version = \"0.1.0\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string()
    }

    fn example_file_without_version() -> String {
        "[package]
    name = \"semantic-rs\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string()
    }

    #[test]
    fn read_version_number() {
        let version_str = read_version(example_file());
        assert_eq!(version_str, Some("0.1.0".into()));
    }

    #[test]
    fn read_file_without_version_number() {
        let version_str = read_version(example_file_without_version());
        assert_eq!(version_str, None);
    }

    #[test]
    fn write_new_version_number() {
        let new_toml_file = file_with_new_version(example_file(), "0.2.0".into());
        let expected_file =
            "[package]
    name = \"semantic-rs\"
    version = \"0.2.0\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string();
        assert_eq!(new_toml_file, expected_file);
    }
}
<commit_msg>fix(toml_file): Open Cargo.toml for writing<commit_after>use toml::Parser;
use regex::Regex;
use std::io::prelude::*;
use std::fs::File;
use std::io::Error;
use std::fs::OpenOptions;

pub enum TomlError {
    parseError(&'static str),
    ioError(Error)
}

pub fn read_version(file: String) -> Option<String> {
   let file_map = Parser::new(&file).parse().unwrap();
   let package = file_map.get("package").unwrap();
   let version = package.as_table()
       .unwrap()
       .get("version");
   match version {
       Some(v) => Some(v.as_str().unwrap().into()),
       None => None
   }
}

pub fn file_with_new_version(file: String, new_version: &str) -> String {
    let re = Regex::new(r#"version\s=\s"\d+\.\d+\.\d+""#).unwrap();
    let new_version = format!("version = \"{}\"", new_version);
    re.replace(&file, &new_version[..])
}

pub fn read_from_file() -> Result<String, TomlError> {
    let cargo_file = match read_cargo_toml() {
        Ok(buffer) => buffer,
        Err(err) => return Err(TomlError::ioError(err))
    };

    match read_version(cargo_file) {
        Some(version) => Ok(version),
        None => Err(TomlError::parseError("No version field found"))
    }
}

pub fn write_new_version(new_version: String) -> Result<(), Error> {
    let cargo_toml = try!(read_cargo_toml());
    let new_cargo_toml = file_with_new_version(cargo_toml, &new_version);
    let mut handle = try!(OpenOptions::new().read(true).write(true).open("Cargo.toml"));
    handle.write_all(new_cargo_toml.as_bytes())
}

fn read_cargo_toml() -> Result<String, Error> {
    let mut handle = match File::open("Cargo.toml") {
        Ok(handle) => handle,
        Err(err) => {
            return Err(err)
        }
    };

    let mut buffer = String::new();
    match handle.read_to_string(&mut buffer) {
        Ok(_) => Ok(buffer),
        Err(err) => Err(err)
    }
}

#[cfg(test)]
mod tests {
    extern crate toml;
    extern crate regex;
    use super::*;

    fn example_file() -> String {
        "[package]
    name = \"semantic-rs\"
    version = \"0.1.0\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string()
    }

    fn example_file_without_version() -> String {
        "[package]
    name = \"semantic-rs\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string()
    }

    #[test]
    fn read_version_number() {
        let version_str = read_version(example_file());
        assert_eq!(version_str, Some("0.1.0".into()));
    }

    #[test]
    fn read_file_without_version_number() {
        let version_str = read_version(example_file_without_version());
        assert_eq!(version_str, None);
    }

    #[test]
    fn write_new_version_number() {
        let new_toml_file = file_with_new_version(example_file(), "0.2.0".into());
        let expected_file =
            "[package]
    name = \"semantic-rs\"
    version = \"0.2.0\"
    authors = [\"Jan Schulte <hello@unexpected-co.de>\"]
    [dependencies]
    term = \"0.2\"
    toml = \"0.1\"".to_string();
        assert_eq!(new_toml_file, expected_file);
    }
}
<|endoftext|>


<commit_before>// Copyright 2013-2014 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.

//! Traits for dynamic typing of any `'static` type (through runtime reflection)
//!
//! This module implements the `Any` trait, which enables dynamic typing
//! of any `'static` type through runtime reflection.
//!
//! `Any` itself can be used to get a `TypeId`, and has more features when used as a trait object.
//! As `&Any` (a borrowed trait object), it has the `is` and `as_ref` methods, to test if the
//! contained value is of a given type, and to get a reference to the inner value as a type. As
//! `&mut Any`, there is also the `as_mut` method, for getting a mutable reference to the inner
//! value. `Box<Any>` adds the `move` method, which will unwrap a `Box<T>` from the object.  See
//! the extension traits (`*Ext`) for the full details.

use mem::{transmute, transmute_copy};
use option::{Option, Some, None};
use raw::TraitObject;
use intrinsics::TypeId;

/// A type with no inhabitants
pub enum Void { }

///////////////////////////////////////////////////////////////////////////////
// Any trait
///////////////////////////////////////////////////////////////////////////////

/// The `Any` trait is implemented by all `'static` types, and can be used for dynamic typing
///
/// Every type with no non-`'static` references implements `Any`, so `Any` can be used as a trait
/// object to emulate the effects dynamic typing.
pub trait Any {
    /// Get the `TypeId` of `self`
    fn get_type_id(&self) -> TypeId;
}

impl<T: 'static> Any for T {
    /// Get the `TypeId` of `self`
    fn get_type_id(&self) -> TypeId {
        TypeId::of::<T>()
    }
}

///////////////////////////////////////////////////////////////////////////////
// Extension methods for Any trait objects.
// Implemented as three extension traits so that the methods can be generic.
///////////////////////////////////////////////////////////////////////////////

/// Extension methods for a referenced `Any` trait object
pub trait AnyRefExt<'a> {
    /// Returns true if the boxed type is the same as `T`
    fn is<T: 'static>(self) -> bool;

    /// Returns some reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn as_ref<T: 'static>(self) -> Option<&'a T>;
}

impl<'a> AnyRefExt<'a> for &'a Any {
    #[inline]
    fn is<T: 'static>(self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    #[inline]
    fn as_ref<T: 'static>(self) -> Option<&'a T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute_copy(&self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }
}

/// Extension methods for a mutable referenced `Any` trait object
pub trait AnyMutRefExt<'a> {
    /// Returns some mutable reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn as_mut<T: 'static>(self) -> Option<&'a mut T>;
}

impl<'a> AnyMutRefExt<'a> for &'a mut Any {
    #[inline]
    fn as_mut<T: 'static>(self) -> Option<&'a mut T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute_copy(&self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }
}
<commit_msg>Add example to Any documentation<commit_after>// Copyright 2013-2014 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.

//! Traits for dynamic typing of any `'static` type (through runtime reflection)
//!
//! This module implements the `Any` trait, which enables dynamic typing
//! of any `'static` type through runtime reflection.
//!
//! `Any` itself can be used to get a `TypeId`, and has more features when used
//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and
//! `as_ref` methods, to test if the contained value is of a given type, and to
//! get a reference to the inner value as a type. As`&mut Any`, there is also
//! the `as_mut` method, for getting a mutable reference to the inner value.
//! `Box<Any>` adds the `move` method, which will unwrap a `Box<T>` from the
//! object.  See the extension traits (`*Ext`) for the full details.
//!
//! Note that &Any is limited to testing whether a value is of a specified
//! concrete type, and cannot be used to test whether a type implements a trait.
//!
//! # Examples
//!
//! Consider a situation where we want to log out a value passed to a function.
//! We know the value we're working on implements Show, but we don't know its
//! concrete type.  We want to give special treatment to certain types: in this
//! case printing out the length of String values prior to their value.
//! We don't know the concrete type of our value at compile time, so we need to
//! use runtime reflection instead.
//!
//! ```rust
//! use std::fmt::Show;
//! use std::any::{Any, AnyRefExt};
//!
//! // Logger function for any type that implements Show.
//! fn log<T: Any+Show>(value: &T) {
//!     let value_any = value as &Any;
//!
//!     // try to convert our value to a String.  If successful, we want to
//!     // output the String's length as well as its value.  If not, it's a
//!     // different type: just print it out unadorned.
//!     match value_any.as_ref::<String>() {
//!         Some(as_string) => {
//!             println!("String ({}): {}", as_string.len(), as_string);
//!         }
//!         None => {
//!             println!("{}", value);
//!         }
//!     }
//! }
//!
//! // This function wants to log its parameter out prior to doing work with it.
//! fn do_work<T: Show>(value: &T) {
//!     log(value);
//!     // ...do some other work
//! }
//!
//! fn main() {
//!     let my_string = "Hello World".to_string();
//!     do_work(&my_string);
//!
//!     let my_i8: i8 = 100;
//!     do_work(&my_i8);
//! }
//! ```

use mem::{transmute, transmute_copy};
use option::{Option, Some, None};
use raw::TraitObject;
use intrinsics::TypeId;

/// A type with no inhabitants
pub enum Void { }

///////////////////////////////////////////////////////////////////////////////
// Any trait
///////////////////////////////////////////////////////////////////////////////

/// The `Any` trait is implemented by all `'static` types, and can be used for dynamic typing
///
/// Every type with no non-`'static` references implements `Any`, so `Any` can be used as a trait
/// object to emulate the effects dynamic typing.
pub trait Any {
    /// Get the `TypeId` of `self`
    fn get_type_id(&self) -> TypeId;
}

impl<T: 'static> Any for T {
    /// Get the `TypeId` of `self`
    fn get_type_id(&self) -> TypeId {
        TypeId::of::<T>()
    }
}

///////////////////////////////////////////////////////////////////////////////
// Extension methods for Any trait objects.
// Implemented as three extension traits so that the methods can be generic.
///////////////////////////////////////////////////////////////////////////////

/// Extension methods for a referenced `Any` trait object
pub trait AnyRefExt<'a> {
    /// Returns true if the boxed type is the same as `T`
    fn is<T: 'static>(self) -> bool;

    /// Returns some reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn as_ref<T: 'static>(self) -> Option<&'a T>;
}

impl<'a> AnyRefExt<'a> for &'a Any {
    #[inline]
    fn is<T: 'static>(self) -> bool {
        // Get TypeId of the type this function is instantiated with
        let t = TypeId::of::<T>();

        // Get TypeId of the type in the trait object
        let boxed = self.get_type_id();

        // Compare both TypeIds on equality
        t == boxed
    }

    #[inline]
    fn as_ref<T: 'static>(self) -> Option<&'a T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute_copy(&self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }
}

/// Extension methods for a mutable referenced `Any` trait object
pub trait AnyMutRefExt<'a> {
    /// Returns some mutable reference to the boxed value if it is of type `T`, or
    /// `None` if it isn't.
    fn as_mut<T: 'static>(self) -> Option<&'a mut T>;
}

impl<'a> AnyMutRefExt<'a> for &'a mut Any {
    #[inline]
    fn as_mut<T: 'static>(self) -> Option<&'a mut T> {
        if self.is::<T>() {
            unsafe {
                // Get the raw representation of the trait object
                let to: TraitObject = transmute_copy(&self);

                // Extract the data pointer
                Some(transmute(to.data))
            }
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! *It is not recommended to use the core library*. The stable
//! functionality of libcore is reexported from the
//! [standard library](../std/index.html). The composition of this library is
//! subject to change over time; only the interface exposed through libstd is
//! intended to be stable.
//!
//! # How to use the core library
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [rlibc crate](https://crates.io/crates/rlibc).
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
//!   `fmt::Arguments`, a `&str`, and a `u32`. These three arguments dictate
//!   the panic message, the file at which panic was invoked, and the line.
//!   It is up to consumers of this core library to define this panic
//!   function; it is only required to never return.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.

// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "core"]
#![unstable(feature = "core",
            reason = "the libcore library has not yet been scrutinized for \
                      stabilization in terms of structure and naming",
            issue = "27701")]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
#![doc(test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]

#![no_core]
#![allow(raw_pointer_derive)]
#![deny(missing_docs)]

#![feature(allow_internal_unstable)]
#![feature(associated_type_defaults)]
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(custom_attribute)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(reflect)]
#![feature(rustc_attrs)]
#![feature(unwind_attributes)]
#![cfg_attr(stage0, feature(simd))]
#![cfg_attr(not(stage0), feature(repr_simd, platform_intrinsics))]
#![feature(staged_api)]
#![feature(unboxed_closures)]

#[macro_use]
mod macros;

#[macro_use]
mod cmp_macros;

#[path = "num/float_macros.rs"]
#[macro_use]
mod float_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"]  pub mod isize;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod nonzero;
pub mod ptr;

/* Core language traits */

pub mod marker;
pub mod ops;
pub mod cmp;
pub mod clone;
pub mod default;
pub mod convert;
pub mod borrow;

/* Core types and methods on primitives */

pub mod any;
pub mod array;
pub mod sync;
pub mod cell;
pub mod char;
pub mod panicking;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;

#[cfg(stage0)]
#[path = "simd_old.rs"]
pub mod simd;
#[cfg(not(stage0))]
pub mod simd;

pub mod slice;
pub mod str;
pub mod hash;
pub mod fmt;

// note: does not need to be public
mod tuple;
<commit_msg>Rollup merge of #29612 - steveklabnik:gh29502, r=alexcrichton<commit_after>// Copyright 2014 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.

//! # The Rust Core Library
//!
//! The Rust Core Library is the dependency-free[^free] foundation of [The
//! Rust Standard Library](../std/index.html). It is the portable glue
//! between the language and its libraries, defining the intrinsic and
//! primitive building blocks of all Rust code. It links to no
//! upstream libraries, no system libraries, and no libc.
//!
//! [^free]: Strictly speaking, there are some symbols which are needed but
//!          they aren't always neccesary.
//!
//! The core library is *minimal*: it isn't even aware of heap allocation,
//! nor does it provide concurrency or I/O. These things require
//! platform integration, and this library is platform-agnostic.
//!
//! *It is not recommended to use the core library*. The stable
//! functionality of libcore is reexported from the
//! [standard library](../std/index.html). The composition of this library is
//! subject to change over time; only the interface exposed through libstd is
//! intended to be stable.
//!
//! # How to use the core library
//!
// FIXME: Fill me in with more detail when the interface settles
//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//!   often generated by LLVM. Additionally, this library can make explicit
//!   calls to these functions. Their signatures are the same as found in C.
//!   These functions are often provided by the system libc, but can also be
//!   provided by the [rlibc crate](https://crates.io/crates/rlibc).
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
//!   `fmt::Arguments`, a `&str`, and a `u32`. These three arguments dictate
//!   the panic message, the file at which panic was invoked, and the line.
//!   It is up to consumers of this core library to define this panic
//!   function; it is only required to never return.

// Since libcore defines many fundamental lang items, all tests live in a
// separate crate, libcoretest, to avoid bizarre issues.

// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "core"]
#![unstable(feature = "core",
            reason = "the libcore library has not yet been scrutinized for \
                      stabilization in terms of structure and naming",
            issue = "27701")]
#![staged_api]
#![crate_type = "rlib"]
#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
       html_root_url = "https://doc.rust-lang.org/nightly/",
       html_playground_url = "https://play.rust-lang.org/",
       issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
#![doc(test(no_crate_inject, attr(allow(unused_variables), deny(warnings))))]

#![no_core]
#![allow(raw_pointer_derive)]
#![deny(missing_docs)]

#![feature(allow_internal_unstable)]
#![feature(associated_type_defaults)]
#![feature(concat_idents)]
#![feature(const_fn)]
#![feature(custom_attribute)]
#![feature(fundamental)]
#![feature(intrinsics)]
#![feature(lang_items)]
#![feature(no_core)]
#![feature(on_unimplemented)]
#![feature(optin_builtin_traits)]
#![feature(reflect)]
#![feature(rustc_attrs)]
#![feature(unwind_attributes)]
#![cfg_attr(stage0, feature(simd))]
#![cfg_attr(not(stage0), feature(repr_simd, platform_intrinsics))]
#![feature(staged_api)]
#![feature(unboxed_closures)]

#[macro_use]
mod macros;

#[macro_use]
mod cmp_macros;

#[path = "num/float_macros.rs"]
#[macro_use]
mod float_macros;

#[path = "num/int_macros.rs"]
#[macro_use]
mod int_macros;

#[path = "num/uint_macros.rs"]
#[macro_use]
mod uint_macros;

#[path = "num/isize.rs"]  pub mod isize;
#[path = "num/i8.rs"]   pub mod i8;
#[path = "num/i16.rs"]  pub mod i16;
#[path = "num/i32.rs"]  pub mod i32;
#[path = "num/i64.rs"]  pub mod i64;

#[path = "num/usize.rs"] pub mod usize;
#[path = "num/u8.rs"]   pub mod u8;
#[path = "num/u16.rs"]  pub mod u16;
#[path = "num/u32.rs"]  pub mod u32;
#[path = "num/u64.rs"]  pub mod u64;

#[path = "num/f32.rs"]   pub mod f32;
#[path = "num/f64.rs"]   pub mod f64;

#[macro_use]
pub mod num;

/* The libcore prelude, not as all-encompassing as the libstd prelude */

pub mod prelude;

/* Core modules for ownership management */

pub mod intrinsics;
pub mod mem;
pub mod nonzero;
pub mod ptr;

/* Core language traits */

pub mod marker;
pub mod ops;
pub mod cmp;
pub mod clone;
pub mod default;
pub mod convert;
pub mod borrow;

/* Core types and methods on primitives */

pub mod any;
pub mod array;
pub mod sync;
pub mod cell;
pub mod char;
pub mod panicking;
pub mod iter;
pub mod option;
pub mod raw;
pub mod result;

#[cfg(stage0)]
#[path = "simd_old.rs"]
pub mod simd;
#[cfg(not(stage0))]
pub mod simd;

pub mod slice;
pub mod str;
pub mod hash;
pub mod fmt;

// note: does not need to be public
mod tuple;
<|endoftext|>


<commit_before>use std::fmt::Write;

/* For branch name dedup */
use std::collections::HashSet;

use util::*;

use std::process;

use timesheet::traits::HasHTML;

#[derive(PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub enum EventType {
    Pause,
    Resume,
    Note,
    Commit { hash: String },
}

#[derive(Serialize, Deserialize, Debug)]
struct Event {
    timestamp : u64,
    note      : Option<String>,
    ev_ty     : EventType
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Session {
    pub start    : u64,
    pub end      : u64,
    running  : bool,
    branches : HashSet<String>,
    events   : Vec<Event>,
}

impl Session {
    pub fn new(timestamp: Option<u64>) -> Session {
        let timestamp = match timestamp {
            Some(timestamp) => timestamp,
            None => get_seconds(),
        };
        Session {
            start    : timestamp,
            end      : timestamp + 1,
            running  : true,
            branches : HashSet::<String>::new(),
            events   : Vec::<Event>::new(),
        }
    }

    pub fn is_running(&self) -> bool {
        self.running
    }

    pub fn is_paused(&self) -> bool {
        self.events.last().map_or(false, |ev| {
            println!("{:?} is pause: {}", ev.ev_ty,
            ev.ev_ty == EventType::Pause);
            true
        });
        self.events.last().map_or(false, |ev| ev.ev_ty == EventType::Pause)
    }

    pub fn update_end(&mut self) {
        self.end = match self.events.len() {
            0 => self.end,
            n => &self.events[n - 1].timestamp + 1,
        }
    }

    pub fn finalize(&mut self, timestamp: Option<u64>) {
        let timestamp = match timestamp {
            None => get_seconds(),
            Some(timestamp) => {
                let is_valid_ts = match self.events.len() {
                    0 => timestamp > self.start,
                    n => {
                        let last_ev = &self.events[n - 1];
                        timestamp > last_ev.timestamp
                    }
                };
                if is_valid_ts {
                    timestamp
                } else {
                    println!("That is not a valid timestamp!");
                    process::exit(0);
                }
            }
        };
        if self.is_running() {
            if self.is_paused() {
                self.push_event(Some(timestamp), None, EventType::Resume);
            }
            self.running = false;
            self.end = timestamp + 1;
        }
    }

    pub fn push_event(&mut self,
                  timestamp : Option<u64>,
                  note      : Option<String>,
                  type_of_event : EventType)
                  -> bool {
        /* Cannot push if session is already finalized. */
        if !self.is_running() {
            println!("Already finalized, cannot push event.");
            return false;
        }

        let timestamp = match timestamp {
            None => {
                let now = get_seconds();
                self.end = now;
                now
            }
            Some(timestamp) => {
                let is_valid_ts = match self.events.len() {
                    0 => timestamp > self.start,
                    n => timestamp > self.events[n - 1].timestamp,
                };
                if is_valid_ts {
                    self.end = timestamp + 1;
                    timestamp
                } else {
                    println!("That timestamp is before the last event.");
                    return false;
                }
            }
        };
        /* TODO: improve logic */
        match type_of_event {
            // TODO: fix this, so both note and ago work...
            EventType::Pause => {
                if self.is_paused() {
                    println!("Already paused.");
                    false
                } else {
                    self.events
                        .push(Event {
                                  timestamp : timestamp,
                                  note      : note,
                                  ev_ty   : EventType::Pause,
                              });
                    true
                }
            }
            EventType::Resume => {
                if !self.is_paused() {
                    println!("Currently not paused.");
                    false
                } else {
                    self.events
                        .push(Event {
                                  timestamp : timestamp,
                                  note      : note,
                                  ev_ty     : EventType::Resume,
                              });
                    true
                }
            }
            EventType::Note => {
                if self.is_paused() {
                    /* Add note to previous pause (last of events vec) */
                    /* If self.is_paused(), then self.len() is always at least 1 */
                    let len = self.events.len();
                    let pause = &mut self.events[len - 1];
                    match pause.note {
                        Some(ref mut already) => {
                            // TODO: handle long strings (also in other types)
                            // TODO: there must be another way other than

                            already.push_str("
");
                            already.push_str(&note.unwrap());
                        }
                        None => pause.note = note,
                    }
                } else {
                    self.events
                        .push(Event {
                                  timestamp : timestamp,
                                  note      : note,
                                  ev_ty     : EventType::Note,
                              })
                };
                true
            }
            /* Commit adding possible only in present */
            EventType::Commit { hash } => {
                if self.is_paused() {
                    self.push_event(None, None, EventType::Resume);
                }
                /* Commit message must be provided */
                if note.is_none() {
                    println!("No commit message found for commit {}.", hash);
                }
                self.events
                    .push(Event {
                              timestamp : get_seconds(),
                              note      : note,
                              ev_ty     : EventType::Commit { hash },
                          });
                true
            }
        }
    }

    pub fn pause_time(&self) -> u64 {
        let mut pause_time = 0;
        let mut last_pause_ts = 0;
        for event in &self.events {
            match event.ev_ty {
                EventType::Pause => last_pause_ts = event.timestamp,
                EventType::Resume => pause_time += event.timestamp - last_pause_ts,
                _ => {}
            }
        }
        if self.is_paused() {
            pause_time +=   get_seconds()
                          - self.events.last().unwrap().timestamp;
        }
        pause_time
    }

    pub fn work_time(&self) -> u64 {
        let pause_time = self.pause_time();
        self.end - self.start - pause_time
    }

    pub fn add_branch(&mut self, name: String) {
        if self.is_running() {
            self.branches.insert(name);
        }
    }

    pub fn status(&self) -> String {
        let mut status = String::new();
        write!(&mut status, "Session running since {}.\n",
               sec_to_hms_string(get_seconds() - self.start))
                .unwrap();
        if self.is_paused() {
            write!(&mut status, "    Paused since {}.\n",
                   sec_to_hms_string(get_seconds() - self.events[self.events.len() - 1].timestamp))
                    .unwrap();
        } else {
            match self.events.len() {
                0 => write!(&mut status, "    No events in this session yet!\n").unwrap(),
                n => {
                    write!(&mut status,
                           "    Last event: {:?}, {} ago.\n",
                           &self.events[n - 1].ev_ty,
                           sec_to_hms_string(get_seconds() - self.events[n - 1].timestamp))
                            .unwrap()
                }
            }
        }
        let branch_str = match self.branches.len() {
            0 => String::new(),
            n => {
                self.branches.iter().fold(
                    format!("Worked on {} branches: ", n),
                    |res, s| res + s + " "
                )
            }
        };
        status.push_str(&branch_str);
        status.push_str(&format!("    Total work time:  {}\n    \
                                      Total pause time: {}\n",
                        sec_to_hms_string(self.work_time()),
                        sec_to_hms_string(self.pause_time())));
        status
    }
}

impl HasHTML for Event {
    fn to_html(&self) -> String {
        match self.ev_ty {
            EventType::Pause => {
                match self.note {
                    Some(ref info) => {
                        format!(r#"
{}: Started a pause

{}

"#,
                                ts_to_date(self.timestamp),
                                info.clone())
                    }
                    None => {
                        format!(r#"
{}: Started a pause

"#,
                                ts_to_date(self.timestamp))
                    }
                }
            }
            EventType::Resume => {
                format!(r#"
{}: Resumed work

"#,
                        ts_to_date(self.timestamp))
            }
            /* An EventType::Note note is a Some because it's
             * 'constructor' function takes a String
             * (and not Option<String>)
             */
            EventType::Note => {
                match self.note {
                    Some(ref text) => {
                        format!(r#"
{}: Note: {
}

"#,
                                ts_to_date(self.timestamp),
                                text)
                    }
                    None => unreachable!(),
                }
            }
            /* It is safe to unwrap an EventType::Commit note because if
             * a commit has no message something went really wrong
             * (like parsing the output of `git log` in git_commit_message()
             */
            EventType::Commit { ref hash } => {
                match self.note {
                    Some(ref text) => {
                        format!(r#"
{}: Commit id: {}

message: {}

"#,
                                ts_to_date(self.timestamp),
                                hash,
                                text)
                    }
                    None => unreachable!(),
                }
            }
        }
    }
}

impl HasHTML for Session {
    fn to_html(&self) -> String {
        let mut html = format!(r#"

Session on {}
"#,
                               ts_to_date(self.start));

        for event in &self.events {
            html.push_str(&event.to_html());
        }

        write!(&mut html,
               r#"
Ended on {}
"#,
               ts_to_date(self.end))
                .unwrap();

        let mut branch_str = String::new();
        match self.branches.len() {
            0 => {}
            n => {
                write!(&mut branch_str, "Worked on {} branches: ", n).unwrap();
                for branch in &self.branches {
                    write!(&mut branch_str, "{} ", branch).unwrap();
                }
            }
        };

        write!(&mut html,
               r#"

{}

Worked for {}

Paused for {}

"#,
               branch_str,
               sec_to_hms_string(self.work_time()),
               sec_to_hms_string(self.pause_time()))
                .unwrap();

        write!(&mut html, "
").unwrap();
        html
    }
}
<commit_msg>simplify finalize logic<commit_after>use std::fmt::Write;

/* For branch name dedup */
use std::collections::HashSet;

use util::*;

use std::process;

use timesheet::traits::HasHTML;

#[derive(PartialEq, PartialOrd, Serialize, Deserialize, Debug)]
pub enum EventType {
    Pause,
    Resume,
    Note,
    Commit { hash: String },
}

#[derive(Serialize, Deserialize, Debug)]
struct Event {
    timestamp : u64,
    note      : Option<String>,
    ev_ty     : EventType
}

#[derive(Serialize, Deserialize, Debug)]
pub struct Session {
    pub start    : u64,
    pub end      : u64,
    running  : bool,
    branches : HashSet<String>,
    events   : Vec<Event>,
}

impl Session {
    pub fn new(timestamp: Option<u64>) -> Session {
        let timestamp = match timestamp {
            Some(timestamp) => timestamp,
            None => get_seconds(),
        };
        Session {
            start    : timestamp,
            end      : timestamp + 1,
            running  : true,
            branches : HashSet::<String>::new(),
            events   : Vec::<Event>::new(),
        }
    }

    pub fn is_running(&self) -> bool {
        self.running
    }

    pub fn is_paused(&self) -> bool {
        self.events.last().map_or(false, |ev| ev.ev_ty == EventType::Pause)
    }

    pub fn update_end(&mut self) {
        self.end = match self.events.len() {
            0 => self.end,
            n => &self.events[n - 1].timestamp + 1,
        }
    }

    pub fn finalize(&mut self, timestamp: Option<u64>) {
        let timestamp = timestamp.unwrap_or(get_seconds());
        let is_valid_ts = match self.events.len() {
            0 => timestamp > self.start,
            n => {
                let last_ev = &self.events[n - 1];
                timestamp > last_ev.timestamp
            }
        };
        if !is_valid_ts {
            println!("That is not a valid timestamp!");
            process::exit(0);
        }

        if self.is_running() {
            if self.is_paused() {
                self.push_event(Some(timestamp), None, EventType::Resume);
            }
            self.running = false;
            self.end = timestamp + 1;
        }
    }

    pub fn push_event(&mut self,
                  timestamp : Option<u64>,
                  note      : Option<String>,
                  type_of_event : EventType)
                  -> bool {
        /* Cannot push if session is already finalized. */
        if !self.is_running() {
            println!("Already finalized, cannot push event.");
            return false;
        }

        let timestamp = match timestamp {
            None => {
                let now = get_seconds();
                self.end = now;
                now
            }
            Some(timestamp) => {
                let is_valid_ts = match self.events.len() {
                    0 => timestamp > self.start,
                    n => timestamp > self.events[n - 1].timestamp,
                };
                if is_valid_ts {
                    self.end = timestamp + 1;
                    timestamp
                } else {
                    println!("That timestamp is before the last event.");
                    return false;
                }
            }
        };
        /* TODO: improve logic */
        match type_of_event {
            // TODO: fix this, so both note and ago work...
            EventType::Pause => {
                if self.is_paused() {
                    println!("Already paused.");
                    false
                } else {
                    self.events
                        .push(Event {
                                  timestamp : timestamp,
                                  note      : note,
                                  ev_ty   : EventType::Pause,
                              });
                    true
                }
            }
            EventType::Resume => {
                if !self.is_paused() {
                    println!("Currently not paused.");
                    false
                } else {
                    self.events
                        .push(Event {
                                  timestamp : timestamp,
                                  note      : note,
                                  ev_ty     : EventType::Resume,
                              });
                    true
                }
            }
            EventType::Note => {
                if self.is_paused() {
                    /* Add note to previous pause (last of events vec) */
                    /* If self.is_paused(), then self.len() is always at least 1 */
                    let len = self.events.len();
                    let pause = &mut self.events[len - 1];
                    match pause.note {
                        Some(ref mut already) => {
                            // TODO: handle long strings (also in other types)
                            // TODO: there must be another way other than

                            already.push_str("
");
                            already.push_str(&note.unwrap());
                        }
                        None => pause.note = note,
                    }
                } else {
                    self.events
                        .push(Event {
                                  timestamp : timestamp,
                                  note      : note,
                                  ev_ty     : EventType::Note,
                              })
                };
                true
            }
            /* Commit adding possible only in present */
            EventType::Commit { hash } => {
                if self.is_paused() {
                    self.push_event(None, None, EventType::Resume);
                }
                /* Commit message must be provided */
                if note.is_none() {
                    println!("No commit message found for commit {}.", hash);
                }
                self.events
                    .push(Event {
                              timestamp : get_seconds(),
                              note      : note,
                              ev_ty     : EventType::Commit { hash },
                          });
                true
            }
        }
    }

    pub fn pause_time(&self) -> u64 {
        let mut pause_time = 0;
        let mut last_pause_ts = 0;
        for event in &self.events {
            match event.ev_ty {
                EventType::Pause => last_pause_ts = event.timestamp,
                EventType::Resume => pause_time += event.timestamp - last_pause_ts,
                _ => {}
            }
        }
        if self.is_paused() {
            pause_time +=   get_seconds()
                          - self.events.last().unwrap().timestamp;
        }
        pause_time
    }

    pub fn work_time(&self) -> u64 {
        let pause_time = self.pause_time();
        self.end - self.start - pause_time
    }

    pub fn add_branch(&mut self, name: String) {
        if self.is_running() {
            self.branches.insert(name);
        }
    }

    pub fn status(&self) -> String {
        let mut status = String::new();
        write!(&mut status, "Session running since {}.\n",
               sec_to_hms_string(get_seconds() - self.start))
                .unwrap();
        if self.is_paused() {
            write!(&mut status, "    Paused since {}.\n",
                   sec_to_hms_string(get_seconds() - self.events[self.events.len() - 1].timestamp))
                    .unwrap();
        } else {
            match self.events.len() {
                0 => write!(&mut status, "    No events in this session yet!\n").unwrap(),
                n => {
                    write!(&mut status,
                           "    Last event: {:?}, {} ago.\n",
                           &self.events[n - 1].ev_ty,
                           sec_to_hms_string(get_seconds() - self.events[n - 1].timestamp))
                            .unwrap()
                }
            }
        }
        let branch_str = match self.branches.len() {
            0 => String::new(),
            n => {
                self.branches.iter().fold(
                    format!("Worked on {} branches: ", n),
                    |res, s| res + s + " "
                )
            }
        };
        status.push_str(&branch_str);
        status.push_str(&format!("    Total work time:  {}\n    \
                                      Total pause time: {}\n",
                        sec_to_hms_string(self.work_time()),
                        sec_to_hms_string(self.pause_time())));
        status
    }
}

impl HasHTML for Event {
    fn to_html(&self) -> String {
        match self.ev_ty {
            EventType::Pause => {
                match self.note {
                    Some(ref info) => {
                        format!(r#"
{}: Started a pause

{}

"#,
                                ts_to_date(self.timestamp),
                                info.clone())
                    }
                    None => {
                        format!(r#"
{}: Started a pause

"#,
                                ts_to_date(self.timestamp))
                    }
                }
            }
            EventType::Resume => {
                format!(r#"
{}: Resumed work

"#,
                        ts_to_date(self.timestamp))
            }
            /* An EventType::Note note is a Some because it's
             * 'constructor' function takes a String
             * (and not Option<String>)
             */
            EventType::Note => {
                match self.note {
                    Some(ref text) => {
                        format!(r#"
{}: Note: {
}

"#,
                                ts_to_date(self.timestamp),
                                text)
                    }
                    None => unreachable!(),
                }
            }
            /* It is safe to unwrap an EventType::Commit note because if
             * a commit has no message something went really wrong
             * (like parsing the output of `git log` in git_commit_message()
             */
            EventType::Commit { ref hash } => {
                match self.note {
                    Some(ref text) => {
                        format!(r#"
{}: Commit id: {}

message: {}

"#,
                                ts_to_date(self.timestamp),
                                hash,
                                text)
                    }
                    None => unreachable!(),
                }
            }
        }
    }
}

impl HasHTML for Session {
    fn to_html(&self) -> String {
        let mut html = format!(r#"

Session on {}
"#,
                               ts_to_date(self.start));

        for event in &self.events {
            html.push_str(&event.to_html());
        }

        write!(&mut html,
               r#"
Ended on {}
"#,
               ts_to_date(self.end))
                .unwrap();

        let mut branch_str = String::new();
        match self.branches.len() {
            0 => {}
            n => {
                write!(&mut branch_str, "Worked on {} branches: ", n).unwrap();
                for branch in &self.branches {
                    write!(&mut branch_str, "{} ", branch).unwrap();
                }
            }
        };

        write!(&mut html,
               r#"

{}

Worked for {}

Paused for {}

"#,
               branch_str,
               sec_to_hms_string(self.work_time()),
               sec_to_hms_string(self.pause_time()))
                .unwrap();

        write!(&mut html, "
").unwrap();
        html
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Assumes Unix
use std::io::prelude::*;
use std::fs::File;
use std::process::{ Child, Command };
use std::io::Result;
use managed_process::ManagedProcess;

pub type TunnelProcess = ManagedProcess;

pub struct Tunnel {
    config: TunnelConfig,
    pub tunnel_process: Option<TunnelProcess>
}

#[derive(Clone, Debug)]
pub struct TunnelConfig {
    local_port: u16,
    remote_host: String,
}

impl TunnelConfig {
    pub fn new(port: u16, remote_host: String) -> Self {
        TunnelConfig {
            local_port: port,
            remote_host: remote_host
        }
    }

    /// Describes how to spawn the ngrok process
    pub fn spawn(&self) -> Result<Child> {
        self.write_config_file();
        Command::new("ngrok")
                // Important! By default ngrok has a curses like view
                // which takes over terminal, setting log overrides that
                .arg("-log=stdout")
                .arg("-config")
                .arg("ngrok_config.yaml")
                .arg(self.local_port.to_string())
                .spawn()
    }

    /// Write out the config file that ngrok relies on - this means that this file will always be
    /// around in the right place, it doesn't clean up after itself
    fn write_config_file(&self) -> () {
        let mut file = File::create("ngrok_config.yaml").unwrap();
        let remote_host = self.remote_host.to_owned();

        file.write_fmt(format_args!("server_addr: {}\ntrust_host_root_certs: false", remote_host)).unwrap();
    }
}

impl Tunnel {

    /// Create a new Tunnel object containing the necessary
    /// configuration
    pub fn new(config: TunnelConfig) -> Tunnel {
        Tunnel {
            config: config,
            tunnel_process: None
        }
    }

    /// Start the Tunnel process if it has not already been started
    pub fn start(&mut self) -> Result<()> {
        if let Some(_) = self.tunnel_process {
            // Already started
            Ok(())
        } else {
            let tunnel_config = self.config.clone();

            self.tunnel_process = Some(ManagedProcess::start(move || {
                tunnel_config.spawn()
            }).unwrap());

            Ok(())
        }
    }

    /// Stop the tunnel process if it is runnnig
    pub fn stop(&mut self) -> Result<()> {
        match self.tunnel_process.take() {
            None => Ok(()),
            Some(process) => process.shutdown()
        }
    }
}
<commit_msg>Allow dead code until this is plumbed into the API<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

// Assumes Unix
use std::io::prelude::*;
use std::fs::File;
use std::process::{ Child, Command };
use std::io::Result;
use managed_process::ManagedProcess;

pub type TunnelProcess = ManagedProcess;

pub struct Tunnel {
    config: TunnelConfig,
    pub tunnel_process: Option<TunnelProcess>
}

#[derive(Clone, Debug)]
pub struct TunnelConfig {
    local_port: u16,
    remote_host: String,
}

impl TunnelConfig {
    pub fn new(port: u16, remote_host: String) -> Self {
        TunnelConfig {
            local_port: port,
            remote_host: remote_host
        }
    }

    /// Describes how to spawn the ngrok process
    pub fn spawn(&self) -> Result<Child> {
        self.write_config_file();
        Command::new("ngrok")
                // Important! By default ngrok has a curses like view
                // which takes over terminal, setting log overrides that
                .arg("-log=stdout")
                .arg("-config")
                .arg("ngrok_config.yaml")
                .arg(self.local_port.to_string())
                .spawn()
    }

    /// Write out the config file that ngrok relies on - this means that this file will always be
    /// around in the right place, it doesn't clean up after itself
    fn write_config_file(&self) -> () {
        let mut file = File::create("ngrok_config.yaml").unwrap();
        let remote_host = self.remote_host.to_owned();

        file.write_fmt(format_args!("server_addr: {}\ntrust_host_root_certs: false", remote_host)).unwrap();
    }
}

impl Tunnel {

    /// Create a new Tunnel object containing the necessary
    /// configuration
    pub fn new(config: TunnelConfig) -> Tunnel {
        Tunnel {
            config: config,
            tunnel_process: None
        }
    }

    /// Start the Tunnel process if it has not already been started
    pub fn start(&mut self) -> Result<()> {
        if let Some(_) = self.tunnel_process {
            // Already started
            Ok(())
        } else {
            let tunnel_config = self.config.clone();

            self.tunnel_process = Some(ManagedProcess::start(move || {
                tunnel_config.spawn()
            }).unwrap());

            Ok(())
        }
    }

    /// Stop the tunnel process if it is runnnig
    #[allow(dead_code)]
    pub fn stop(&mut self) -> Result<()> {
        match self.tunnel_process.take() {
            None => Ok(()),
            Some(process) => process.shutdown()
        }
    }
}
<|endoftext|>


<commit_before>use std::str::Chars;
use std::fmt::{Show,Formatter};
use std::fmt;
use std::cast::transmute;

pub struct TokenValue<'a> {
    token: Token,
    value: &'a str
}

impl<'a> TokenValue<'a> {
    pub fn new(tok: Token, val: &'a str) -> TokenValue<'a> {
        TokenValue {
            token: tok,
            value: val
        }
    }
}

/// Lexer
pub struct Lexer<'a> {
    iter: *mut Chars<'a>,
    done: bool
}

/// Lexer tokens.
pub enum Token {
    PLUS,
    MINUS,
    INTEGER, // Any type of integer
    IDEN, // Identifier
    LPAREN,
    RPAREN,
    COLON
}

// An iden is identified by:
// /^([A-Za-z-+*^][A-Za-z0-9-_]*)$/
pub fn is_iden<'b>(ch: &'b str) -> bool {
    // Create a new iterator
    let mut iter = ch.chars().peekable();

    // Verify the first character.
    if !verify_iden_start(iter.next().unwrap()) {
        return false;
    }

    for x in iter {
        match x {
            '\n' => return false,
            '\r' => return false,
            ' ' => return false,
            _  =>  if !verify_iden_start(x) { return false }
        }
    }

    true
}

impl<'a> Lexer<'a> {
    pub fn new(input: &'a str) -> Lexer<'a> {
        let it = ~input.chars();
        Lexer {
            iter: unsafe { transmute(it) },
            done: false
        }
    }

    pub fn next_token(&mut self) -> Option<TokenValue<'a>> {
        unsafe {
            for c in *self.iter {
                match c {
                    '(' => return Some(TokenValue::new(LPAREN, &"(")),
                    ')' => return Some(TokenValue::new(RPAREN, &")")),
                    '+' => return Some(TokenValue::new(PLUS, &"+")),
                    '-' => return Some(TokenValue::new(MINUS, &"-")),
                    ':' => return Some(TokenValue::new(COLON, &":")),
                    '9' => return Some(TokenValue::new(INTEGER, &"9")),
                    '8' => return Some(TokenValue::new(INTEGER, &"8")),
                    '7' => return Some(TokenValue::new(INTEGER, &"7")),
                    '6' => return Some(TokenValue::new(INTEGER, &"6")),
                    '5' => return Some(TokenValue::new(INTEGER, &"5")),
                    '4' => return Some(TokenValue::new(INTEGER, &"4")),
                    '3' => return Some(TokenValue::new(INTEGER, &"3")),
                    '2' => return Some(TokenValue::new(INTEGER, &"2")),
                    '1' => return Some(TokenValue::new(INTEGER, &"1")),
                    '0' => return Some(TokenValue::new(INTEGER, &"0")),
                    _ => {

                        // Try and parse an identifier
                        let mut iden = ~"";
                        let mut prev = ~"";
                        iden.push_char(c);

                        for a in *self.iter {
                            // FIXME(TheHydroImpulse): A huge fucking hack.
                            if !is_iden(iden) && is_iden(prev) {
                            return Some(TokenValue::new(IDEN, unsafe {
                              transmute(prev.as_slice())
                            }));
                            }

                            prev = iden.clone();
                            iden.push_char(a);
                        }

                        if !is_iden(iden) && is_iden(prev) {
                            return Some(TokenValue::new(IDEN, unsafe {
                            transmute(prev.as_slice())
                            }));
                        }
                    }
                }
            }
        }
        None
    }
}

pub fn verify_iden_start(ch: char) -> bool {
    match ch {
        'A' => true,
        'a' => true,
        'B' => true,
        'b' => true,
        'C' => true,
        'c' => true,
        'D' => true,
        'd' => true,
        'E' => true,
        'e' => true,
        'F' => true,
        'f' => true,
        'G' => true,
        'g' => true,
        'H' => true,
        'h' => true,
        'I' => true,
        'i' => true,
        'J' => true,
        'j' => true,
        'K' => true,
        'k' => true,
        'L' => true,
        'l' => true,
        'M' => true,
        'm' => true,
        'N' => true,
        'n' => true,
        'O' => true,
        'o' => true,
        'P' => true,
        'p' => true,
        'Q' => true,
        'q' => true,
        'R' => true,
        'r' => true,
        'S' => true,
        's' => true,
        'T' => true,
        't' => true,
        'U' => true,
        'u' => true,
        'V' => true,
        'v' => true,
        'W' => true,
        'w' => true,
        'Y' => true,
        'y' => true,
        'Z' => true,
        'z' => true,
        '+' => true,
        '-' => true,
        '*' => true,
        _ => false
    }
}

impl Eq for Token {
    fn eq(&self, other: &Token) -> bool {
        match *self {
            PLUS => match *other { PLUS => true, _ => false },
            MINUS => match *other { MINUS => true, _ => false },
            INTEGER => match *other { INTEGER => true, _ => false },
            IDEN => match *other { IDEN => true, _ => false },
            LPAREN => match *other { LPAREN => true, _ => false },
            RPAREN => match *other { RPAREN => true, _ => false },
            COLON => match *other { COLON => true, _ => false }
        }
    }
}

impl Show for Token {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let c = match *self {
            PLUS => &"+",
            MINUS => &"-",
            INTEGER => &"integer",
            IDEN => &"iden",
            LPAREN => &"(",
            RPAREN => &")",
            COLON => ":"
        };

        write!(f.buf, "({})", c)
    }
}

#[cfg(test)]
mod test {
    use super::Lexer;
    use super::LPAREN;
    use super::TokenValue;

    #[test]
    fn next_token() {
        // Should spit out two tokens (LPAREN,RPAREN)
        let mut lex = Lexer::new(&"()");
        assert!(lex.next_token().unwrap().value == &"(");
        assert!(lex.next_token().unwrap().value == &")");
    }

    #[test]
    fn return_complex_tokens() {
        let mut lex = Lexer::new(&"(+(():830");

        assert!(lex.next_token().unwrap().value == &"(");
        assert!(lex.next_token().unwrap().value == &"+");
        assert!(lex.next_token().unwrap().value == &"(");
        assert!(lex.next_token().unwrap().value == &"(");
        assert!(lex.next_token().unwrap().value == &")");
        assert!(lex.next_token().unwrap().value == &":");
        assert!(lex.next_token().unwrap().value == &"8");
        assert!(lex.next_token().unwrap().value == &"3");
        assert!(lex.next_token().unwrap().value == &"0");
    }

    #[test]
    fn should_tokenize_identifier() {
        let mut lex = Lexer::new(&"(let)");

        assert_eq!(lex.next_token().unwrap().value, &"(");
        assert_eq!(lex.next_token().unwrap().value, &"let");
    }
}<commit_msg>works<commit_after>use std::str::Chars;
use std::fmt::{Show,Formatter};
use std::fmt;
use std::cast::transmute;

pub struct TokenValue {
    token: Token,
    value: ~str
}

impl TokenValue {
    pub fn new(tok: Token, val: ~str) -> TokenValue {
        TokenValue {
            token: tok,
            value: val
        }
    }
}

/// Lexer tokens.
pub enum Token {
    PLUS,
    MINUS,
    INTEGER, // Any type of integer
    IDEN, // Identifier
    LPAREN,
    RPAREN,
    COLON
}

/// Lexer
pub struct Lexer<'a> {
    iter: Chars<'a>,
    done: bool
}

impl<'a> Lexer<'a> {
    pub fn new(input: &'a str) -> Lexer<'a> {
        let it = input.chars();
        Lexer {
            iter: it,
            done: false
        }
    }

    pub fn next_token(&mut self) -> Option<TokenValue> {
        for c in self.iter {
            match c {
                ' ' => continue,
                '\r' => continue,
                '\n' => continue,
                '(' => return Some(TokenValue::new(LPAREN, ~"(")),
                ')' => return Some(TokenValue::new(RPAREN, ~")")),
                '+' => return Some(TokenValue::new(PLUS, ~"+")),
                '-' => return Some(TokenValue::new(MINUS, ~"-")),
                ':' => return Some(TokenValue::new(COLON, ~":")),
                '9' => return Some(TokenValue::new(INTEGER, ~"9")),
                '8' => return Some(TokenValue::new(INTEGER, ~"8")),
                '7' => return Some(TokenValue::new(INTEGER, ~"7")),
                '6' => return Some(TokenValue::new(INTEGER, ~"6")),
                '5' => return Some(TokenValue::new(INTEGER, ~"5")),
                '4' => return Some(TokenValue::new(INTEGER, ~"4")),
                '3' => return Some(TokenValue::new(INTEGER, ~"3")),
                '2' => return Some(TokenValue::new(INTEGER, ~"2")),
                '1' => return Some(TokenValue::new(INTEGER, ~"1")),
                '0' => return Some(TokenValue::new(INTEGER, ~"0")),
                _ => {

                    let mut it = self.iter;
                    let mut current = ~"";
                    let mut previous = ~"";

                    // Push the current character
                    current.push_char(c);

                    for character in it {
                        // Lets save the current buffer as the previous.
                        // This ensures that if this character makes the invalidation,
                        // we can return the previously valid string.
                        previous = current.clone();

                        // Push the new chracter onto the current buffer.
                        current.push_char(character);

                    //     // FIXME(TheHydroImpulse): A huge fucking hack.
                        if !is_iden(current) && is_iden(previous) {
                            return Some(TokenValue::new(IDEN, previous));
                    //      println!("ooo");
                        }
                    }

                    if !is_iden(current) && is_iden(previous) {
                        return Some(TokenValue::new(IDEN, previous));
                    }
                }
            }
        }
        None
    }
}

// An iden is identified by:
// /^([A-Za-z-+*^][A-Za-z0-9-_]*)$/
pub fn is_iden<'b>(ch: &'b str) -> bool {
    // Create a new iterator
    let mut iter = ch.chars().peekable();

    // Verify the first character.
    if !verify_iden_start(iter.next().unwrap()) {
        return false;
    }

    for x in iter {
        match x {
            '\n' => return false,
            '\r' => return false,
            ' ' => return false,
            _  =>  if !verify_iden_start(x) { return false }
        }
    }

    true
}

pub fn verify_iden_start(ch: char) -> bool {
    match ch {
        'A' => true,
        'a' => true,
        'B' => true,
        'b' => true,
        'C' => true,
        'c' => true,
        'D' => true,
        'd' => true,
        'E' => true,
        'e' => true,
        'F' => true,
        'f' => true,
        'G' => true,
        'g' => true,
        'H' => true,
        'h' => true,
        'I' => true,
        'i' => true,
        'J' => true,
        'j' => true,
        'K' => true,
        'k' => true,
        'L' => true,
        'l' => true,
        'M' => true,
        'm' => true,
        'N' => true,
        'n' => true,
        'O' => true,
        'o' => true,
        'P' => true,
        'p' => true,
        'Q' => true,
        'q' => true,
        'R' => true,
        'r' => true,
        'S' => true,
        's' => true,
        'T' => true,
        't' => true,
        'U' => true,
        'u' => true,
        'V' => true,
        'v' => true,
        'W' => true,
        'w' => true,
        'Y' => true,
        'y' => true,
        'Z' => true,
        'z' => true,
        '+' => true,
        '-' => true,
        '*' => true,
        _ => false
    }
}

impl Eq for Token {
    fn eq(&self, other: &Token) -> bool {
        match *self {
            PLUS => match *other { PLUS => true, _ => false },
            MINUS => match *other { MINUS => true, _ => false },
            INTEGER => match *other { INTEGER => true, _ => false },
            IDEN => match *other { IDEN => true, _ => false },
            LPAREN => match *other { LPAREN => true, _ => false },
            RPAREN => match *other { RPAREN => true, _ => false },
            COLON => match *other { COLON => true, _ => false }
        }
    }
}

impl Show for Token {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let c = match *self {
            PLUS => &"+",
            MINUS => &"-",
            INTEGER => &"integer",
            IDEN => &"iden",
            LPAREN => &"(",
            RPAREN => &")",
            COLON => ":"
        };

        write!(f.buf, "({})", c)
    }
}

#[cfg(test)]
mod test {
    use super::Lexer;
    use super::LPAREN;
    use super::TokenValue;

    #[test]
    fn next_token() {
        // Should spit out two tokens (LPAREN,RPAREN)
        let mut lex = Lexer::new(&"()");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~")");
    }

    #[test]
    fn return_complex_tokens() {
        let mut lex = Lexer::new(&"(+(():830");

        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~"+");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~"(");
        assert!(lex.next_token().unwrap().value == ~")");
        assert!(lex.next_token().unwrap().value == ~":");
        assert!(lex.next_token().unwrap().value == ~"8");
        assert!(lex.next_token().unwrap().value == ~"3");
        assert!(lex.next_token().unwrap().value == ~"0");
    }

    #[test]
    fn should_tokenize_identifier() {
        let mut lex = Lexer::new(&"(let)");

        assert_eq!(lex.next_token().unwrap().value, ~"(");
        assert_eq!(lex.next_token().unwrap().value, ~"let");
    }
}<|endoftext|>