<commit_before>use std::cmp;

use grid_traits::GridDimensions;
use units::{ColumnIndex, ColumnLength, ColumnsCount, EdgesCount, NodesCount, RowIndex, RowLength,
            RowsCount};

#[derive(Debug, Copy, Clone)]
pub struct RectGridDimensions {
    row_width: RowLength,
    column_height: ColumnLength,
}

impl RectGridDimensions {
    pub fn new(row_width: RowLength, column_height: ColumnLength) -> RectGridDimensions {
        RectGridDimensions {
            row_width: row_width,
            column_height: column_height,
        }
    }
}

impl GridDimensions for RectGridDimensions {
    fn size(&self) -> NodesCount {
        NodesCount(self.row_width.0 * self.column_height.0)
    }

    fn rows(&self) -> RowsCount {
        RowsCount(self.column_height.0)
    }

    fn row_length(&self, _: Option<RowIndex>) -> Option<RowLength> {
        Some(self.row_width)
    }

    fn columns(&self) -> ColumnsCount {
        ColumnsCount(self.row_width.0)
    }

    fn column_length(&self, _: Option<ColumnIndex>) -> ColumnLength {
        self.column_height
    }

    fn graph_size(&self) -> (NodesCount, EdgesCount) {
        let cells_count = self.size();
        let edges_count_hint = 4 * cells_count.0 -
                               4 * cmp::max(self.row_width.0, self.column_height.0);
        (cells_count, EdgesCount(edges_count_hint))
    }
}
<commit_msg>inline RectGridDimensions accessors.<commit_after>use std::cmp;

use grid_traits::GridDimensions;
use units::{ColumnIndex, ColumnLength, ColumnsCount, EdgesCount, NodesCount, RowIndex, RowLength,
            RowsCount};

#[derive(Debug, Copy, Clone)]
pub struct RectGridDimensions {
    row_width: RowLength,
    column_height: ColumnLength,
}

impl RectGridDimensions {
    pub fn new(row_width: RowLength, column_height: ColumnLength) -> RectGridDimensions {
        RectGridDimensions {
            row_width: row_width,
            column_height: column_height,
        }
    }
}

impl GridDimensions for RectGridDimensions {

    #[inline(always)]
    fn size(&self) -> NodesCount {
        NodesCount(self.row_width.0 * self.column_height.0)
    }

    #[inline(always)]
    fn rows(&self) -> RowsCount {
        RowsCount(self.column_height.0)
    }

    #[inline(always)]
    fn row_length(&self, _: Option<RowIndex>) -> Option<RowLength> {
        Some(self.row_width)
    }

    #[inline(always)]
    fn columns(&self) -> ColumnsCount {
        ColumnsCount(self.row_width.0)
    }

    #[inline(always)]
    fn column_length(&self, _: Option<ColumnIndex>) -> ColumnLength {
        self.column_height
    }

    fn graph_size(&self) -> (NodesCount, EdgesCount) {
        let cells_count = self.size();
        let edges_count_hint = 4 * cells_count.0 -
                               4 * cmp::max(self.row_width.0, self.column_height.0);
        (cells_count, EdgesCount(edges_count_hint))
    }
}
<|endoftext|>


<commit_before>use extra::json;
use extra::serialize::Decodable;

fn maybe_extract_from_json_object<T: Decodable<json::Decoder>>(
        obj: &json::Object, id: &~str) -> Option<T> {
    let found = match obj.find(id) {
        Some(s) => s.clone(),
        None => return None,
    };
    let mut decoder = json::Decoder::init(found);
    Decodable::decode(&mut decoder)
}

fn extract_from_json_object<T: Decodable<json::Decoder>>(obj: &json::Object, id: &~str) -> T {
    maybe_extract_from_json_object(obj, id).unwrap_or_else(|| {
        fail!("Didn't find id `{}` or an incorrect type in `{}`", *id, json::Object(~obj.clone()).to_str());
    })
}

fn expect_json_object<'a>(json: &'a json::Json) -> &'a json::Object {
    match *json {
        json::Object(~ref obj) => obj,
        _ => fail!("Expected an object, got {:?}", json),
    }
}

pub static API_VERSION: int = 3;

pub static API_KEY: &'static str = "def2ba77d002afeec898674ede24fe10828ad8a5";

pub struct ApiKey(~str);

#[deriving(Clone)]
pub struct PlayToken(~str);

pub struct Response<T> {
    status: ~str,
    errors: Option<~str>,
    notices: Option<~str>,
    logged_in: bool,
    api_version: uint,
    contents: Option<T>,
}

impl <T> Response<T> {
    fn from_json(json: &json::Json, contents: Option<T>) -> Response<T> {
        let obj = expect_json_object(json);
        Response::from_json_obj(obj, contents)
    }

    fn from_json_obj(obj: &json::Object, contents: Option<T>) -> Response<T> {
        Response {
            status: extract_from_json_object(obj, &~"status"),
            errors: maybe_extract_from_json_object(obj, &~"errors"),
            notices: maybe_extract_from_json_object(obj, &~"notices"),
            logged_in: maybe_extract_from_json_object(obj, &~"logged_in").unwrap_or(false),
            api_version: extract_from_json_object(obj, &~"api_version"),
            contents: contents,
        }
    }
}

#[deriving(Decodable, Clone)]
pub struct CoverUrls {
    sq56: ~str,
    sq100: ~str,
    sq133: ~str,
    max133w: ~str,
    max200: ~str,
    sq250: ~str,
    sq500: ~str,
    max1024: ~str,
    original: ~str,
}

impl CoverUrls {
    pub fn from_json(json: json::Json) -> CoverUrls {
        let mut decoder = json::Decoder::init(json);
        Decodable::decode(&mut decoder)
    }
}

#[deriving(Decodable, Clone)]
pub struct Mix {
    id: uint,
    path: ~str,
    web_path: ~str,
    name: ~str,
    description: ~str,
    plays_count: uint,
    likes_count: uint,
    certification: Option<~str>,
    // TODO parse this...
    tag_list_cache: ~str,
    duration: uint,
    tracks_count: uint,
    nsfw: bool,
    liked_by_current_user: bool,
    cover_urls: CoverUrls,
    // TODO parse this...
    first_published_at: ~str,
    user_id: uint,
}

impl Mix {
    pub fn from_json(json: &json::Json) -> Mix {
        let obj = expect_json_object(json);
        Mix {
            id: extract_from_json_object(obj, &~"id"),
            path: extract_from_json_object(obj, &~"path"),
            web_path: extract_from_json_object(obj, &~"web_path"),
            name: extract_from_json_object(obj, &~"name"),
            description: extract_from_json_object(obj, &~"description"),
            plays_count: extract_from_json_object(obj, &~"plays_count"),
            likes_count: extract_from_json_object(obj, &~"likes_count"),
            certification: maybe_extract_from_json_object(obj, &~"certification"),
            tag_list_cache: maybe_extract_from_json_object(obj, &~"tags_list_cache").unwrap_or_default(),
            duration: extract_from_json_object(obj, &~"duration"),
            tracks_count: extract_from_json_object(obj, &~"tracks_count"),
            nsfw: maybe_extract_from_json_object(obj, &~"nsfw").unwrap_or_default(),
            liked_by_current_user: maybe_extract_from_json_object(obj, &~"liked_by_current_user").unwrap_or_default(),
            cover_urls: CoverUrls::from_json(obj.find(&~"cover_urls").unwrap().clone()),
            first_published_at: extract_from_json_object(obj, &~"first_published_at"),
            user_id: extract_from_json_object(obj, &~"user_id"),
        }
    }
}

#[deriving(Decodable)]
struct MixSet {
    mixes: ~[Mix],
    smart_id: ~str,
    smart_type: ~str,
    path: ~str,
    name: ~str,
    web_path: ~str,
}

impl MixSet {
    pub fn from_json(json: &json::Json) -> MixSet {
        let obj = expect_json_object(json);
        let mixes_list = match obj.find(&~"mixes") {
            Some(&json::List(ref list)) => list,
            _ => fail!("expected mixes list in mix set, got {:?}", obj)
        };
        let mixes = mixes_list.map(|json| { Mix::from_json(json) });
        MixSet {
            mixes: mixes,
            smart_id: extract_from_json_object(obj, &~"smart_id"),
            smart_type: extract_from_json_object(obj, &~"smart_type"),
            path: extract_from_json_object(obj, &~"path"),
            name: extract_from_json_object(obj, &~"name"),
            web_path: extract_from_json_object(obj, &~"web_path"),
        }
    }
}

#[deriving(Clone, Decodable)]
struct Track {
    id: uint,
    name: ~str,
    performer: ~str,
    release_name: Option<~str>,
    year: Option<int>,
    track_file_stream_url: ~str,
    buy_link: ~str,
    faved_by_current_user: bool,
    url: ~str,
}

impl Track {
    pub fn from_json(json: json::Json) -> Track {
        let mut decoder = json::Decoder::init(json);
        Decodable::decode(&mut decoder)
    }
}

#[deriving(Decodable)]
struct PlayState {
    at_beginning: bool,
    at_last_track: bool,
    at_end: bool,
    skip_allowed: bool,
    track: Track,
}

impl PlayState {
    pub fn from_json(json: json::Json) -> PlayState {
        let mut decoder = json::Decoder::init(json);
        Decodable::decode(&mut decoder)
    }
}

pub fn parse_mix_set_response(json: &json::Json) -> Response<MixSet> {
    let obj = expect_json_object(json);
    let mix_set = obj.find(&~"mix_set").map(|ms| MixSet::from_json(ms));
    Response::from_json(json, mix_set)
}

pub fn parse_play_token_response(json: &json::Json) -> Response<PlayToken> {
    let obj = expect_json_object(json);
    let pt = maybe_extract_from_json_object(obj, &~"play_token").map(|pt| PlayToken(pt));
    Response::from_json(json, pt)
}

pub fn parse_play_state_response(json: &json::Json) -> Response<PlayState> {
    let obj = expect_json_object(json);
    debug!("play state json {}", json.to_str());
    let ps = obj.find(&~"set").map(|set| PlayState::from_json(set.clone()));
    Response::from_json(json, ps)
}
<commit_msg>Fix for stdlib changes<commit_after>use extra::json;
use extra::serialize::Decodable;

fn maybe_extract_from_json_object<T: Decodable<json::Decoder>>(
        obj: &json::Object, id: &~str) -> Option<T> {
    let found = match obj.find(id) {
        Some(s) => s.clone(),
        None => return None,
    };
    let mut decoder = json::Decoder::new(found);
    Decodable::decode(&mut decoder)
}

fn extract_from_json_object<T: Decodable<json::Decoder>>(obj: &json::Object, id: &~str) -> T {
    maybe_extract_from_json_object(obj, id).unwrap_or_else(|| {
        fail!("Didn't find id `{}` or an incorrect type in `{}`", *id, json::Object(~obj.clone()).to_str());
    })
}

fn expect_json_object<'a>(json: &'a json::Json) -> &'a json::Object {
    match *json {
        json::Object(~ref obj) => obj,
        _ => fail!("Expected an object, got {:?}", json),
    }
}

pub static API_VERSION: int = 3;

pub static API_KEY: &'static str = "def2ba77d002afeec898674ede24fe10828ad8a5";

pub struct ApiKey(~str);

#[deriving(Clone)]
pub struct PlayToken(~str);

pub struct Response<T> {
    status: ~str,
    errors: Option<~str>,
    notices: Option<~str>,
    logged_in: bool,
    api_version: uint,
    contents: Option<T>,
}

impl <T> Response<T> {
    fn from_json(json: &json::Json, contents: Option<T>) -> Response<T> {
        let obj = expect_json_object(json);
        Response::from_json_obj(obj, contents)
    }

    fn from_json_obj(obj: &json::Object, contents: Option<T>) -> Response<T> {
        Response {
            status: extract_from_json_object(obj, &~"status"),
            errors: maybe_extract_from_json_object(obj, &~"errors"),
            notices: maybe_extract_from_json_object(obj, &~"notices"),
            logged_in: maybe_extract_from_json_object(obj, &~"logged_in").unwrap_or(false),
            api_version: extract_from_json_object(obj, &~"api_version"),
            contents: contents,
        }
    }
}

#[deriving(Decodable, Clone)]
pub struct CoverUrls {
    sq56: ~str,
    sq100: ~str,
    sq133: ~str,
    max133w: ~str,
    max200: ~str,
    sq250: ~str,
    sq500: ~str,
    max1024: ~str,
    original: ~str,
}

impl CoverUrls {
    pub fn from_json(json: json::Json) -> CoverUrls {
        let mut decoder = json::Decoder::new(json);
        Decodable::decode(&mut decoder)
    }
}

#[deriving(Decodable, Clone)]
pub struct Mix {
    id: uint,
    path: ~str,
    web_path: ~str,
    name: ~str,
    description: ~str,
    plays_count: uint,
    likes_count: uint,
    certification: Option<~str>,
    // TODO parse this...
    tag_list_cache: ~str,
    duration: uint,
    tracks_count: uint,
    nsfw: bool,
    liked_by_current_user: bool,
    cover_urls: CoverUrls,
    // TODO parse this...
    first_published_at: ~str,
    user_id: uint,
}

impl Mix {
    pub fn from_json(json: &json::Json) -> Mix {
        let obj = expect_json_object(json);
        Mix {
            id: extract_from_json_object(obj, &~"id"),
            path: extract_from_json_object(obj, &~"path"),
            web_path: extract_from_json_object(obj, &~"web_path"),
            name: extract_from_json_object(obj, &~"name"),
            description: extract_from_json_object(obj, &~"description"),
            plays_count: extract_from_json_object(obj, &~"plays_count"),
            likes_count: extract_from_json_object(obj, &~"likes_count"),
            certification: maybe_extract_from_json_object(obj, &~"certification"),
            tag_list_cache: maybe_extract_from_json_object(obj, &~"tags_list_cache").unwrap_or_default(),
            duration: extract_from_json_object(obj, &~"duration"),
            tracks_count: extract_from_json_object(obj, &~"tracks_count"),
            nsfw: maybe_extract_from_json_object(obj, &~"nsfw").unwrap_or_default(),
            liked_by_current_user: maybe_extract_from_json_object(obj, &~"liked_by_current_user").unwrap_or_default(),
            cover_urls: CoverUrls::from_json(obj.find(&~"cover_urls").unwrap().clone()),
            first_published_at: extract_from_json_object(obj, &~"first_published_at"),
            user_id: extract_from_json_object(obj, &~"user_id"),
        }
    }
}

#[deriving(Decodable)]
struct MixSet {
    mixes: ~[Mix],
    smart_id: ~str,
    smart_type: ~str,
    path: ~str,
    name: ~str,
    web_path: ~str,
}

impl MixSet {
    pub fn from_json(json: &json::Json) -> MixSet {
        let obj = expect_json_object(json);
        let mixes_list = match obj.find(&~"mixes") {
            Some(&json::List(ref list)) => list,
            _ => fail!("expected mixes list in mix set, got {:?}", obj)
        };
        let mixes = mixes_list.map(|json| { Mix::from_json(json) });
        MixSet {
            mixes: mixes,
            smart_id: extract_from_json_object(obj, &~"smart_id"),
            smart_type: extract_from_json_object(obj, &~"smart_type"),
            path: extract_from_json_object(obj, &~"path"),
            name: extract_from_json_object(obj, &~"name"),
            web_path: extract_from_json_object(obj, &~"web_path"),
        }
    }
}

#[deriving(Clone, Decodable)]
struct Track {
    id: uint,
    name: ~str,
    performer: ~str,
    release_name: Option<~str>,
    year: Option<int>,
    track_file_stream_url: ~str,
    buy_link: ~str,
    faved_by_current_user: bool,
    url: ~str,
}

impl Track {
    pub fn from_json(json: json::Json) -> Track {
        let mut decoder = json::Decoder::new(json);
        Decodable::decode(&mut decoder)
    }
}

#[deriving(Decodable)]
struct PlayState {
    at_beginning: bool,
    at_last_track: bool,
    at_end: bool,
    skip_allowed: bool,
    track: Track,
}

impl PlayState {
    pub fn from_json(json: json::Json) -> PlayState {
        let mut decoder = json::Decoder::new(json);
        Decodable::decode(&mut decoder)
    }
}

pub fn parse_mix_set_response(json: &json::Json) -> Response<MixSet> {
    let obj = expect_json_object(json);
    let mix_set = obj.find(&~"mix_set").map(|ms| MixSet::from_json(ms));
    Response::from_json(json, mix_set)
}

pub fn parse_play_token_response(json: &json::Json) -> Response<PlayToken> {
    let obj = expect_json_object(json);
    let pt = maybe_extract_from_json_object(obj, &~"play_token").map(|pt| PlayToken(pt));
    Response::from_json(json, pt)
}

pub fn parse_play_state_response(json: &json::Json) -> Response<PlayState> {
    let obj = expect_json_object(json);
    debug!("play state json {}", json.to_str());
    let ps = obj.find(&~"set").map(|set| PlayState::from_json(set.clone()));
    Response::from_json(json, ps)
}
<|endoftext|>


<commit_before>use base::world::{self, Chunk};
use base::math::*;
use glium;
use Camera;
use render::ToArr;
use std::collections::VecDeque;
use std::f32::consts;

/// Graphical representation of the `base::Chunk`.
pub struct ChunkView {
    vertices: glium::VertexBuffer<Vertex>,
    program: glium::Program,
    pillars_positions: Vec<Point2f>,
    index_buffer: glium::index::IndexBuffer<u32>,
}
/// Calculates one Point-coordinates of a Hexagon
fn hex_corner(size: f32, i: i32) -> (f32, f32) {
    let angle_deg = 60.0 * (i as f32) + 30.0;
    let angle_rad = (consts::PI / 180.0) * angle_deg;

    (size * angle_rad.cos(), size * angle_rad.sin())
}

impl ChunkView {
    /// Creates the graphical representation of given chunk at the given chunk
    /// offset
    pub fn from_chunk<F>(_chunk: &Chunk, offset: AxialPoint, facade: &F) -> Self
        where F: glium::backend::Facade
    {

        // Create one hexagon for this chunk
        let mut hexagon_vertex_buffer = VecDeque::new();
        for i in 0..6 {
            let raw_modell = hex_corner(world::HEX_OUTER_RADIUS, i);

            hexagon_vertex_buffer.push_front(Vertex {
                position: [raw_modell.0, raw_modell.1, world::PILLAR_STEP_HEIGHT / 2.0],
                color: [0.15 * i as f32, 0.0, 0.0],
            });

            hexagon_vertex_buffer.push_back(Vertex {
                position: [raw_modell.0, raw_modell.1, -1.0 * (world::PILLAR_STEP_HEIGHT / 2.0)],
                color: [1.0 - 0.15 * i as f32, 0.15 * i as f32, 0.0],
            });

        }

        // convert to vector
        let mut final_buffer = Vec::new();
        for element in hexagon_vertex_buffer {
            final_buffer.push(element);
        }

        let vbuf = glium::VertexBuffer::new(facade, &final_buffer).unwrap();
        let prog = glium::Program::from_source(facade,
                                               include_str!("chunk_std.vert"),
                                               include_str!("chunk_std.frag"),
                                               None)
            .unwrap();

        let mut positions = Vec::new();
        for q in 0..world::CHUNK_SIZE {
            for r in 0..world::CHUNK_SIZE {
                let pos = offset.to_real() + AxialVector::new(q.into(), r.into()).to_real();
                positions.push(pos);
            }
        }

        // Indecies
        let raw_index_buffer = [5, 0, 1, 2, 5, 1, 4, 5, 2, 3, 4, 2 /* TOP */, 6, 7, 8, 8, 9,
                                6, 9, 11, 6, 9, 10, 11 /* BOTTOM */, 6, 5, 4, 7, 6, 4, 6, 0,
                                5, 11, 0, 6, 10, 1, 0, 11, 10, 0, 9, 2, 1, 10, 9, 1, 8, 3, 2, 9,
                                8, 2, 7, 4, 3, 8, 7, 3 /* Body */];

        let ibuf = glium::index::IndexBuffer::new(facade,
                                                  glium::index::PrimitiveType::TrianglesList,
                                                  &raw_index_buffer)
            .unwrap();

        ChunkView {
            vertices: vbuf,
            program: prog,
            pillars_positions: positions,
            index_buffer: ibuf,
        }
    }

    pub fn draw<S>(&self, surface: &mut S, camera: &Camera)
        where S: glium::Surface
    {

        for pillar_pos in &self.pillars_positions {
            let uniforms = uniform!{
              scale_matrix:[[1.0,0.0,0.0,0.0]
                      ,[0.0,1.0,0.0,0.0],
                      //FIXME 5.0 heightvalue
                      [0.0,0.0,1.0,0.0],
                      [0.0,0.0,0.0,1.0f32]],
                offset: [pillar_pos.x, pillar_pos.y],
                proj_matrix: camera.proj_matrix().to_arr(),
                view_matrix: camera.view_matrix().to_arr(),
            };

            let params = glium::DrawParameters {
                depth: glium::Depth {
                    write: true,
                    test: glium::draw_parameters::DepthTest::IfLess,
                    ..Default::default()
                },
                backface_culling: glium::draw_parameters::BackfaceCullingMode::CullCounterClockwise,
                ..Default::default()
            };

            surface.draw(&self.vertices,
                      &self.index_buffer,
                      &self.program,
                      &uniforms,
                      &params)
                .unwrap();

        }

    }
}

#[derive(Debug, Copy, Clone)]
struct Vertex {
    position: [f32; 3],
    color: [f32; 3],
}

implement_vertex!(Vertex, position, color);
<commit_msg>fixed format<commit_after>use base::world::{self, Chunk};
use base::math::*;
use glium;
use Camera;
use render::ToArr;
use std::collections::VecDeque;
use std::f32::consts;

/// Graphical representation of the `base::Chunk`.
pub struct ChunkView {
    vertices: glium::VertexBuffer<Vertex>,
    program: glium::Program,
    pillars_positions: Vec<Point2f>,
    index_buffer: glium::index::IndexBuffer<u32>,
}
/// Calculates one Point-coordinates of a Hexagon
fn hex_corner(size: f32, i: i32) -> (f32, f32) {
    let angle_deg = 60.0 * (i as f32) + 30.0;
    let angle_rad = (consts::PI / 180.0) * angle_deg;

    (size * angle_rad.cos(), size * angle_rad.sin())
}

impl ChunkView {
    /// Creates the graphical representation of given chunk at the given chunk
    /// offset
    pub fn from_chunk<F>(_chunk: &Chunk, offset: AxialPoint, facade: &F) -> Self
        where F: glium::backend::Facade
    {

        // Create one hexagon for this chunk
        let mut hexagon_vertex_buffer = VecDeque::new();
        for i in 0..6 {
            let (x, y) = hex_corner(world::HEX_OUTER_RADIUS, i);

            hexagon_vertex_buffer.push_front(Vertex {
                position: [x, y, world::PILLAR_STEP_HEIGHT],
                color: [0.15 * i as f32, 0.0, 0.0],
            });

            hexagon_vertex_buffer.push_back(Vertex {
                position: [x, y, -1.0 * world::PILLAR_STEP_HEIGHT],
                color: [1.0 - 0.15 * i as f32, 0.15 * i as f32, 0.0],
            });

        }

        // convert to vector
        let mut final_buffer = Vec::new();
        for element in hexagon_vertex_buffer {
            final_buffer.push(element);
        }

        let vbuf = glium::VertexBuffer::new(facade, &final_buffer).unwrap();
        let prog = glium::Program::from_source(facade,
                                               include_str!("chunk_std.vert"),
                                               include_str!("chunk_std.frag"),
                                               None)
            .unwrap();

        let mut positions = Vec::new();
        for q in 0..world::CHUNK_SIZE {
            for r in 0..world::CHUNK_SIZE {
                let pos = offset.to_real() + AxialVector::new(q.into(), r.into()).to_real();
                positions.push(pos);
            }
        }

        // Indecies
        let raw_index_buffer = [5, 0, 1, 2, 5, 1, 4, 5, 2, 3, 4, 2 /* TOP */, 6, 7, 8, 8, 9,
                                6, 9, 11, 6, 9, 10, 11 /* BOTTOM */, 6, 5, 4, 7, 6, 4, 6, 0,
                                5, 11, 0, 6, 10, 1, 0, 11, 10, 0, 9, 2, 1, 10, 9, 1, 8, 3, 2, 9,
                                8, 2, 7, 4, 3, 8, 7, 3 /* Body */];

        let ibuf = glium::index::IndexBuffer::new(facade,
                                                  glium::index::PrimitiveType::TrianglesList,
                                                  &raw_index_buffer)
            .unwrap();

        ChunkView {
            vertices: vbuf,
            program: prog,
            pillars_positions: positions,
            index_buffer: ibuf,
        }
    }

    pub fn draw<S>(&self, surface: &mut S, camera: &Camera)
        where S: glium::Surface
    {

        for pillar_pos in &self.pillars_positions {
            let uniforms = uniform!{
              scale_matrix:[[1.0,0.0,0.0,0.0]
                      ,[0.0,1.0,0.0,0.0],
                      //FIXME 5.0 heightvalue
                      [0.0,0.0,1.0,0.0],
                      [0.0,0.0,0.0,1.0f32]],
                offset: [pillar_pos.x, pillar_pos.y],
                proj_matrix: camera.proj_matrix().to_arr(),
                view_matrix: camera.view_matrix().to_arr(),
            };

            let params = glium::DrawParameters {
                depth: glium::Depth {
                    write: true,
                    test: glium::draw_parameters::DepthTest::IfLess,
                    ..Default::default()
                },
                backface_culling: glium::draw_parameters::BackfaceCullingMode::CullCounterClockwise,
                ..Default::default()
            };

            surface.draw(&self.vertices,
                      &self.index_buffer,
                      &self.program,
                      &uniforms,
                      &params)
                .unwrap();

        }

    }
}

#[derive(Debug, Copy, Clone)]
struct Vertex {
    position: [f32; 3],
    color: [f32; 3],
}

implement_vertex!(Vertex, position, color);
<|endoftext|>


<commit_before>use lib::alias_dist::AliasDistribution;
use lib::error::MarkovpassError;
use std::collections::HashMap;

struct MarkovChainIterator<'a> {
    markov_chain: &'a PassphraseMarkovChain<'a>,
    current: &'a str,
}

impl<'a> Iterator for MarkovChainIterator<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<&'a str> {
        let last = self.current;
        self.current = self.markov_chain.get_next_ngram(&self.current);

        Some(last)
    }
}

#[derive(Debug)]
struct MarkovNode<T> {
    pub value: T,
    transitions: Vec<T>,
    dist: AliasDistribution,
}

impl<T> MarkovNode<T> {
    pub fn new(value: T, values: Vec<T>, weights: Vec<f64>) -> MarkovNode<T> {
        MarkovNode {
            value: value,
            transitions: values,
            dist: AliasDistribution::new(&weights).unwrap(),
        }
    }

    pub fn next(&self) -> &T {
        &self.transitions[self.dist.choice()]
    }

    pub fn entropy(&self) -> f64 {
        self.dist.entropy
    }
}

#[derive(Debug)]
pub struct PassphraseMarkovChain<'a> {
    nodes: HashMap<&'a str, MarkovNode<&'a str>>,
    starting_ngrams: Vec<&'a str>,
    starting_dist: AliasDistribution,
}

impl<'a> PassphraseMarkovChain<'a> {
    pub fn new(
        ngrams: impl Iterator<Item = &'a str>,
    ) -> Result<PassphraseMarkovChain<'a>, MarkovpassError> {
        // Count transitions and viable starting ngrams.
        // To get natural sounding words, starting ngrams should be at word start.
        let mut transition_counters: HashMap<&str, HashMap<&str, usize>> = HashMap::new();
        let mut starting_ngram_counts: HashMap<&str, usize> = HashMap::new();
        let mut ngrams = ngrams.peekable();
        let first_ngram = ngrams.peek().ok_or(MarkovpassError::NoNgrams)?.clone();
        while let Some(current_ngram) = ngrams.next() {
            if current_ngram.starts_with(" ") {
                *starting_ngram_counts.entry(current_ngram).or_insert(0) += 1;
            }
            // To guarantee every ngram has at least one valid transition, let the last ngram
            // transition to the first.
            let next_ngram = ngrams.peek().unwrap_or(&first_ngram);
            *transition_counters
                .entry(current_ngram)
                .or_insert(HashMap::new())
                .entry(next_ngram)
                .or_insert(0) += 1;
        }

        // Generate the starting ngram probability distribution.
        let mut starting_ngrams = Vec::with_capacity(starting_ngram_counts.len());
        let mut starting_ngram_weights = Vec::with_capacity(starting_ngram_counts.len());
        for (value, weight) in starting_ngram_counts.into_iter() {
            starting_ngrams.push(value);
            starting_ngram_weights.push(weight as f64);
        }
        let starting_dist = AliasDistribution::new(&starting_ngram_weights).unwrap();

        // Build all the MarkovNodes from the transition counts.
        let mut nodes: HashMap<&str, MarkovNode<&str>> = HashMap::new();
        let mut total_entropy: f64 = 0.0;
        for (ngram, transition_counts) in transition_counters.into_iter() {
            let mut values = Vec::with_capacity(transition_counts.len());
            let mut weights = Vec::with_capacity(transition_counts.len());
            for (value, weight) in transition_counts.into_iter() {
                values.push(value);
                weights.push(weight as f64);
            }

            let node = MarkovNode::new(ngram, values, weights);
            total_entropy += node.entropy();
            nodes.insert(ngram, node);
        }

        if total_entropy == 0.0 {
            return Err(MarkovpassError::NoEntropy);
        } else if starting_dist.entropy == 0.0 {
            return Err(MarkovpassError::NoStartOfWordEntropy);
        };

        Ok(PassphraseMarkovChain {
            nodes: nodes,
            starting_ngrams: starting_ngrams,
            starting_dist: starting_dist,
        })
    }

    pub fn passphrase(&self, min_entropy: f64) -> (String, f64) {
        let mut selected_ngrams = Vec::new();
        let mut entropy = self.starting_dist.entropy;

        for ngram in self.iter() {
            selected_ngrams.push(ngram.clone());
            entropy += self.ngram_entropy(&ngram);
            if entropy >= min_entropy && ngram.ends_with(" ") {
                break;
            }
        }

        // Include the first character from each ngram, and the whole final ngram.
        let tail = selected_ngrams.last().unwrap().chars().skip(1);
        let chars = selected_ngrams
            .iter()
            .map(|n| n.chars().next().unwrap())
            .chain(tail);
        let passphrase = chars.collect::<String>().trim().to_string();

        (passphrase, entropy)
    }

    fn iter(&self) -> MarkovChainIterator {
        MarkovChainIterator {
            markov_chain: &self,
            current: &self.get_starting_ngram(),
        }
    }

    fn get_starting_ngram(&self) -> &str {
        &self
            .nodes
            .get(&self.starting_ngrams[self.starting_dist.choice()])
            .unwrap()
            .value
    }

    fn get_next_ngram(&self, ngram: &str) -> &str {
        self.nodes.get(ngram).unwrap().next()
    }

    fn ngram_entropy(&self, ngram: &str) -> f64 {
        self.nodes.get(ngram).unwrap().entropy()
    }
}

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

    #[test]
    fn test_passphrasemarkovchain_new() {
        let ngrams = vec![" ti", "tic", "ic ", "c t", " to", "toc", "oc ", "c t"];
        let result = PassphraseMarkovChain::new(ngrams.iter().cloned());
        assert!(result.is_ok());
        let chain = result.unwrap();
        assert_eq!(chain.starting_ngrams.len(), 2);
        assert!(chain.starting_ngrams.contains(&" ti"));
        assert!(chain.starting_ngrams.contains(&" to"));
        assert_eq!(chain.starting_dist.entropy, 1.0);
        assert!(ngrams.contains(&chain.get_starting_ngram()));
        let (p, e) = chain.passphrase(60.0);
        assert_eq!(e, 60.0);
        assert_eq!(p.len(), 239);
    }

    #[test]
    fn test_passphrase_no_ngrams() {
        let result = PassphraseMarkovChain::new(std::iter::empty());
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), MarkovpassError::NoNgrams);
    }

    #[test]
    fn test_passphrase_no_entropy() {
        let ngrams = vec![" ab", "abc", "bcd", "cd ", "d a"];
        let result = PassphraseMarkovChain::new(ngrams.into_iter());
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), MarkovpassError::NoEntropy);
    }

    #[test]
    fn test_passphrases_no_starting_entropy() {
        let ngrams = vec![
            " ab", "abc", "bc ", "c a", " ab", "abc", "cbd", "bd ", "d a",
        ];
        let result = PassphraseMarkovChain::new(ngrams.into_iter());
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), MarkovpassError::NoStartOfWordEntropy);
    }
}
<commit_msg>A couple minor style improvements in markovchain.rs<commit_after>use lib::alias_dist::AliasDistribution;
use lib::error::MarkovpassError;
use std::collections::HashMap;

struct MarkovChainIterator<'a> {
    markov_chain: &'a PassphraseMarkovChain<'a>,
    current: &'a str,
}

impl<'a> Iterator for MarkovChainIterator<'a> {
    type Item = &'a str;

    fn next(&mut self) -> Option<Self::Item> {
        let last = self.current;
        self.current = self.markov_chain.get_next_ngram(&self.current);

        Some(last)
    }
}

#[derive(Debug)]
struct MarkovNode<T> {
    pub value: T,
    transitions: Vec<T>,
    dist: AliasDistribution,
}

impl<T> MarkovNode<T> {
    pub fn new(value: T, values: Vec<T>, weights: Vec<f64>) -> MarkovNode<T> {
        MarkovNode {
            value: value,
            transitions: values,
            dist: AliasDistribution::new(&weights).unwrap(),
        }
    }

    pub fn next(&self) -> &T {
        &self.transitions[self.dist.choice()]
    }

    pub fn entropy(&self) -> f64 {
        self.dist.entropy
    }
}

#[derive(Debug)]
pub struct PassphraseMarkovChain<'a> {
    nodes: HashMap<&'a str, MarkovNode<&'a str>>,
    starting_ngrams: Vec<&'a str>,
    starting_dist: AliasDistribution,
}

impl<'a> PassphraseMarkovChain<'a> {
    pub fn new(
        ngrams: impl Iterator<Item = &'a str>,
    ) -> Result<PassphraseMarkovChain<'a>, MarkovpassError> {
        // Count transitions and viable starting ngrams.
        // To get natural sounding words, starting ngrams should be at word start.
        let mut transition_counters: HashMap<&str, HashMap<&str, usize>> = HashMap::new();
        let mut starting_ngram_counts: HashMap<&str, usize> = HashMap::new();
        let mut ngrams = ngrams.peekable();
        let first_ngram = ngrams.peek().ok_or(MarkovpassError::NoNgrams)?.clone();
        while let Some(current_ngram) = ngrams.next() {
            if current_ngram.starts_with(" ") {
                *starting_ngram_counts.entry(current_ngram).or_insert(0) += 1;
            }
            // To guarantee every ngram has at least one valid transition, let the last ngram
            // transition to the first.
            let next_ngram = ngrams.peek().unwrap_or(&first_ngram);
            *transition_counters
                .entry(current_ngram)
                .or_insert(HashMap::new())
                .entry(next_ngram)
                .or_insert(0) += 1;
        }

        // Generate the starting ngram probability distribution.
        let mut starting_ngrams = Vec::with_capacity(starting_ngram_counts.len());
        let mut starting_ngram_weights = Vec::with_capacity(starting_ngram_counts.len());
        for (value, weight) in starting_ngram_counts.into_iter() {
            starting_ngrams.push(value);
            starting_ngram_weights.push(weight as f64);
        }
        let starting_dist = AliasDistribution::new(&starting_ngram_weights).unwrap();

        // Build all the MarkovNodes from the transition counts.
        let mut nodes: HashMap<&str, MarkovNode<&str>> = HashMap::new();
        let mut total_entropy: f64 = 0.0;
        for (ngram, transition_counts) in transition_counters.into_iter() {
            let mut values = Vec::with_capacity(transition_counts.len());
            let mut weights = Vec::with_capacity(transition_counts.len());
            for (value, weight) in transition_counts.into_iter() {
                values.push(value);
                weights.push(weight as f64);
            }

            let node = MarkovNode::new(ngram, values, weights);
            total_entropy += node.entropy();
            nodes.insert(ngram, node);
        }

        if total_entropy == 0.0 {
            return Err(MarkovpassError::NoEntropy);
        } else if starting_dist.entropy == 0.0 {
            return Err(MarkovpassError::NoStartOfWordEntropy);
        };

        Ok(PassphraseMarkovChain {
            nodes: nodes,
            starting_ngrams: starting_ngrams,
            starting_dist: starting_dist,
        })
    }

    pub fn passphrase(&self, min_entropy: f64) -> (String, f64) {
        let mut selected_ngrams = Vec::new();
        let mut entropy = self.starting_dist.entropy;

        for ngram in self.iter() {
            selected_ngrams.push(ngram);
            entropy += self.ngram_entropy(&ngram);
            if entropy >= min_entropy && ngram.ends_with(" ") {
                break;
            }
        }

        // Include the first character from each ngram, and the whole final ngram.
        let tail = selected_ngrams.last().unwrap().chars().skip(1);
        let chars = selected_ngrams
            .iter()
            .map(|n| n.chars().next().unwrap())
            .chain(tail);
        let passphrase = chars.collect::<String>().trim().to_string();

        (passphrase, entropy)
    }

    fn iter(&self) -> MarkovChainIterator {
        MarkovChainIterator {
            markov_chain: self,
            current: self.get_starting_ngram(),
        }
    }

    fn get_starting_ngram(&self) -> &str {
        &self
            .nodes
            .get(&self.starting_ngrams[self.starting_dist.choice()])
            .unwrap()
            .value
    }

    fn get_next_ngram(&self, ngram: &str) -> &str {
        self.nodes.get(ngram).unwrap().next()
    }

    fn ngram_entropy(&self, ngram: &str) -> f64 {
        self.nodes.get(ngram).unwrap().entropy()
    }
}

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

    #[test]
    fn test_passphrasemarkovchain_new() {
        let ngrams = vec![" ti", "tic", "ic ", "c t", " to", "toc", "oc ", "c t"];
        let result = PassphraseMarkovChain::new(ngrams.iter().cloned());
        assert!(result.is_ok());
        let chain = result.unwrap();
        assert_eq!(chain.starting_ngrams.len(), 2);
        assert!(chain.starting_ngrams.contains(&" ti"));
        assert!(chain.starting_ngrams.contains(&" to"));
        assert_eq!(chain.starting_dist.entropy, 1.0);
        assert!(ngrams.contains(&chain.get_starting_ngram()));
        let (p, e) = chain.passphrase(60.0);
        assert_eq!(e, 60.0);
        assert_eq!(p.len(), 239);
    }

    #[test]
    fn test_passphrase_no_ngrams() {
        let result = PassphraseMarkovChain::new(std::iter::empty());
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), MarkovpassError::NoNgrams);
    }

    #[test]
    fn test_passphrase_no_entropy() {
        let ngrams = vec![" ab", "abc", "bcd", "cd ", "d a"];
        let result = PassphraseMarkovChain::new(ngrams.into_iter());
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), MarkovpassError::NoEntropy);
    }

    #[test]
    fn test_passphrases_no_starting_entropy() {
        let ngrams = vec![
            " ab", "abc", "bc ", "c a", " ab", "abc", "cbd", "bd ", "d a",
        ];
        let result = PassphraseMarkovChain::new(ngrams.into_iter());
        assert!(result.is_err());
        assert_eq!(result.unwrap_err(), MarkovpassError::NoStartOfWordEntropy);
    }
}
<|endoftext|>


<commit_before>use na::{Scalar, Real, U1, U2, U3, U4, DefaultAllocator,
         Quaternion, Matrix2, Matrix3, Matrix4, Vector1, Vector2, Vector3, Vector4,
         Matrix2x3, Matrix2x4, Matrix3x2, Matrix3x4, Matrix4x2, Matrix4x3};

use traits::{Number, Alloc, Dimension};
use aliases::{Qua, Vec, Mat};

/// Creates a 2x2 matrix from a slice arranged in column-major order.
pub fn make_mat2<N: Scalar>(ptr: &[N]) -> Mat<N, U2, U2> {
    Matrix2::from_column_slice(ptr)
}

/// Creates a 2x2 matrix from a slice arranged in column-major order.
pub fn make_mat2x2<N: Scalar>(ptr: &[N]) -> Mat<N, U2, U2> {
    Matrix2::from_column_slice(ptr)
}

/// Creates a 2x3 matrix from a slice arranged in column-major order.
pub fn make_mat2x3<N: Scalar>(ptr: &[N]) -> Mat<N, U2, U3> {
    Matrix2x3::from_column_slice(ptr)
}

/// Creates a 2x4 matrix from a slice arranged in column-major order.
pub fn make_mat2x4<N: Scalar>(ptr: &[N]) -> Mat<N, U2, U4> {
    Matrix2x4::from_column_slice(ptr)
}

/// Creates a 3 matrix from a slice arranged in column-major order.
pub fn make_mat3<N: Scalar>(ptr: &[N]) -> Mat<N, U3, U3> {
    Matrix3::from_column_slice(ptr)
}

/// Creates a 3x2 matrix from a slice arranged in column-major order.
pub fn make_mat3x2<N: Scalar>(ptr: &[N]) -> Mat<N, U3, U2> {
    Matrix3x2::from_column_slice(ptr)
}

/// Creates a 3x3 matrix from a slice arranged in column-major order.
pub fn make_mat3x3<N: Scalar>(ptr: &[N]) -> Mat<N, U3, U3> {
    Matrix3::from_column_slice(ptr)
}

/// Creates a 3x4 matrix from a slice arranged in column-major order.
pub fn make_mat3x4<N: Scalar>(ptr: &[N]) -> Mat<N, U3, U4> {
    Matrix3x4::from_column_slice(ptr)
}

/// Creates a 4x4 matrix from a slice arranged in column-major order.
pub fn make_mat4<N: Scalar>(ptr: &[N]) -> Mat<N, U4, U4> {
    Matrix4::from_column_slice(ptr)
}

/// Creates a 4x2 matrix from a slice arranged in column-major order.
pub fn make_mat4x2<N: Scalar>(ptr: &[N]) -> Mat<N, U4, U2> {
    Matrix4x2::from_column_slice(ptr)
}

/// Creates a 4x3 matrix from a slice arranged in column-major order.
pub fn make_mat4x3<N: Scalar>(ptr: &[N]) -> Mat<N, U4, U3> {
    Matrix4x3::from_column_slice(ptr)
}

/// Creates a 4x4 matrix from a slice arranged in column-major order.
pub fn make_mat4x4<N: Scalar>(ptr: &[N]) -> Mat<N, U4, U4> {
    Matrix4::from_column_slice(ptr)
}

/// Creates a quaternion from a slice arranged as `[x, y, z, w]`.
pub fn make_quat<N: Real>(ptr: &[N]) -> Qua<N> {
    Quaternion::from_vector(Vector4::from_column_slice(ptr))
}

/// Creates a 1D vector from a slice.
pub fn make_vec1<N: Scalar>(v: &Vec<N, U1>) -> Vec<N, U1> {
    *v
}

/// Creates a 1D vector from another vector.
pub fn vec2_to_vec1<N: Scalar>(v: &Vec<N, U2>) -> Vec<N, U1> {
    Vector1::new(v.x)
}

/// Creates a 1D vector from another vector.
pub fn vec3_to_vec1<N: Scalar>(v: &Vec<N, U3>) -> Vec<N, U1> {
    Vector1::new(v.x)
}

/// Creates a 1D vector from another vector.
pub fn vec4_to_vec1<N: Scalar>(v: &Vec<N, U4>) -> Vec<N, U1> {
    Vector1::new(v.x)
}

/// Creates a 2D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec1_to_vec2<N: Number>(v: &Vec<N, U1>) -> Vec<N, U2> {
    Vector2::new(v.x, N::zero())
}

/// Creates a 2D vector from another vector.
pub fn vec2_to_vec2<N: Scalar>(v: &Vec<N, U2>) -> Vec<N, U2> {
    *v
}

/// Creates a 2D vector from another vector.
pub fn vec3_to_vec2<N: Scalar>(v: &Vec<N, U3>) -> Vec<N, U2> {
    Vector2::new(v.x, v.y)
}

/// Creates a 2D vector from another vector.
pub fn vec4_to_vec2<N: Scalar>(v: &Vec<N, U4>) -> Vec<N, U2> {
    Vector2::new(v.x, v.y)
}

/// Creates a 2D vector from a slice.
pub fn make_vec2<N: Scalar>(ptr: &[N]) -> Vec<N, U2> {
    Vector2::from_column_slice(ptr)
}

/// Creates a 3D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec1_to_vec3<N: Number>(v: &Vec<N, U1>) -> Vec<N, U3> {
    Vector3::new(v.x, N::zero(), N::zero())
}

/// Creates a 3D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec2_to_vec3<N: Number>(v: &Vec<N, U2>) -> Vec<N, U3> {
    Vector3::new(v.x, v.y, N::zero())
}

/// Creates a 3D vector from another vector.
pub fn vec3_to_vec3<N: Scalar>(v: &Vec<N, U3>) -> Vec<N, U3> {
    *v
}

/// Creates a 3D vector from another vector.
pub fn vec4_to_vec3<N: Scalar>(v: &Vec<N, U4>) -> Vec<N, U3> {
    Vector3::new(v.x, v.y, v.z)
}

/// Creates a 3D vector from another vector.
pub fn make_vec3<N: Scalar>(ptr: &[N]) -> Vec<N, U3> {
    Vector3::from_column_slice(ptr)
}

/// Creates a 4D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec1_to_vec4<N: Number>(v: &Vec<N, U1>) -> Vec<N, U4> {
    Vector4::new(v.x, N::zero(), N::zero(), N::zero())
}

/// Creates a 4D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec2_to_vec4<N: Number>(v: &Vec<N, U2>) -> Vec<N, U4> {
    Vector4::new(v.x, v.y, N::zero(), N::zero())
}

/// Creates a 4D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec3_to_vec4<N: Number>(v: &Vec<N, U3>) -> Vec<N, U4> {
    Vector4::new(v.x, v.y, v.z, N::zero())
}

/// Creates a 4D vector from another vector.
pub fn vec4_to_vec4<N: Scalar>(v: &Vec<N, U4>) -> Vec<N, U4> {
    *v
}

/// Creates a 4D vector from another vector.
pub fn make_vec4<N: Scalar>(ptr: &[N]) -> Vec<N, U4> {
    Vector4::from_column_slice(ptr)
}

/// Converts a matrix or vector to a slice arranged in column-major order.
pub fn value_ptr<N: Scalar, R: Dimension, C: Dimension>(x: &Mat<N, R, C>) -> &[N]
    where DefaultAllocator: Alloc<N, R, C> {
    x.as_slice()
}

/// Converts a matrix or vector to a mutable slice arranged in column-major order.
pub fn value_ptr_mut<N: Scalar, R: Dimension, C: Dimension>(x: &mut Mat<N, R, C>) -> &mut [N]
    where DefaultAllocator: Alloc<N, R, C> {
    x.as_mut_slice()
}

<commit_msg>Add conversion functions between square matrices.<commit_after>use na::{Scalar, Real, U1, U2, U3, U4, DefaultAllocator,
         Quaternion, Matrix2, Matrix3, Matrix4, Vector1, Vector2, Vector3, Vector4,
         Matrix2x3, Matrix2x4, Matrix3x2, Matrix3x4, Matrix4x2, Matrix4x3};

use traits::{Number, Alloc, Dimension};
use aliases::{Qua, Vec, Mat};

/// Creates a 2x2 matrix from a slice arranged in column-major order.
pub fn make_mat2<N: Scalar>(ptr: &[N]) -> Mat<N, U2, U2> {
    Matrix2::from_column_slice(ptr)
}

/// Creates a 2x2 matrix from a slice arranged in column-major order.
pub fn make_mat2x2<N: Scalar>(ptr: &[N]) -> Mat<N, U2, U2> {
    Matrix2::from_column_slice(ptr)
}

/// Creates a 2x3 matrix from a slice arranged in column-major order.
pub fn make_mat2x3<N: Scalar>(ptr: &[N]) -> Mat<N, U2, U3> {
    Matrix2x3::from_column_slice(ptr)
}

/// Creates a 2x4 matrix from a slice arranged in column-major order.
pub fn make_mat2x4<N: Scalar>(ptr: &[N]) -> Mat<N, U2, U4> {
    Matrix2x4::from_column_slice(ptr)
}

/// Creates a 3 matrix from a slice arranged in column-major order.
pub fn make_mat3<N: Scalar>(ptr: &[N]) -> Mat<N, U3, U3> {
    Matrix3::from_column_slice(ptr)
}

/// Creates a 3x2 matrix from a slice arranged in column-major order.
pub fn make_mat3x2<N: Scalar>(ptr: &[N]) -> Mat<N, U3, U2> {
    Matrix3x2::from_column_slice(ptr)
}

/// Creates a 3x3 matrix from a slice arranged in column-major order.
pub fn make_mat3x3<N: Scalar>(ptr: &[N]) -> Mat<N, U3, U3> {
    Matrix3::from_column_slice(ptr)
}

/// Creates a 3x4 matrix from a slice arranged in column-major order.
pub fn make_mat3x4<N: Scalar>(ptr: &[N]) -> Mat<N, U3, U4> {
    Matrix3x4::from_column_slice(ptr)
}

/// Creates a 4x4 matrix from a slice arranged in column-major order.
pub fn make_mat4<N: Scalar>(ptr: &[N]) -> Mat<N, U4, U4> {
    Matrix4::from_column_slice(ptr)
}

/// Creates a 4x2 matrix from a slice arranged in column-major order.
pub fn make_mat4x2<N: Scalar>(ptr: &[N]) -> Mat<N, U4, U2> {
    Matrix4x2::from_column_slice(ptr)
}

/// Creates a 4x3 matrix from a slice arranged in column-major order.
pub fn make_mat4x3<N: Scalar>(ptr: &[N]) -> Mat<N, U4, U3> {
    Matrix4x3::from_column_slice(ptr)
}

/// Creates a 4x4 matrix from a slice arranged in column-major order.
pub fn make_mat4x4<N: Scalar>(ptr: &[N]) -> Mat<N, U4, U4> {
    Matrix4::from_column_slice(ptr)
}

/// Converts a 2x2 matrix to a 3x3 matrix.
pub fn mat2_to_mat3<N: Number>(m: &Mat<N, U2, U2>) -> Mat<N, U3, U3> {
    let _0 = N::zero();
    let _1 = N::one();

    Matrix3::new(
        m.m11, m.m12, _0,
        m.m21, m.m22, _0,
        _0, _0, _1
    )
}

/// Converts a 3x3 matrix to a 2x2 matrix.
pub fn mat3_to_mat2<N: Scalar>(m: &Mat<N, U3, U3>) -> Mat<N, U2, U2> {
    Matrix2::new(
        m.m11, m.m12,
        m.m21, m.m22
    )
}

/// Converts a 3x3 matrix to a 4x4 matrix.
pub fn mat3_to_mat4<N: Number>(m: &Mat<N, U3, U3>) -> Mat<N, U4, U4> {
    let _0 = N::zero();
    let _1 = N::one();

    Matrix4::new(
        m.m11, m.m12, m.m13, _0,
        m.m21, m.m22, m.m23, _0,
        m.m31, m.m32, m.m33, _0,
        _0, _0, _0, _1,
    )
}

/// Converts a 4x4 matrix to a 3x3 matrix.
pub fn mat4_to_mat3<N: Scalar>(m: &Mat<N, U4, U4>) -> Mat<N, U3, U3> {
    Matrix3::new(
        m.m11, m.m12, m.m13,
        m.m21, m.m22, m.m23,
        m.m31, m.m32, m.m33,
    )
}

/// Converts a 2x2 matrix to a 4x4 matrix.
pub fn mat2_to_mat4<N: Number>(m: &Mat<N, U2, U2>) -> Mat<N, U4, U4> {
    let _0 = N::zero();
    let _1 = N::one();

    Matrix4::new(
        m.m11, m.m12, _0, _0,
        m.m21, m.m22, _0, _0,
        _0, _0, _1, _0,
        _0, _0, _0, _1,
    )
}

/// Converts a 4x4 matrix to a 2x2 matrix.
pub fn mat4_to_mat2<N: Scalar>(m: &Mat<N, U4, U4>) -> Mat<N, U2, U2> {
    Matrix2::new(
        m.m11, m.m12,
        m.m21, m.m22,
    )
}

/// Creates a quaternion from a slice arranged as `[x, y, z, w]`.
pub fn make_quat<N: Real>(ptr: &[N]) -> Qua<N> {
    Quaternion::from_vector(Vector4::from_column_slice(ptr))
}

/// Creates a 1D vector from a slice.
pub fn make_vec1<N: Scalar>(v: &Vec<N, U1>) -> Vec<N, U1> {
    *v
}

/// Creates a 1D vector from another vector.
pub fn vec2_to_vec1<N: Scalar>(v: &Vec<N, U2>) -> Vec<N, U1> {
    Vector1::new(v.x)
}

/// Creates a 1D vector from another vector.
pub fn vec3_to_vec1<N: Scalar>(v: &Vec<N, U3>) -> Vec<N, U1> {
    Vector1::new(v.x)
}

/// Creates a 1D vector from another vector.
pub fn vec4_to_vec1<N: Scalar>(v: &Vec<N, U4>) -> Vec<N, U1> {
    Vector1::new(v.x)
}

/// Creates a 2D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec1_to_vec2<N: Number>(v: &Vec<N, U1>) -> Vec<N, U2> {
    Vector2::new(v.x, N::zero())
}

/// Creates a 2D vector from another vector.
pub fn vec2_to_vec2<N: Scalar>(v: &Vec<N, U2>) -> Vec<N, U2> {
    *v
}

/// Creates a 2D vector from another vector.
pub fn vec3_to_vec2<N: Scalar>(v: &Vec<N, U3>) -> Vec<N, U2> {
    Vector2::new(v.x, v.y)
}

/// Creates a 2D vector from another vector.
pub fn vec4_to_vec2<N: Scalar>(v: &Vec<N, U4>) -> Vec<N, U2> {
    Vector2::new(v.x, v.y)
}

/// Creates a 2D vector from a slice.
pub fn make_vec2<N: Scalar>(ptr: &[N]) -> Vec<N, U2> {
    Vector2::from_column_slice(ptr)
}

/// Creates a 3D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec1_to_vec3<N: Number>(v: &Vec<N, U1>) -> Vec<N, U3> {
    Vector3::new(v.x, N::zero(), N::zero())
}

/// Creates a 3D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec2_to_vec3<N: Number>(v: &Vec<N, U2>) -> Vec<N, U3> {
    Vector3::new(v.x, v.y, N::zero())
}

/// Creates a 3D vector from another vector.
pub fn vec3_to_vec3<N: Scalar>(v: &Vec<N, U3>) -> Vec<N, U3> {
    *v
}

/// Creates a 3D vector from another vector.
pub fn vec4_to_vec3<N: Scalar>(v: &Vec<N, U4>) -> Vec<N, U3> {
    Vector3::new(v.x, v.y, v.z)
}

/// Creates a 3D vector from another vector.
pub fn make_vec3<N: Scalar>(ptr: &[N]) -> Vec<N, U3> {
    Vector3::from_column_slice(ptr)
}

/// Creates a 4D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec1_to_vec4<N: Number>(v: &Vec<N, U1>) -> Vec<N, U4> {
    Vector4::new(v.x, N::zero(), N::zero(), N::zero())
}

/// Creates a 4D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec2_to_vec4<N: Number>(v: &Vec<N, U2>) -> Vec<N, U4> {
    Vector4::new(v.x, v.y, N::zero(), N::zero())
}

/// Creates a 4D vector from another vector.
///
/// Missing components, if any, are set to 0.
pub fn vec3_to_vec4<N: Number>(v: &Vec<N, U3>) -> Vec<N, U4> {
    Vector4::new(v.x, v.y, v.z, N::zero())
}

/// Creates a 4D vector from another vector.
pub fn vec4_to_vec4<N: Scalar>(v: &Vec<N, U4>) -> Vec<N, U4> {
    *v
}

/// Creates a 4D vector from another vector.
pub fn make_vec4<N: Scalar>(ptr: &[N]) -> Vec<N, U4> {
    Vector4::from_column_slice(ptr)
}

/// Converts a matrix or vector to a slice arranged in column-major order.
pub fn value_ptr<N: Scalar, R: Dimension, C: Dimension>(x: &Mat<N, R, C>) -> &[N]
    where DefaultAllocator: Alloc<N, R, C> {
    x.as_slice()
}

/// Converts a matrix or vector to a mutable slice arranged in column-major order.
pub fn value_ptr_mut<N: Scalar, R: Dimension, C: Dimension>(x: &mut Mat<N, R, C>) -> &mut [N]
    where DefaultAllocator: Alloc<N, R, C> {
    x.as_mut_slice()
}

<|endoftext|>


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

//! Base64 binary-to-text encoding
use std::str;

/// Available encoding character sets
pub enum CharacterSet {
    /// The standard character set (uses `+` and `/`)
    Standard,
    /// The URL safe character set (uses `-` and `_`)
    UrlSafe
}

/// Contains configuration parameters for `to_base64`.
pub struct Config {
    /// Character set to use
    char_set: CharacterSet,
    /// True to pad output with `=` characters
    pad: bool,
    /// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping
    line_length: Option<uint>
}

/// Configuration for RFC 4648 standard base64 encoding
pub static STANDARD: Config =
    Config {char_set: Standard, pad: true, line_length: None};

/// Configuration for RFC 4648 base64url encoding
pub static URL_SAFE: Config =
    Config {char_set: UrlSafe, pad: false, line_length: None};

/// Configuration for RFC 2045 MIME base64 encoding
pub static MIME: Config =
    Config {char_set: Standard, pad: true, line_length: Some(76)};

static STANDARD_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                                             "abcdefghijklmnopqrstuvwxyz",
                                             "0123456789+/");

static URLSAFE_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                                            "abcdefghijklmnopqrstuvwxyz",
                                            "0123456789-_");

/// A trait for converting a value to base64 encoding.
pub trait ToBase64 {
    /// Converts the value of `self` to a base64 value following the specified
    /// format configuration, returning the owned string.
    fn to_base64(&self, config: Config) -> ~str;
}

impl<'self> ToBase64 for &'self [u8] {
    /**
     * Turn a vector of `u8` bytes into a base64 string.
     *
     * # Example
     *
     * ```rust
     * extern mod extra;
     * use extra::base64::{ToBase64, standard};
     *
     * fn main () {
     *     let str = [52,32].to_base64(standard);
     *     println!("{}", str);
     * }
     * ```
     */
    fn to_base64(&self, config: Config) -> ~str {
        let bytes = match config.char_set {
            Standard => STANDARD_CHARS,
            UrlSafe => URLSAFE_CHARS
        };

        let mut v: ~[u8] = ~[];
        let mut i = 0;
        let mut cur_length = 0;
        let len = self.len();
        while i < len - (len % 3) {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                        cur_length = 0;
                    },
                None => ()
            }

            let n = (self[i] as u32) << 16 |
                    (self[i + 1] as u32) << 8 |
                    (self[i + 2] as u32);

            // This 24-bit number gets separated into four 6-bit numbers.
            v.push(bytes[(n >> 18) & 63]);
            v.push(bytes[(n >> 12) & 63]);
            v.push(bytes[(n >> 6 ) & 63]);
            v.push(bytes[n & 63]);

            cur_length += 4;
            i += 3;
        }

        if len % 3 != 0 {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                    },
                None => ()
            }
        }

        // Heh, would be cool if we knew this was exhaustive
        // (the dream of bounded integer types)
        match len % 3 {
            0 => (),
            1 => {
                let n = (self[i] as u32) << 16;
                v.push(bytes[(n >> 18) & 63]);
                v.push(bytes[(n >> 12) & 63]);
                if config.pad {
                    v.push('=' as u8);
                    v.push('=' as u8);
                }
            }
            2 => {
                let n = (self[i] as u32) << 16 |
                    (self[i + 1u] as u32) << 8;
                v.push(bytes[(n >> 18) & 63]);
                v.push(bytes[(n >> 12) & 63]);
                v.push(bytes[(n >> 6 ) & 63]);
                if config.pad {
                    v.push('=' as u8);
                }
            }
            _ => fail2!("Algebra is broken, please alert the math police")
        }

        unsafe {
            str::raw::from_utf8_owned(v)
        }
    }
}

/// A trait for converting from base64 encoded values.
pub trait FromBase64 {
    /// Converts the value of `self`, interpreted as base64 encoded data, into
    /// an owned vector of bytes, returning the vector.
    fn from_base64(&self) -> Result<~[u8], ~str>;
}

impl<'self> FromBase64 for &'self str {
    /**
     * Convert any base64 encoded string (literal, `@`, `&`, or `~`)
     * to the byte values it encodes.
     *
     * You can use the `from_utf8` function in `std::str`
     * to turn a `[u8]` into a string with characters corresponding to those
     * values.
     *
     * # Example
     *
     * This converts a string literal to base64 and back.
     *
     * ```rust
     * extern mod extra;
     * use extra::base64::{ToBase64, FromBase64, standard};
     * use std::str;
     *
     * fn main () {
     *     let hello_str = "Hello, World".to_base64(standard);
     *     println!("{}", hello_str);
     *     let bytes = hello_str.from_base64();
     *     println!("{:?}", bytes);
     *     let result_str = str::from_utf8(bytes);
     *     println!("{}", result_str);
     * }
     * ```
     */
    fn from_base64(&self) -> Result<~[u8], ~str> {
        let mut r = ~[];
        let mut buf: u32 = 0;
        let mut modulus = 0;

        let mut it = self.byte_iter().enumerate();
        for (idx, byte) in it {
            let val = byte as u32;

            match byte as char {
                'A'..'Z' => buf |= val - 0x41,
                'a'..'z' => buf |= val - 0x47,
                '0'..'9' => buf |= val + 0x04,
                '+'|'-' => buf |= 0x3E,
                '/'|'_' => buf |= 0x3F,
                '\r'|'\n' => continue,
                '=' => break,
                _ => return Err(format!("Invalid character '{}' at position {}",
                                     self.char_at(idx), idx))
            }

            buf <<= 6;
            modulus += 1;
            if modulus == 4 {
                modulus = 0;
                r.push((buf >> 22) as u8);
                r.push((buf >> 14) as u8);
                r.push((buf >> 6 ) as u8);
            }
        }

        for (idx, byte) in it {
            if (byte as char) != '=' {
                return Err(format!("Invalid character '{}' at position {}",
                                self.char_at(idx), idx));
            }
        }

        match modulus {
            2 => {
                r.push((buf >> 10) as u8);
            }
            3 => {
                r.push((buf >> 16) as u8);
                r.push((buf >> 8 ) as u8);
            }
            0 => (),
            _ => return Err(~"Invalid Base64 length")
        }

        Ok(r)
    }
}

#[cfg(test)]
mod test {
    use test::BenchHarness;
    use base64::*;

    #[test]
    fn test_to_base64_basic() {
        assert_eq!("".as_bytes().to_base64(STANDARD), ~"");
        assert_eq!("f".as_bytes().to_base64(STANDARD), ~"Zg==");
        assert_eq!("fo".as_bytes().to_base64(STANDARD), ~"Zm8=");
        assert_eq!("foo".as_bytes().to_base64(STANDARD), ~"Zm9v");
        assert_eq!("foob".as_bytes().to_base64(STANDARD), ~"Zm9vYg==");
        assert_eq!("fooba".as_bytes().to_base64(STANDARD), ~"Zm9vYmE=");
        assert_eq!("foobar".as_bytes().to_base64(STANDARD), ~"Zm9vYmFy");
    }

    #[test]
    fn test_to_base64_line_break() {
        assert!(![0u8, 1000].to_base64(Config {line_length: None, ..STANDARD})
                .contains("\r\n"));
        assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4),
                                                         ..STANDARD}),
                   ~"Zm9v\r\nYmFy");
    }

    #[test]
    fn test_to_base64_padding() {
        assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zg");
        assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zm8");
    }

    #[test]
    fn test_to_base64_url_safe() {
        assert_eq!([251, 255].to_base64(URL_SAFE), ~"-_8");
        assert_eq!([251, 255].to_base64(STANDARD), ~"+/8=");
    }

    #[test]
    fn test_from_base64_basic() {
        assert_eq!("".from_base64().unwrap(), "".as_bytes().to_owned());
        assert_eq!("Zg==".from_base64().unwrap(), "f".as_bytes().to_owned());
        assert_eq!("Zm8=".from_base64().unwrap(), "fo".as_bytes().to_owned());
        assert_eq!("Zm9v".from_base64().unwrap(), "foo".as_bytes().to_owned());
        assert_eq!("Zm9vYg==".from_base64().unwrap(), "foob".as_bytes().to_owned());
        assert_eq!("Zm9vYmE=".from_base64().unwrap(), "fooba".as_bytes().to_owned());
        assert_eq!("Zm9vYmFy".from_base64().unwrap(), "foobar".as_bytes().to_owned());
    }

    #[test]
    fn test_from_base64_newlines() {
        assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap(),
                   "foobar".as_bytes().to_owned());
    }

    #[test]
    fn test_from_base64_urlsafe() {
        assert_eq!("-_8".from_base64().unwrap(), "+/8=".from_base64().unwrap());
    }

    #[test]
    fn test_from_base64_invalid_char() {
        assert!("Zm$=".from_base64().is_err())
        assert!("Zg==$".from_base64().is_err());
    }

    #[test]
    fn test_from_base64_invalid_padding() {
        assert!("Z===".from_base64().is_err());
    }

    #[test]
    fn test_base64_random() {
        use std::rand::{task_rng, random, Rng};
        use std::vec;

        do 1000.times {
            let times = task_rng().gen_integer_range(1u, 100);
            let v = vec::from_fn(times, |_| random::<u8>());
            assert_eq!(v.to_base64(STANDARD).from_base64().unwrap(), v);
        }
    }

    #[bench]
    pub fn bench_to_base64(bh: & mut BenchHarness) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        do bh.iter {
            s.as_bytes().to_base64(STANDARD);
        }
        bh.bytes = s.len() as u64;
    }

    #[bench]
    pub fn bench_from_base64(bh: & mut BenchHarness) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        let b = s.as_bytes().to_base64(STANDARD);
        do bh.iter {
            b.from_base64();
        }
        bh.bytes = b.len() as u64;
    }

}
<commit_msg>Correct code examples for base64 documentation<commit_after>// Copyright 2012-2013 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.

//! Base64 binary-to-text encoding
use std::str;

/// Available encoding character sets
pub enum CharacterSet {
    /// The standard character set (uses `+` and `/`)
    Standard,
    /// The URL safe character set (uses `-` and `_`)
    UrlSafe
}

/// Contains configuration parameters for `to_base64`.
pub struct Config {
    /// Character set to use
    char_set: CharacterSet,
    /// True to pad output with `=` characters
    pad: bool,
    /// `Some(len)` to wrap lines at `len`, `None` to disable line wrapping
    line_length: Option<uint>
}

/// Configuration for RFC 4648 standard base64 encoding
pub static STANDARD: Config =
    Config {char_set: Standard, pad: true, line_length: None};

/// Configuration for RFC 4648 base64url encoding
pub static URL_SAFE: Config =
    Config {char_set: UrlSafe, pad: false, line_length: None};

/// Configuration for RFC 2045 MIME base64 encoding
pub static MIME: Config =
    Config {char_set: Standard, pad: true, line_length: Some(76)};

static STANDARD_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                                             "abcdefghijklmnopqrstuvwxyz",
                                             "0123456789+/");

static URLSAFE_CHARS: &'static[u8] = bytes!("ABCDEFGHIJKLMNOPQRSTUVWXYZ",
                                            "abcdefghijklmnopqrstuvwxyz",
                                            "0123456789-_");

/// A trait for converting a value to base64 encoding.
pub trait ToBase64 {
    /// Converts the value of `self` to a base64 value following the specified
    /// format configuration, returning the owned string.
    fn to_base64(&self, config: Config) -> ~str;
}

impl<'self> ToBase64 for &'self [u8] {
    /**
     * Turn a vector of `u8` bytes into a base64 string.
     *
     * # Example
     *
     * ```rust
     * extern mod extra;
     * use extra::base64::{ToBase64, STANDARD};
     *
     * fn main () {
     *     let str = [52,32].to_base64(STANDARD);
     *     println!("base 64 output: {}", str);
     * }
     * ```
     */
    fn to_base64(&self, config: Config) -> ~str {
        let bytes = match config.char_set {
            Standard => STANDARD_CHARS,
            UrlSafe => URLSAFE_CHARS
        };

        let mut v: ~[u8] = ~[];
        let mut i = 0;
        let mut cur_length = 0;
        let len = self.len();
        while i < len - (len % 3) {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                        cur_length = 0;
                    },
                None => ()
            }

            let n = (self[i] as u32) << 16 |
                    (self[i + 1] as u32) << 8 |
                    (self[i + 2] as u32);

            // This 24-bit number gets separated into four 6-bit numbers.
            v.push(bytes[(n >> 18) & 63]);
            v.push(bytes[(n >> 12) & 63]);
            v.push(bytes[(n >> 6 ) & 63]);
            v.push(bytes[n & 63]);

            cur_length += 4;
            i += 3;
        }

        if len % 3 != 0 {
            match config.line_length {
                Some(line_length) =>
                    if cur_length >= line_length {
                        v.push('\r' as u8);
                        v.push('\n' as u8);
                    },
                None => ()
            }
        }

        // Heh, would be cool if we knew this was exhaustive
        // (the dream of bounded integer types)
        match len % 3 {
            0 => (),
            1 => {
                let n = (self[i] as u32) << 16;
                v.push(bytes[(n >> 18) & 63]);
                v.push(bytes[(n >> 12) & 63]);
                if config.pad {
                    v.push('=' as u8);
                    v.push('=' as u8);
                }
            }
            2 => {
                let n = (self[i] as u32) << 16 |
                    (self[i + 1u] as u32) << 8;
                v.push(bytes[(n >> 18) & 63]);
                v.push(bytes[(n >> 12) & 63]);
                v.push(bytes[(n >> 6 ) & 63]);
                if config.pad {
                    v.push('=' as u8);
                }
            }
            _ => fail2!("Algebra is broken, please alert the math police")
        }

        unsafe {
            str::raw::from_utf8_owned(v)
        }
    }
}

/// A trait for converting from base64 encoded values.
pub trait FromBase64 {
    /// Converts the value of `self`, interpreted as base64 encoded data, into
    /// an owned vector of bytes, returning the vector.
    fn from_base64(&self) -> Result<~[u8], ~str>;
}

impl<'self> FromBase64 for &'self str {
    /**
     * Convert any base64 encoded string (literal, `@`, `&`, or `~`)
     * to the byte values it encodes.
     *
     * You can use the `from_utf8` function in `std::str`
     * to turn a `[u8]` into a string with characters corresponding to those
     * values.
     *
     * # Example
     *
     * This converts a string literal to base64 and back.
     *
     * ```rust
     * extern mod extra;
     * use extra::base64::{ToBase64, FromBase64, STANDARD};
     * use std::str;
     *
     * fn main () {
     *     let hello_str = bytes!("Hello, World").to_base64(STANDARD);
     *     println!("base64 output: {}", hello_str);
     *     let res = hello_str.from_base64();
     *     if res.is_ok() {
     *       let optBytes = str::from_utf8_opt(res.unwrap());
     *       if optBytes.is_some() {
     *         println!("decoded from base64: {}", optBytes.unwrap());
     *       }
     *     }
     * }
     * ```
     */
    fn from_base64(&self) -> Result<~[u8], ~str> {
        let mut r = ~[];
        let mut buf: u32 = 0;
        let mut modulus = 0;

        let mut it = self.byte_iter().enumerate();
        for (idx, byte) in it {
            let val = byte as u32;

            match byte as char {
                'A'..'Z' => buf |= val - 0x41,
                'a'..'z' => buf |= val - 0x47,
                '0'..'9' => buf |= val + 0x04,
                '+'|'-' => buf |= 0x3E,
                '/'|'_' => buf |= 0x3F,
                '\r'|'\n' => continue,
                '=' => break,
                _ => return Err(format!("Invalid character '{}' at position {}",
                                     self.char_at(idx), idx))
            }

            buf <<= 6;
            modulus += 1;
            if modulus == 4 {
                modulus = 0;
                r.push((buf >> 22) as u8);
                r.push((buf >> 14) as u8);
                r.push((buf >> 6 ) as u8);
            }
        }

        for (idx, byte) in it {
            if (byte as char) != '=' {
                return Err(format!("Invalid character '{}' at position {}",
                                self.char_at(idx), idx));
            }
        }

        match modulus {
            2 => {
                r.push((buf >> 10) as u8);
            }
            3 => {
                r.push((buf >> 16) as u8);
                r.push((buf >> 8 ) as u8);
            }
            0 => (),
            _ => return Err(~"Invalid Base64 length")
        }

        Ok(r)
    }
}

#[cfg(test)]
mod test {
    use test::BenchHarness;
    use base64::*;

    #[test]
    fn test_to_base64_basic() {
        assert_eq!("".as_bytes().to_base64(STANDARD), ~"");
        assert_eq!("f".as_bytes().to_base64(STANDARD), ~"Zg==");
        assert_eq!("fo".as_bytes().to_base64(STANDARD), ~"Zm8=");
        assert_eq!("foo".as_bytes().to_base64(STANDARD), ~"Zm9v");
        assert_eq!("foob".as_bytes().to_base64(STANDARD), ~"Zm9vYg==");
        assert_eq!("fooba".as_bytes().to_base64(STANDARD), ~"Zm9vYmE=");
        assert_eq!("foobar".as_bytes().to_base64(STANDARD), ~"Zm9vYmFy");
    }

    #[test]
    fn test_to_base64_line_break() {
        assert!(![0u8, 1000].to_base64(Config {line_length: None, ..STANDARD})
                .contains("\r\n"));
        assert_eq!("foobar".as_bytes().to_base64(Config {line_length: Some(4),
                                                         ..STANDARD}),
                   ~"Zm9v\r\nYmFy");
    }

    #[test]
    fn test_to_base64_padding() {
        assert_eq!("f".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zg");
        assert_eq!("fo".as_bytes().to_base64(Config {pad: false, ..STANDARD}), ~"Zm8");
    }

    #[test]
    fn test_to_base64_url_safe() {
        assert_eq!([251, 255].to_base64(URL_SAFE), ~"-_8");
        assert_eq!([251, 255].to_base64(STANDARD), ~"+/8=");
    }

    #[test]
    fn test_from_base64_basic() {
        assert_eq!("".from_base64().unwrap(), "".as_bytes().to_owned());
        assert_eq!("Zg==".from_base64().unwrap(), "f".as_bytes().to_owned());
        assert_eq!("Zm8=".from_base64().unwrap(), "fo".as_bytes().to_owned());
        assert_eq!("Zm9v".from_base64().unwrap(), "foo".as_bytes().to_owned());
        assert_eq!("Zm9vYg==".from_base64().unwrap(), "foob".as_bytes().to_owned());
        assert_eq!("Zm9vYmE=".from_base64().unwrap(), "fooba".as_bytes().to_owned());
        assert_eq!("Zm9vYmFy".from_base64().unwrap(), "foobar".as_bytes().to_owned());
    }

    #[test]
    fn test_from_base64_newlines() {
        assert_eq!("Zm9v\r\nYmFy".from_base64().unwrap(),
                   "foobar".as_bytes().to_owned());
    }

    #[test]
    fn test_from_base64_urlsafe() {
        assert_eq!("-_8".from_base64().unwrap(), "+/8=".from_base64().unwrap());
    }

    #[test]
    fn test_from_base64_invalid_char() {
        assert!("Zm$=".from_base64().is_err())
        assert!("Zg==$".from_base64().is_err());
    }

    #[test]
    fn test_from_base64_invalid_padding() {
        assert!("Z===".from_base64().is_err());
    }

    #[test]
    fn test_base64_random() {
        use std::rand::{task_rng, random, Rng};
        use std::vec;

        do 1000.times {
            let times = task_rng().gen_integer_range(1u, 100);
            let v = vec::from_fn(times, |_| random::<u8>());
            assert_eq!(v.to_base64(STANDARD).from_base64().unwrap(), v);
        }
    }

    #[bench]
    pub fn bench_to_base64(bh: & mut BenchHarness) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        do bh.iter {
            s.as_bytes().to_base64(STANDARD);
        }
        bh.bytes = s.len() as u64;
    }

    #[bench]
    pub fn bench_from_base64(bh: & mut BenchHarness) {
        let s = "イロハニホヘト チリヌルヲ ワカヨタレソ ツネナラム \
                 ウヰノオクヤマ ケフコエテ アサキユメミシ ヱヒモセスン";
        let b = s.as_bytes().to_base64(STANDARD);
        do bh.iter {
            b.from_base64();
        }
        bh.bytes = b.len() as u64;
    }

}
<|endoftext|>


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

//! Temporal quantification.

#![stable(feature = "time", since = "1.3.0")]

use error::Error;
use fmt;
use ops::{Add, Sub};
use sys::time;

#[stable(feature = "time", since = "1.3.0")]
pub use self::duration::Duration;

mod duration;

/// A measurement of a monotonically increasing clock which is suitable for
/// measuring the amount of time that an operation takes.
///
/// Instants are guaranteed always be greater than any previously measured
/// instant when created, and are often useful for tasks such as measuring
/// benchmarks or timing how long an operation takes.
///
/// Note, however, that instants are not guaranteed to be **steady**.  In other
/// words each tick of the underlying clock may not be the same length (e.g.
/// some seconds may be longer than others). An instant may jump forwards or
/// experience time dilation (slow down or speed up), but it will never go
/// backwards.
///
/// Instants are opaque types that can only be compared to one another. There is
/// no method to get "the number of seconds" from an instant but instead it only
/// allow learning the duration between two instants (or comparing two
/// instants).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct Instant(time::Instant);

/// A measurement of the system clock appropriate for timestamps such as those
/// on files on the filesystem.
///
/// Distinct from the `Instant` type, this time measurement **is not
/// monotonic**. This means that you can save a file to the file system, then
/// save another file to the file system, **and the second file has a
/// `SystemTime` measurement earlier than the second**. In other words, an
/// operation that happens after another operation in real time may have an
/// earlier `SystemTime`!
///
/// Consequently, comparing two `SystemTime` instances to learn about the
/// duration between them returns a `Result` instead of an infallible `Duration`
/// to indicate that this sort of time drift may happen and needs to be handled.
///
/// Although a `SystemTime` cannot be directly inspected, the `UNIX_EPOCH`
/// constant is provided in this module as an anchor in time to learn
/// information about a `SystemTime`. By calculating the duration from this
/// fixed point in time a `SystemTime` can be converted to a human-readable time
/// or perhaps some other string representation.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTime(time::SystemTime);

/// An error returned from the `duration_from_earlier` method on `SystemTime`,
/// used to learn about why how far in the opposite direction a timestamp lies.
#[derive(Clone, Debug)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTimeError(Duration);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Instant {
    /// Returns an instant corresponding to "now".
    pub fn now() -> Instant {
        Instant(time::Instant::now())
    }

    /// Returns the amount of time elapsed from another instant to this one.
    ///
    /// # Panics
    ///
    /// This function will panic if `earlier` is later than `self`, which should
    /// only be possible if `earlier` was created after `self`. Because
    /// `Instant` is monotonic, the only time that this should happen should be
    /// a bug.
    pub fn duration_from_earlier(&self, earlier: Instant) -> Duration {
        self.0.sub_instant(&earlier.0)
    }

    /// Returns the amount of time elapsed since this instant was created.
    ///
    /// # Panics
    ///
    /// This function may panic if the current time is earlier than this instant
    /// which can happen if an `Instant` is produced synthetically.
    pub fn elapsed(&self) -> Duration {
        Instant::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for Instant {
    type Output = Instant;

    fn add(self, other: Duration) -> Instant {
        Instant(self.0.add_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for Instant {
    type Output = Instant;

    fn sub(self, other: Duration) -> Instant {
        Instant(self.0.sub_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for Instant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTime {
    /// Returns the system time corresponding to "now".
    pub fn now() -> SystemTime {
        SystemTime(time::SystemTime::now())
    }

    /// Returns the amount of time elapsed from an earlier point in time.
    ///
    /// This function may fail because measurements taken earlier are not
    /// guaranteed to always be before later measurements (due to anomalies such
    /// as the system clock being adjusted either forwards or backwards).
    ///
    /// If successful, `Ok(duration)` is returned where the duration represents
    /// the amount of time elapsed from the specified measurement to this one.
    ///
    /// Returns an `Err` if `earlier` is later than `self`, and the error
    /// contains how far from `self` the time is.
    pub fn duration_from_earlier(&self, earlier: SystemTime)
                                 -> Result<Duration, SystemTimeError> {
        self.0.sub_time(&earlier.0).map_err(SystemTimeError)
    }

    /// Returns the amount of time elapsed since this system time was created.
    ///
    /// This function may fail as the underlying system clock is susceptible to
    /// drift and updates (e.g. the system clock could go backwards), so this
    /// function may not always succeed. If successful, `Ok(duration)` is
    /// returned where the duration represents the amount of time elapsed from
    /// this time measurement to the current time.
    ///
    /// Returns an `Err` if `self` is later than the current system time, and
    /// the error contains how far from the current system time `self` is.
    pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
        SystemTime::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for SystemTime {
    type Output = SystemTime;

    fn add(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.add_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for SystemTime {
    type Output = SystemTime;

    fn sub(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.sub_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for SystemTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// An anchor in time which can be used to create new `SystemTime` instances or
/// learn about where in time a `SystemTime` lies.
///
/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
/// respect to the system clock. Using `duration_from_earlier` on an existing
/// `SystemTime` instance can tell how far away from this point in time a
/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
/// `SystemTime` instance to represent another fixed point in time.
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTimeError {
    /// Returns the positive duration which represents how far forward the
    /// second system time was from the first.
    ///
    /// A `SystemTimeError` is returned from the `duration_from_earlier`
    /// operation whenever the second duration, `earlier`, actually represents a
    /// point later in time than the `self` of the method call. This function
    /// will extract and return the amount of time later `earlier` actually is.
    pub fn duration(&self) -> Duration {
        self.0
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Error for SystemTimeError {
    fn description(&self) -> &str { "other time was not earlier than self" }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Display for SystemTimeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "second time provided was later than self")
    }
}

#[cfg(test)]
mod tests {
    use super::{Instant, SystemTime, Duration, UNIX_EPOCH};

    macro_rules! assert_almost_eq {
        ($a:expr, $b:expr) => ({
            let (a, b) = ($a, $b);
            if a != b {
                let (a, b) = if a > b {(a, b)} else {(b, a)};
                assert!(a - Duration::new(0, 1) <= b);
            }
        })
    }

    #[test]
    fn instant_monotonic() {
        let a = Instant::now();
        let b = Instant::now();
        assert!(b >= a);
    }

    #[test]
    fn instant_elapsed() {
        let a = Instant::now();
        a.elapsed();
    }

    #[test]
    fn instant_math() {
        let a = Instant::now();
        let b = Instant::now();
        let dur = b.duration_from_earlier(a);
        assert_almost_eq!(b - dur, a);
        assert_almost_eq!(a + dur, b);

        let second = Duration::new(1, 0);
        assert_almost_eq!(a - second + second, a);
    }

    #[test]
    #[should_panic]
    fn instant_duration_panic() {
        let a = Instant::now();
        (a - Duration::new(1, 0)).duration_from_earlier(a);
    }

    #[test]
    fn system_time_math() {
        let a = SystemTime::now();
        let b = SystemTime::now();
        match b.duration_from_earlier(a) {
            Ok(dur) if dur == Duration::new(0, 0) => {
                assert_almost_eq!(a, b);
            }
            Ok(dur) => {
                assert!(b > a);
                assert_almost_eq!(b - dur, a);
                assert_almost_eq!(a + dur, b);
            }
            Err(dur) => {
                let dur = dur.duration();
                assert!(a > b);
                assert_almost_eq!(b + dur, a);
                assert_almost_eq!(b - dur, a);
            }
        }

        let second = Duration::new(1, 0);
        assert_almost_eq!(a.duration_from_earlier(a - second).unwrap(), second);
        assert_almost_eq!(a.duration_from_earlier(a + second).unwrap_err()
                           .duration(), second);

        assert_almost_eq!(a - second + second, a);

        let eighty_years = second * 60 * 60 * 24 * 365 * 80;
        assert_almost_eq!(a - eighty_years + eighty_years, a);
        assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
    }

    #[test]
    fn system_time_elapsed() {
        let a = SystemTime::now();
        drop(a.elapsed());
    }

    #[test]
    fn since_epoch() {
        let ts = SystemTime::now();
        let a = ts.duration_from_earlier(UNIX_EPOCH).unwrap();
        let b = ts.duration_from_earlier(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
        assert!(b > a);
        assert_eq!(b - a, Duration::new(1, 0));

        // let's assume that we're all running computers later than 2000
        let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30;
        assert!(a > thirty_years);

        // let's assume that we're all running computers earlier than 2090.
        // Should give us ~70 years to fix this!
        let hundred_twenty_years = thirty_years * 4;
        assert!(a < hundred_twenty_years);
    }
}
<commit_msg>doc: remove info repeated on next paragraph<commit_after>// Copyright 2012-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.

//! Temporal quantification.

#![stable(feature = "time", since = "1.3.0")]

use error::Error;
use fmt;
use ops::{Add, Sub};
use sys::time;

#[stable(feature = "time", since = "1.3.0")]
pub use self::duration::Duration;

mod duration;

/// A measurement of a monotonically increasing clock.
///
/// Instants are guaranteed always be greater than any previously measured
/// instant when created, and are often useful for tasks such as measuring
/// benchmarks or timing how long an operation takes.
///
/// Note, however, that instants are not guaranteed to be **steady**.  In other
/// words each tick of the underlying clock may not be the same length (e.g.
/// some seconds may be longer than others). An instant may jump forwards or
/// experience time dilation (slow down or speed up), but it will never go
/// backwards.
///
/// Instants are opaque types that can only be compared to one another. There is
/// no method to get "the number of seconds" from an instant but instead it only
/// allow learning the duration between two instants (or comparing two
/// instants).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct Instant(time::Instant);

/// A measurement of the system clock appropriate for timestamps such as those
/// on files on the filesystem.
///
/// Distinct from the `Instant` type, this time measurement **is not
/// monotonic**. This means that you can save a file to the file system, then
/// save another file to the file system, **and the second file has a
/// `SystemTime` measurement earlier than the second**. In other words, an
/// operation that happens after another operation in real time may have an
/// earlier `SystemTime`!
///
/// Consequently, comparing two `SystemTime` instances to learn about the
/// duration between them returns a `Result` instead of an infallible `Duration`
/// to indicate that this sort of time drift may happen and needs to be handled.
///
/// Although a `SystemTime` cannot be directly inspected, the `UNIX_EPOCH`
/// constant is provided in this module as an anchor in time to learn
/// information about a `SystemTime`. By calculating the duration from this
/// fixed point in time a `SystemTime` can be converted to a human-readable time
/// or perhaps some other string representation.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTime(time::SystemTime);

/// An error returned from the `duration_from_earlier` method on `SystemTime`,
/// used to learn about why how far in the opposite direction a timestamp lies.
#[derive(Clone, Debug)]
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub struct SystemTimeError(Duration);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Instant {
    /// Returns an instant corresponding to "now".
    pub fn now() -> Instant {
        Instant(time::Instant::now())
    }

    /// Returns the amount of time elapsed from another instant to this one.
    ///
    /// # Panics
    ///
    /// This function will panic if `earlier` is later than `self`, which should
    /// only be possible if `earlier` was created after `self`. Because
    /// `Instant` is monotonic, the only time that this should happen should be
    /// a bug.
    pub fn duration_from_earlier(&self, earlier: Instant) -> Duration {
        self.0.sub_instant(&earlier.0)
    }

    /// Returns the amount of time elapsed since this instant was created.
    ///
    /// # Panics
    ///
    /// This function may panic if the current time is earlier than this instant
    /// which can happen if an `Instant` is produced synthetically.
    pub fn elapsed(&self) -> Duration {
        Instant::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for Instant {
    type Output = Instant;

    fn add(self, other: Duration) -> Instant {
        Instant(self.0.add_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for Instant {
    type Output = Instant;

    fn sub(self, other: Duration) -> Instant {
        Instant(self.0.sub_duration(&other))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for Instant {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTime {
    /// Returns the system time corresponding to "now".
    pub fn now() -> SystemTime {
        SystemTime(time::SystemTime::now())
    }

    /// Returns the amount of time elapsed from an earlier point in time.
    ///
    /// This function may fail because measurements taken earlier are not
    /// guaranteed to always be before later measurements (due to anomalies such
    /// as the system clock being adjusted either forwards or backwards).
    ///
    /// If successful, `Ok(duration)` is returned where the duration represents
    /// the amount of time elapsed from the specified measurement to this one.
    ///
    /// Returns an `Err` if `earlier` is later than `self`, and the error
    /// contains how far from `self` the time is.
    pub fn duration_from_earlier(&self, earlier: SystemTime)
                                 -> Result<Duration, SystemTimeError> {
        self.0.sub_time(&earlier.0).map_err(SystemTimeError)
    }

    /// Returns the amount of time elapsed since this system time was created.
    ///
    /// This function may fail as the underlying system clock is susceptible to
    /// drift and updates (e.g. the system clock could go backwards), so this
    /// function may not always succeed. If successful, `Ok(duration)` is
    /// returned where the duration represents the amount of time elapsed from
    /// this time measurement to the current time.
    ///
    /// Returns an `Err` if `self` is later than the current system time, and
    /// the error contains how far from the current system time `self` is.
    pub fn elapsed(&self) -> Result<Duration, SystemTimeError> {
        SystemTime::now().duration_from_earlier(*self)
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Add<Duration> for SystemTime {
    type Output = SystemTime;

    fn add(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.add_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Sub<Duration> for SystemTime {
    type Output = SystemTime;

    fn sub(self, dur: Duration) -> SystemTime {
        SystemTime(self.0.sub_duration(&dur))
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Debug for SystemTime {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// An anchor in time which can be used to create new `SystemTime` instances or
/// learn about where in time a `SystemTime` lies.
///
/// This constant is defined to be "1970-01-01 00:00:00 UTC" on all systems with
/// respect to the system clock. Using `duration_from_earlier` on an existing
/// `SystemTime` instance can tell how far away from this point in time a
/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
/// `SystemTime` instance to represent another fixed point in time.
#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
pub const UNIX_EPOCH: SystemTime = SystemTime(time::UNIX_EPOCH);

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl SystemTimeError {
    /// Returns the positive duration which represents how far forward the
    /// second system time was from the first.
    ///
    /// A `SystemTimeError` is returned from the `duration_from_earlier`
    /// operation whenever the second duration, `earlier`, actually represents a
    /// point later in time than the `self` of the method call. This function
    /// will extract and return the amount of time later `earlier` actually is.
    pub fn duration(&self) -> Duration {
        self.0
    }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl Error for SystemTimeError {
    fn description(&self) -> &str { "other time was not earlier than self" }
}

#[unstable(feature = "time2", reason = "recently added", issue = "29866")]
impl fmt::Display for SystemTimeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "second time provided was later than self")
    }
}

#[cfg(test)]
mod tests {
    use super::{Instant, SystemTime, Duration, UNIX_EPOCH};

    macro_rules! assert_almost_eq {
        ($a:expr, $b:expr) => ({
            let (a, b) = ($a, $b);
            if a != b {
                let (a, b) = if a > b {(a, b)} else {(b, a)};
                assert!(a - Duration::new(0, 1) <= b);
            }
        })
    }

    #[test]
    fn instant_monotonic() {
        let a = Instant::now();
        let b = Instant::now();
        assert!(b >= a);
    }

    #[test]
    fn instant_elapsed() {
        let a = Instant::now();
        a.elapsed();
    }

    #[test]
    fn instant_math() {
        let a = Instant::now();
        let b = Instant::now();
        let dur = b.duration_from_earlier(a);
        assert_almost_eq!(b - dur, a);
        assert_almost_eq!(a + dur, b);

        let second = Duration::new(1, 0);
        assert_almost_eq!(a - second + second, a);
    }

    #[test]
    #[should_panic]
    fn instant_duration_panic() {
        let a = Instant::now();
        (a - Duration::new(1, 0)).duration_from_earlier(a);
    }

    #[test]
    fn system_time_math() {
        let a = SystemTime::now();
        let b = SystemTime::now();
        match b.duration_from_earlier(a) {
            Ok(dur) if dur == Duration::new(0, 0) => {
                assert_almost_eq!(a, b);
            }
            Ok(dur) => {
                assert!(b > a);
                assert_almost_eq!(b - dur, a);
                assert_almost_eq!(a + dur, b);
            }
            Err(dur) => {
                let dur = dur.duration();
                assert!(a > b);
                assert_almost_eq!(b + dur, a);
                assert_almost_eq!(b - dur, a);
            }
        }

        let second = Duration::new(1, 0);
        assert_almost_eq!(a.duration_from_earlier(a - second).unwrap(), second);
        assert_almost_eq!(a.duration_from_earlier(a + second).unwrap_err()
                           .duration(), second);

        assert_almost_eq!(a - second + second, a);

        let eighty_years = second * 60 * 60 * 24 * 365 * 80;
        assert_almost_eq!(a - eighty_years + eighty_years, a);
        assert_almost_eq!(a - (eighty_years * 10) + (eighty_years * 10), a);
    }

    #[test]
    fn system_time_elapsed() {
        let a = SystemTime::now();
        drop(a.elapsed());
    }

    #[test]
    fn since_epoch() {
        let ts = SystemTime::now();
        let a = ts.duration_from_earlier(UNIX_EPOCH).unwrap();
        let b = ts.duration_from_earlier(UNIX_EPOCH - Duration::new(1, 0)).unwrap();
        assert!(b > a);
        assert_eq!(b - a, Duration::new(1, 0));

        // let's assume that we're all running computers later than 2000
        let thirty_years = Duration::new(1, 0) * 60 * 60 * 24 * 365 * 30;
        assert!(a > thirty_years);

        // let's assume that we're all running computers earlier than 2090.
        // Should give us ~70 years to fix this!
        let hundred_twenty_years = thirty_years * 4;
        assert!(a < hundred_twenty_years);
    }
}
<|endoftext|>