<commit_before>use std::fmt;
use lexer::reader::{CodeReader,StrReader,FileReader};
use lexer::token::{Token,TokenType};
use lexer::position::Position;
use error::{ParseError,ErrorCode};

pub mod reader;
pub mod token;
pub mod position;

struct CharPos {
    value: char,
    position: Position
}

impl fmt::Show for CharPos {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "char {} at line {:?}", self.value, self.position)
    }
}

impl Copy for CharPos {}

pub struct Lexer<T : CodeReader> {
    reader: T,
    position: Position,

    buffer: Vec<CharPos>,
    eof_reached: bool
}

impl Lexer<StrReader> {
    pub fn from_str(code: &'static str) -> Lexer<StrReader> {
        Lexer::new(StrReader::new(code))
    }
}

impl Lexer<StrReader> {
    pub fn from_file(filename: &'static str) -> Lexer<FileReader> {
        Lexer::new(FileReader::new(filename))
    }
}

impl<T : CodeReader> Lexer<T> {
    pub fn new(reader : T) -> Lexer<T> {
        let mut lexer = Lexer::<T> {
            reader: reader,
            position: Position::new(1, 1),
            buffer: Vec::with_capacity(10),
            eof_reached: false
        };
        lexer.fill_buffer();

        lexer
    }

    pub fn read_token(&mut self) -> Result<Token,ParseError> {
        loop {
            self.skip_white();

            if self.top().is_none() {
                return Ok(Token::new(TokenType::End, self.position));
            }

            if self.is_digit() {
                return self.read_number();

            } else if self.is_comment_start() {
                match self.read_comment() {
                    Some(err) => return Err(err),
                    _ => {}
                }

            } else if self.is_multi_comment_start() {
                match self.read_multi_comment() {
                    Some(err) => return Err(err),
                    _ => {}
                }

            } else if self.is_identifier_start() {
                return self.read_identifier();

            } else {
                let ch = self.top().unwrap().value;

                return Err( ParseError {
                  filename: self.reader.filename().to_string(),
                  position: self.position,
                  code: ErrorCode::UnknownChar,
                  message: format!("unknown character {} (ascii code {}", ch, ch as usize)
                } )
            }
        }
    }

    fn skip_white(&mut self) {
        while self.is_whitespace() {
            self.read_char();
        }
    }

    fn read_comment(&mut self) -> Option<ParseError> {
        while self.top().is_some() && !self.is_newline() {
            self.read_char();
        }

        None
    }

    fn read_multi_comment(&mut self) -> Option<ParseError> {
        let pos = self.top().unwrap().position;

        self.read_char();
        self.read_char();

        while self.top().is_some() && !self.is_multi_comment_end() {
          self.read_char();
        }

        if self.top().is_none() {
          return Some(ParseError {
              filename: self.reader.filename().to_string(),
              position: pos,
              code: ErrorCode::UnclosedComment,
              message: "unclosed comment".to_string()
          } );
        }

        self.read_char();
        self.read_char();

        None
    }

    fn read_identifier(&mut self) -> Result<Token,ParseError> {
        let mut tok = self.build_token(TokenType::Identifier);

        while self.is_digit() || self.is_identifier_start() {
            let ch = self.read_char().unwrap().value;
            tok.value.push(ch);
        }

        Ok(tok)
    }

    fn read_number(&mut self) -> Result<Token,ParseError> {
        let mut tok = self.build_token(TokenType::Number);

        while self.is_digit() {
            let ch = self.read_char().unwrap().value;
            tok.value.push(ch);
        }

        Ok(tok)
    }

    fn read_char(&mut self) -> Option<CharPos> {
        if self.buffer.len() > 0 {
            let ch = self.buffer.remove(0);
            self.fill_buffer();

            Some(ch)
        } else {
            None
        }
    }

    fn top(&self) -> Option<CharPos> {
        self.at(0)
    }

    fn at(&self, index: usize) -> Option<CharPos> {
        if self.buffer.len() > index {
            Some(self.buffer[index])
        } else {
            None
        }
    }

    fn build_token(&self, ttype: TokenType) -> Token {
        Token::new(ttype, self.top().unwrap().position)
    }

    fn fill_buffer(&mut self) {
        while !self.eof_reached && self.buffer.len() < 10 {
            let ch = self.reader.read_char();

            if ch.is_some() {
                let ch = ch.unwrap();
                self.buffer.push(CharPos { value: ch, position: self.position });

                if ch == '\n' {
                    self.position.line += 1;
                    self.position.column = 1;
                } else {
                    self.position.column += 1;
                }
            } else {
                self.eof_reached = true;
            }
        }
    }

    fn is_comment_start(&self) -> bool {
        let top = self.top();
        let ntop = self.at(1);

        top.is_some() && top.unwrap().value == '/' &&
            ntop.is_some() && ntop.unwrap().value == '/'
    }

    fn is_multi_comment_start(&self) -> bool {
        let top = self.top();
        let ntop = self.at(1);

        top.is_some() && top.unwrap().value == '/' &&
            ntop.is_some() && ntop.unwrap().value == '*'
    }

    fn is_multi_comment_end(&self) -> bool {
        let top = self.top();
        let ntop = self.at(1);

        top.is_some() && top.unwrap().value == '*' &&
            ntop.is_some() && ntop.unwrap().value == '/'
    }

    fn is_digit(&self) -> bool {
        let top = self.top();

        top.is_some() && top.unwrap().value.is_digit(10)
    }

    fn is_whitespace(&self) -> bool {
        let top = self.top();

        top.is_some() && top.unwrap().value.is_whitespace()
    }

    fn is_identifier_start(&self) -> bool {
        let top = self.top();
        if top.is_none() { return false; }

        let ch = top.unwrap().value;

        ( ch >= 'a' && ch <= 'z' ) || ( ch >= 'A' && ch <= 'Z' ) || ch == '_'
    }

    fn is_newline(&self) -> bool {
        let top = self.top();

        top.is_some() && top.unwrap().value == '\n'
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use lexer::reader::StrReader;
    use lexer::token::TokenType;
    use error::ErrorCode;

    fn assert_end(reader: &mut Lexer<StrReader>, l: u32, c: u32) {
        assert_tok(reader, TokenType::End, "", l, c);
    }

    fn assert_tok(reader: &mut Lexer<StrReader>, ttype: TokenType, val: &'static str, l: u32, c: u32) {
        let tok = reader.read_token().unwrap();
        assert_eq!(ttype, tok.ttype);
        assert_eq!(val, tok.value);
        assert_eq!(l, tok.position.line);
        assert_eq!(c, tok.position.column);
    }

    fn assert_err(reader: &mut Lexer<StrReader>, code: ErrorCode, l: u32, c: u32) {
        let err = reader.read_token().unwrap_err();
        assert_eq!(code, err.code);
        assert_eq!(l, err.position.line);
        assert_eq!(c, err.position.column);
    }

    #[test]
    fn test_read_empty_file() {
        let mut reader = Lexer::from_str("");
        assert_end(&mut reader, 1, 1);
        assert_end(&mut reader, 1, 1);
    }

    #[test]
    fn test_read_numbers() {
        let mut reader = Lexer::from_str("1 2\n0123 10");
        assert_tok(&mut reader, TokenType::Number, "1", 1, 1);
        assert_tok(&mut reader, TokenType::Number, "2", 1, 3);
        assert_tok(&mut reader, TokenType::Number, "0123", 2, 1);
        assert_tok(&mut reader, TokenType::Number, "10", 2, 6);
        assert_end(&mut reader, 2, 8);
    }

    #[test]
    fn test_skip_single_line_comment() {
        let mut reader = Lexer::from_str("//test\n1");
        assert_tok(&mut reader, TokenType::Number, "1", 2, 1);
        assert_end(&mut reader, 2, 2);
    }

    #[test]
    fn test_unfinished_line_comment() {
        let mut reader = Lexer::from_str("//abc");
        assert_end(&mut reader, 1, 6);
    }

    #[test]
    fn test_skip_multi_comment() {
        let mut reader = Lexer::from_str("/*test*/1");
        assert_tok(&mut reader, TokenType::Number, "1", 1, 9);
        assert_end(&mut reader, 1, 10);
    }

    #[test]
    fn test_unfinished_multi_comment() {
        let mut reader = Lexer::from_str("/*test");
        assert_err(&mut reader, ErrorCode::UnclosedComment, 1, 1);

        let mut reader = Lexer::from_str("1/*test");
        assert_tok(&mut reader, TokenType::Number, "1", 1, 1);
        assert_err(&mut reader, ErrorCode::UnclosedComment, 1, 2);
    }

    #[test]
    fn test_read_identifier() {
        let mut reader = Lexer::from_str("abc ident test");
        assert_tok(&mut reader, TokenType::Identifier, "abc", 1, 1);
        assert_tok(&mut reader, TokenType::Identifier, "ident", 1, 5);
        assert_tok(&mut reader, TokenType::Identifier, "test", 1, 11);
        assert_end(&mut reader, 1, 15);

    }
}

<commit_msg>added tests for tab in lexer<commit_after>use std::fmt;
use lexer::reader::{CodeReader,StrReader,FileReader};
use lexer::token::{Token,TokenType};
use lexer::position::Position;
use error::{ParseError,ErrorCode};

pub mod reader;
pub mod token;
pub mod position;

struct CharPos {
    value: char,
    position: Position
}

impl fmt::Show for CharPos {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "char {} at line {:?}", self.value, self.position)
    }
}

impl Copy for CharPos {}

pub struct Lexer<T : CodeReader> {
    reader: T,
    position: Position,

    buffer: Vec<CharPos>,
    eof_reached: bool,
    tabwidth: u32
}

impl Lexer<StrReader> {
    pub fn from_str(code: &'static str) -> Lexer<StrReader> {
        Lexer::new(StrReader::new(code))
    }
}

impl Lexer<StrReader> {
    pub fn from_file(filename: &'static str) -> Lexer<FileReader> {
        Lexer::new(FileReader::new(filename))
    }
}

impl<T : CodeReader> Lexer<T> {
    pub fn new(reader: T) -> Lexer<T> {
        Lexer::new_with_tabwidth(reader, 4)
    }

    pub fn new_with_tabwidth(reader: T, tabwidth: u32) -> Lexer<T> {
        let mut lexer = Lexer::<T> {
            reader: reader,
            position: Position::new(1, 1),
            buffer: Vec::with_capacity(10),
            eof_reached: false,
            tabwidth: tabwidth
        };
        lexer.fill_buffer();

        lexer
    }

    pub fn read_token(&mut self) -> Result<Token,ParseError> {
        loop {
            self.skip_white();

            if self.top().is_none() {
                return Ok(Token::new(TokenType::End, self.position));
            }

            if self.is_digit() {
                return self.read_number();

            } else if self.is_comment_start() {
                match self.read_comment() {
                    Some(err) => return Err(err),
                    _ => {}
                }

            } else if self.is_multi_comment_start() {
                match self.read_multi_comment() {
                    Some(err) => return Err(err),
                    _ => {}
                }

            } else if self.is_identifier_start() {
                return self.read_identifier();

            } else {
                let ch = self.top().unwrap().value;

                return Err( ParseError {
                  filename: self.reader.filename().to_string(),
                  position: self.position,
                  code: ErrorCode::UnknownChar,
                  message: format!("unknown character {} (ascii code {}", ch, ch as usize)
                } )
            }
        }
    }

    fn skip_white(&mut self) {
        while self.is_whitespace() {
            self.read_char();
        }
    }

    fn read_comment(&mut self) -> Option<ParseError> {
        while self.top().is_some() && !self.is_newline() {
            self.read_char();
        }

        None
    }

    fn read_multi_comment(&mut self) -> Option<ParseError> {
        let pos = self.top().unwrap().position;

        self.read_char();
        self.read_char();

        while self.top().is_some() && !self.is_multi_comment_end() {
          self.read_char();
        }

        if self.top().is_none() {
          return Some(ParseError {
              filename: self.reader.filename().to_string(),
              position: pos,
              code: ErrorCode::UnclosedComment,
              message: "unclosed comment".to_string()
          } );
        }

        self.read_char();
        self.read_char();

        None
    }

    fn read_identifier(&mut self) -> Result<Token,ParseError> {
        let mut tok = self.build_token(TokenType::Identifier);

        while self.is_digit() || self.is_identifier_start() {
            let ch = self.read_char().unwrap().value;
            tok.value.push(ch);
        }

        Ok(tok)
    }

    fn read_number(&mut self) -> Result<Token,ParseError> {
        let mut tok = self.build_token(TokenType::Number);

        while self.is_digit() {
            let ch = self.read_char().unwrap().value;
            tok.value.push(ch);
        }

        Ok(tok)
    }

    fn read_char(&mut self) -> Option<CharPos> {
        if self.buffer.len() > 0 {
            let ch = self.buffer.remove(0);
            self.fill_buffer();

            Some(ch)
        } else {
            None
        }
    }

    fn top(&self) -> Option<CharPos> {
        self.at(0)
    }

    fn at(&self, index: usize) -> Option<CharPos> {
        if self.buffer.len() > index {
            Some(self.buffer[index])
        } else {
            None
        }
    }

    fn build_token(&self, ttype: TokenType) -> Token {
        Token::new(ttype, self.top().unwrap().position)
    }

    fn fill_buffer(&mut self) {
        while !self.eof_reached && self.buffer.len() < 10 {
            let ch = self.reader.read_char();

            if ch.is_some() {
                let ch = ch.unwrap();
                self.buffer.push(CharPos { value: ch, position: self.position });

                match ch {
                    '\n' => {
                        self.position.line += 1;
                        self.position.column = 1;
                    },

                    '\t' => {
                        let tabdepth = (self.position.column-1)/self.tabwidth;

                        self.position.column = 1 + self.tabwidth * (tabdepth+1);
                    }

                    _ => self.position.column += 1
                }
            } else {
                self.eof_reached = true;
            }
        }
    }

    fn is_comment_start(&self) -> bool {
        let top = self.top();
        let ntop = self.at(1);

        top.is_some() && top.unwrap().value == '/' &&
            ntop.is_some() && ntop.unwrap().value == '/'
    }

    fn is_multi_comment_start(&self) -> bool {
        let top = self.top();
        let ntop = self.at(1);

        top.is_some() && top.unwrap().value == '/' &&
            ntop.is_some() && ntop.unwrap().value == '*'
    }

    fn is_multi_comment_end(&self) -> bool {
        let top = self.top();
        let ntop = self.at(1);

        top.is_some() && top.unwrap().value == '*' &&
            ntop.is_some() && ntop.unwrap().value == '/'
    }

    fn is_digit(&self) -> bool {
        let top = self.top();

        top.is_some() && top.unwrap().value.is_digit(10)
    }

    fn is_whitespace(&self) -> bool {
        let top = self.top();

        top.is_some() && top.unwrap().value.is_whitespace()
    }

    fn is_identifier_start(&self) -> bool {
        let top = self.top();
        if top.is_none() { return false; }

        let ch = top.unwrap().value;

        ( ch >= 'a' && ch <= 'z' ) || ( ch >= 'A' && ch <= 'Z' ) || ch == '_'
    }

    fn is_newline(&self) -> bool {
        let top = self.top();

        top.is_some() && top.unwrap().value == '\n'
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use lexer::reader::StrReader;
    use lexer::token::TokenType;
    use error::ErrorCode;

    fn assert_end(reader: &mut Lexer<StrReader>, l: u32, c: u32) {
        assert_tok(reader, TokenType::End, "", l, c);
    }

    fn assert_tok(reader: &mut Lexer<StrReader>, ttype: TokenType, val: &'static str, l: u32, c: u32) {
        let tok = reader.read_token().unwrap();
        assert_eq!(ttype, tok.ttype);
        assert_eq!(val, tok.value);
        assert_eq!(l, tok.position.line);
        assert_eq!(c, tok.position.column);
    }

    fn assert_err(reader: &mut Lexer<StrReader>, code: ErrorCode, l: u32, c: u32) {
        let err = reader.read_token().unwrap_err();
        assert_eq!(code, err.code);
        assert_eq!(l, err.position.line);
        assert_eq!(c, err.position.column);
    }

    #[test]
    fn test_read_empty_file() {
        let mut reader = Lexer::from_str("");
        assert_end(&mut reader, 1, 1);
        assert_end(&mut reader, 1, 1);
    }

    #[test]
    fn test_read_numbers() {
        let mut reader = Lexer::from_str("1 2\n0123 10");
        assert_tok(&mut reader, TokenType::Number, "1", 1, 1);
        assert_tok(&mut reader, TokenType::Number, "2", 1, 3);
        assert_tok(&mut reader, TokenType::Number, "0123", 2, 1);
        assert_tok(&mut reader, TokenType::Number, "10", 2, 6);
        assert_end(&mut reader, 2, 8);
    }

    #[test]
    fn test_skip_single_line_comment() {
        let mut reader = Lexer::from_str("//test\n1");
        assert_tok(&mut reader, TokenType::Number, "1", 2, 1);
        assert_end(&mut reader, 2, 2);
    }

    #[test]
    fn test_unfinished_line_comment() {
        let mut reader = Lexer::from_str("//abc");
        assert_end(&mut reader, 1, 6);
    }

    #[test]
    fn test_skip_multi_comment() {
        let mut reader = Lexer::from_str("/*test*/1");
        assert_tok(&mut reader, TokenType::Number, "1", 1, 9);
        assert_end(&mut reader, 1, 10);
    }

    #[test]
    fn test_unfinished_multi_comment() {
        let mut reader = Lexer::from_str("/*test");
        assert_err(&mut reader, ErrorCode::UnclosedComment, 1, 1);

        let mut reader = Lexer::from_str("1/*test");
        assert_tok(&mut reader, TokenType::Number, "1", 1, 1);
        assert_err(&mut reader, ErrorCode::UnclosedComment, 1, 2);
    }

    #[test]
    fn test_read_identifier() {
        let mut reader = Lexer::from_str("abc ident test");
        assert_tok(&mut reader, TokenType::Identifier, "abc", 1, 1);
        assert_tok(&mut reader, TokenType::Identifier, "ident", 1, 5);
        assert_tok(&mut reader, TokenType::Identifier, "test", 1, 11);
        assert_end(&mut reader, 1, 15);

    }

    #[test]
    fn test_code_with_spaces() {
        let mut reader = Lexer::from_str("1 2 3");
        assert_tok(&mut reader, TokenType::Number, "1", 1, 1);
        assert_tok(&mut reader, TokenType::Number, "2", 1, 3);
        assert_tok(&mut reader, TokenType::Number, "3", 1, 5);
        assert_end(&mut reader, 1, 6);
    }

    #[test]
    fn test_code_with_newlines() {
        let mut reader = Lexer::from_str("1\n2\n3");
        assert_tok(&mut reader, TokenType::Number, "1", 1, 1);
        assert_tok(&mut reader, TokenType::Number, "2", 2, 1);
        assert_tok(&mut reader, TokenType::Number, "3", 3, 1);
        assert_end(&mut reader, 3, 2);
    }

    #[test]
    fn test_code_with_tabs() {
        let mut reader = Lexer::from_str("1\t2\t3");
        assert_tok(&mut reader, TokenType::Number, "1", 1, 1);
        assert_tok(&mut reader, TokenType::Number, "2", 1, 5);
        assert_tok(&mut reader, TokenType::Number, "3", 1, 9);
        assert_end(&mut reader, 1, 10);
    }

    #[test]
    fn test_code_with_tabwidth8() {
        let mut str_reader = StrReader::new("1\t2\n1234567\t8\n12345678\t9");
        let mut reader = Lexer::new_with_tabwidth(str_reader, 8);

        assert_tok(&mut reader, TokenType::Number, "1", 1, 1);
        assert_tok(&mut reader, TokenType::Number, "2", 1, 9);
        assert_tok(&mut reader, TokenType::Number, "1234567", 2, 1);
        assert_tok(&mut reader, TokenType::Number, "8", 2, 9);
        assert_tok(&mut reader, TokenType::Number, "12345678", 3, 1);
        assert_tok(&mut reader, TokenType::Number, "9", 3, 17);
        assert_end(&mut reader, 3, 18);
    }
}

<|endoftext|>


<commit_before>//!A raytracer.
#![feature(core, os, old_path, old_io)]
extern crate image;
extern crate rand;

use std::old_io::File;
use std::num::Float;
use std::f32::consts::PI_2;
use std::thread;
use std::os;

use rand::distributions::IndependentSample;
use rand::Rng;

use point::Point3;
use vec::Vec3;

mod vec;
mod point;

#[derive(Copy)]
struct Ray3 {
    start: Point3,
    dir: Vec3
}

struct Intersection<ObjectId> {
    time: f32,
    point: Point3,
    normal: Vec3,
    emitted: f32,
    reflection: Reflection,
    object: ObjectId
}

impl<ObjectId> Intersection<ObjectId> {
    fn map_obj<NewObjectId, F: FnOnce(ObjectId) -> NewObjectId>(self, func: F) -> Intersection<NewObjectId> {
        Intersection {
            time: self.time,
            point: self.point,
            normal: self.normal,
            emitted: self.emitted,
            reflection: self.reflection,
            object: func(self.object)
        }
    }
}

trait Scene {
    // TODO: Should this have a "not present" id?
    type ObjectId: Copy;

    fn intersect(&self, ray: Ray3, previous: Option<Self::ObjectId>) -> Option<Intersection<Self::ObjectId>>;
}

#[derive(Copy)]
struct Material {
    reflection: Reflection,
    emitted_radiance: f32
}

#[derive(Copy)]
enum Reflection {
    Diffuse,
    Specular
}

struct Sphere {
    center: Point3,
    radius: f32,
    material: Material
}

#[derive(Copy)]
enum SphereSource {
    Inside,
    Outside
}

impl Scene for Sphere {
    type ObjectId = SphereSource;
    fn intersect(&self, ray: Ray3, previous: Option<SphereSource>) -> Option<Intersection<SphereSource>> {
        if let Some(SphereSource::Outside) = previous {
            return None;
        }

        let offset = ray.start - self.center;

        let a = ray.dir.mag2();
        let b = 2. * offset.dot(ray.dir);
        let c = offset.mag2() - self.radius*self.radius;

        let descrim = b*b - 4.*a*c;
        if descrim < 0. {
            return None;
        }

        let time = {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if previous.is_none() && t1 > 0. {
                t1
            } else if t2 > 0. {
                t2
            } else {
                return None;
            }
        };

        let p = ray.start + ray.dir * time;
        let normal = p - self.center;
        Some(Intersection {
            time: time,
            point: p,
            normal: normal,
            emitted: self.material.emitted_radiance,
            reflection: self.material.reflection,
            object: match previous {
                None => SphereSource::Outside,
                Some(source) => source
            }
        })
    }
}

struct Plane {
    origin: Point3,
    normal: Vec3,
    material: Material
}

impl Scene for Plane {
    type ObjectId = ();
    fn intersect(&self, ray: Ray3, previous: Option<()>) -> Option<Intersection<()>> {
        if let Some(()) = previous {
            return None;
        }

        let divisor = ray.dir.dot(self.normal);
        if divisor == 0. {
            None
        } else {
            let offset = ray.start - self.origin;
            let time = -offset.dot(self.normal) / divisor;
            if time > 0. {
                Some(Intersection {
                    time: time,
                    point: ray.start + ray.dir * time,
                    normal: self.normal,
                    emitted: self.material.emitted_radiance,
                    reflection: self.material.reflection,
                    object: ()
                })
            } else {
                None
            }
        }
    }
}

#[derive(Copy)]
enum Choice<A, B> {
    OptA(A),
    OptB(B)
}

impl<A: Scene, B: Scene> Scene for (A, B) {
    type ObjectId = Choice<A::ObjectId, B::ObjectId>;
    fn intersect(&self, ray: Ray3, previous: Option<Choice<A::ObjectId, B::ObjectId>>) -> Option<Intersection<Choice<A::ObjectId, B::ObjectId>>> {
        let (aid, bid) = match previous {
            None => (None, None),
            Some(Choice::OptA(aid)) => (Some(aid), None),
            Some(Choice::OptB(bid)) => (None, Some(bid))
        };

        match (self.0.intersect(ray, aid), self.1.intersect(ray, bid)) {
            (Some(ai), Some(bi)) => if ai.time < bi.time {
                Some(ai.map_obj(Choice::OptA))
            } else {
                Some(bi.map_obj(Choice::OptB))
            },
            (Some(ai), None) => Some(ai.map_obj(Choice::OptA)),
            (None, Some(bi)) => Some(bi.map_obj(Choice::OptB)),
            (None, None) => None
        }
    }
}

impl<T: Scene> Scene for [T] {
    type ObjectId = (usize, T::ObjectId);
    fn intersect(&self, ray: Ray3, previous: Option<(usize, T::ObjectId)>) -> Option<Intersection<(usize, T::ObjectId)>> {
        let mut best: Option<Intersection<(usize, T::ObjectId)>> = None;

        for (id, obj) in self.iter().enumerate() {
            let prev = match previous {
                Some((prev_index, prev_obj)) => if prev_index == id {
                    Some(prev_obj)
                } else {
                    None
                },
                None => None
            };

            if let Some(intersection) = obj.intersect(ray, prev) {
                let new_best = match best {
                    Some(ref cur_best) => intersection.time < cur_best.time,
                    None => true
                };

                if new_best {
                    best = Some(intersection.map_obj(|obj| (id, obj)));
                }
            }
        }

        best
    }
}

impl<'a, T: ?Sized + Scene> Scene for &'a T {
    type ObjectId = T::ObjectId;
    fn intersect(&self, ray: Ray3, previous: Option<T::ObjectId>) -> Option<Intersection<T::ObjectId>> {
        (*self).intersect(ray, previous)
    }
}

fn clamp(val: f32) -> f32 {
    if val > 1. {
        1.
    } else if val < 0. {
        0.
    } else {
        val
    }
}

fn rand_sphere<R: rand::Rng>(rng: &mut R) -> Vec3 {
    let z = rand::distributions::Range::new(-1., 1.).ind_sample(rng);
    let r = (1. - z*z).sqrt();
    let angle = rand::distributions::Range::new(0., PI_2).ind_sample(rng);
    Vec3::new(r*angle.cos(), r*angle.sin(), z)
}

fn main() {
    let rays_per_pixel = 200;
    let scene: (&[Sphere], &[Plane]) = (
        &[Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.0, 2.5, 0.5),
            radius: 1.0,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 20. }
        },
        Sphere {
            center: Point3::new(-1.5, 0.0, 3.5),
            radius: 1.0,
            material: Material { reflection: Reflection::Specular, emitted_radiance: 0. }
        }],
        &[Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 2.0, 0.0),
            normal: Vec3::new(0.0, -1.0, 0.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, -3.0, 0.0),
            normal: Vec3::new(0.0, 1.0, 0.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, -10.0),
            normal: Vec3::new(0.0, 0.0, 1.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        }]
    );

    let num_threads = os::num_cpus();

    let imgx = 800;
    let imgy = 800;

    let scalex = 4.0 / imgx as f32;
    let scaley = 4.0 / imgy as f32;

    // Create a new ImgBuf with width: imgx and height: imgy
    let mut imgbuf = image::ImageBuffer::<image::Luma<u8>>::new(imgx, imgy);

    // Iterate over the pixels in parallel
    {
        let mut img_data = imgbuf.as_mut_slice();
        let chunk_size = img_data.len() / num_threads + 1;
        img_data.chunks_mut(chunk_size).enumerate().map(|(chunk_i, chunk)| {
            thread::scoped(move || {
                let mut rng = rand::weak_rng();

                let base = (chunk_i * chunk_size) as u32;
                let mut x = base % imgx;
                let mut y = base / imgx;
                for pixel in chunk.iter_mut() {
                    x += 1;
                    if x == imgx {
                        x = 0;
                        y += 1;
                    }
        let cy = -(y as f32 * scaley - 2.0);
        let cx = x as f32 * scalex - 2.0;

        let mut total_light = 0.;
        for _ in 0..rays_per_pixel {
            let mut ray = Ray3 {
                start: Point3::new(0., 0., -8.0),
                dir: Vec3::new(cx, cy, 8.0)
            };
            let mut prev_object = None;
            let mut scale = 1.;
            loop {
                if let Some(intersection) = scene.intersect(ray, prev_object) {
                    prev_object = Some(intersection.object);

                    total_light += scale * intersection.emitted;

                    ray = match intersection.reflection {
                        Reflection::Specular => {
                            let projected = intersection.normal * ray.dir.dot(intersection.normal) / intersection.normal.mag2();
                            let new_dir = -ray.dir - projected * 2.;
                            Ray3 {
                                start: intersection.point,
                                dir: new_dir
                            }
                        },
                        Reflection::Diffuse => {
                            let cand_dir = rand_sphere(&mut rng);
                            let dir = if cand_dir.dot(intersection.normal) < 0. {
                                -cand_dir
                            } else {
                                cand_dir
                            };

                            let p = dir.dot(intersection.normal) / intersection.normal.mag2().sqrt();
                            if scale > 0.2 {
                                scale *= p;
                            } else if rng.next_f32() > p {
                                break;
                            }

                            Ray3 {
                                start: intersection.point,
                                dir: dir
                            }
                        }
                    }
                } else {
                    break;
                }
            }
        }

                    // Create an 8bit pixel of type Luma and value i
                    // and assign in to the pixel at position (x, y)
                    *pixel = (clamp(total_light / rays_per_pixel as f32)*255.) as u8;
                }
            })
        }).collect::<Vec<_>>();
    }

    // Save the image as “out.png”
    let ref mut fout = File::create(&Path::new("out.png")).unwrap();

    // We must indicate the image’s color type and what format to save as
    let _ = image::ImageLuma8(imgbuf).save(fout, image::PNG);
}
<commit_msg>Indent after parallelization<commit_after>//!A raytracer.
#![feature(core, os, old_path, old_io)]
extern crate image;
extern crate rand;

use std::old_io::File;
use std::num::Float;
use std::f32::consts::PI_2;
use std::thread;
use std::os;

use rand::distributions::IndependentSample;
use rand::Rng;

use point::Point3;
use vec::Vec3;

mod vec;
mod point;

#[derive(Copy)]
struct Ray3 {
    start: Point3,
    dir: Vec3
}

struct Intersection<ObjectId> {
    time: f32,
    point: Point3,
    normal: Vec3,
    emitted: f32,
    reflection: Reflection,
    object: ObjectId
}

impl<ObjectId> Intersection<ObjectId> {
    fn map_obj<NewObjectId, F: FnOnce(ObjectId) -> NewObjectId>(self, func: F) -> Intersection<NewObjectId> {
        Intersection {
            time: self.time,
            point: self.point,
            normal: self.normal,
            emitted: self.emitted,
            reflection: self.reflection,
            object: func(self.object)
        }
    }
}

trait Scene {
    // TODO: Should this have a "not present" id?
    type ObjectId: Copy;

    fn intersect(&self, ray: Ray3, previous: Option<Self::ObjectId>) -> Option<Intersection<Self::ObjectId>>;
}

#[derive(Copy)]
struct Material {
    reflection: Reflection,
    emitted_radiance: f32
}

#[derive(Copy)]
enum Reflection {
    Diffuse,
    Specular
}

struct Sphere {
    center: Point3,
    radius: f32,
    material: Material
}

#[derive(Copy)]
enum SphereSource {
    Inside,
    Outside
}

impl Scene for Sphere {
    type ObjectId = SphereSource;
    fn intersect(&self, ray: Ray3, previous: Option<SphereSource>) -> Option<Intersection<SphereSource>> {
        if let Some(SphereSource::Outside) = previous {
            return None;
        }

        let offset = ray.start - self.center;

        let a = ray.dir.mag2();
        let b = 2. * offset.dot(ray.dir);
        let c = offset.mag2() - self.radius*self.radius;

        let descrim = b*b - 4.*a*c;
        if descrim < 0. {
            return None;
        }

        let time = {
            let t1 = (-b - descrim.sqrt()) / (2. * a);
            let t2 = (-b + descrim.sqrt()) / (2. * a);
            if previous.is_none() && t1 > 0. {
                t1
            } else if t2 > 0. {
                t2
            } else {
                return None;
            }
        };

        let p = ray.start + ray.dir * time;
        let normal = p - self.center;
        Some(Intersection {
            time: time,
            point: p,
            normal: normal,
            emitted: self.material.emitted_radiance,
            reflection: self.material.reflection,
            object: match previous {
                None => SphereSource::Outside,
                Some(source) => source
            }
        })
    }
}

struct Plane {
    origin: Point3,
    normal: Vec3,
    material: Material
}

impl Scene for Plane {
    type ObjectId = ();
    fn intersect(&self, ray: Ray3, previous: Option<()>) -> Option<Intersection<()>> {
        if let Some(()) = previous {
            return None;
        }

        let divisor = ray.dir.dot(self.normal);
        if divisor == 0. {
            None
        } else {
            let offset = ray.start - self.origin;
            let time = -offset.dot(self.normal) / divisor;
            if time > 0. {
                Some(Intersection {
                    time: time,
                    point: ray.start + ray.dir * time,
                    normal: self.normal,
                    emitted: self.material.emitted_radiance,
                    reflection: self.material.reflection,
                    object: ()
                })
            } else {
                None
            }
        }
    }
}

#[derive(Copy)]
enum Choice<A, B> {
    OptA(A),
    OptB(B)
}

impl<A: Scene, B: Scene> Scene for (A, B) {
    type ObjectId = Choice<A::ObjectId, B::ObjectId>;
    fn intersect(&self, ray: Ray3, previous: Option<Choice<A::ObjectId, B::ObjectId>>) -> Option<Intersection<Choice<A::ObjectId, B::ObjectId>>> {
        let (aid, bid) = match previous {
            None => (None, None),
            Some(Choice::OptA(aid)) => (Some(aid), None),
            Some(Choice::OptB(bid)) => (None, Some(bid))
        };

        match (self.0.intersect(ray, aid), self.1.intersect(ray, bid)) {
            (Some(ai), Some(bi)) => if ai.time < bi.time {
                Some(ai.map_obj(Choice::OptA))
            } else {
                Some(bi.map_obj(Choice::OptB))
            },
            (Some(ai), None) => Some(ai.map_obj(Choice::OptA)),
            (None, Some(bi)) => Some(bi.map_obj(Choice::OptB)),
            (None, None) => None
        }
    }
}

impl<T: Scene> Scene for [T] {
    type ObjectId = (usize, T::ObjectId);
    fn intersect(&self, ray: Ray3, previous: Option<(usize, T::ObjectId)>) -> Option<Intersection<(usize, T::ObjectId)>> {
        let mut best: Option<Intersection<(usize, T::ObjectId)>> = None;

        for (id, obj) in self.iter().enumerate() {
            let prev = match previous {
                Some((prev_index, prev_obj)) => if prev_index == id {
                    Some(prev_obj)
                } else {
                    None
                },
                None => None
            };

            if let Some(intersection) = obj.intersect(ray, prev) {
                let new_best = match best {
                    Some(ref cur_best) => intersection.time < cur_best.time,
                    None => true
                };

                if new_best {
                    best = Some(intersection.map_obj(|obj| (id, obj)));
                }
            }
        }

        best
    }
}

impl<'a, T: ?Sized + Scene> Scene for &'a T {
    type ObjectId = T::ObjectId;
    fn intersect(&self, ray: Ray3, previous: Option<T::ObjectId>) -> Option<Intersection<T::ObjectId>> {
        (*self).intersect(ray, previous)
    }
}

fn clamp(val: f32) -> f32 {
    if val > 1. {
        1.
    } else if val < 0. {
        0.
    } else {
        val
    }
}

fn rand_sphere<R: rand::Rng>(rng: &mut R) -> Vec3 {
    let z = rand::distributions::Range::new(-1., 1.).ind_sample(rng);
    let r = (1. - z*z).sqrt();
    let angle = rand::distributions::Range::new(0., PI_2).ind_sample(rng);
    Vec3::new(r*angle.cos(), r*angle.sin(), z)
}

fn main() {
    let rays_per_pixel = 200;
    let scene: (&[Sphere], &[Plane]) = (
        &[Sphere {
            center: Point3::new(1.2, 0.0, 5.0),
            radius: 0.3,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.5, 0.0, 3.5),
            radius: 0.35,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Sphere {
            center: Point3::new(1.0, 2.5, 0.5),
            radius: 1.0,
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 20. }
        },
        Sphere {
            center: Point3::new(-1.5, 0.0, 3.5),
            radius: 1.0,
            material: Material { reflection: Reflection::Specular, emitted_radiance: 0. }
        }],
        &[Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(2.0, 0.0, -1.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, 8.0),
            normal: Vec3::new(-1.0, 0.0, -2.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 2.0, 0.0),
            normal: Vec3::new(0.0, -1.0, 0.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, -3.0, 0.0),
            normal: Vec3::new(0.0, 1.0, 0.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        },
        Plane {
            origin: Point3::new(0.0, 0.0, -10.0),
            normal: Vec3::new(0.0, 0.0, 1.0),
            material: Material { reflection: Reflection::Diffuse, emitted_radiance: 0. }
        }]
    );

    let num_threads = os::num_cpus();

    let imgx = 800;
    let imgy = 800;

    let scalex = 4.0 / imgx as f32;
    let scaley = 4.0 / imgy as f32;

    // Create a new ImgBuf with width: imgx and height: imgy
    let mut imgbuf = image::ImageBuffer::<image::Luma<u8>>::new(imgx, imgy);

    // Iterate over the pixels in parallel
    {
        let mut img_data = imgbuf.as_mut_slice();
        let chunk_size = img_data.len() / num_threads + 1;
        img_data.chunks_mut(chunk_size).enumerate().map(|(chunk_i, chunk)| {
            thread::scoped(move || {
                let mut rng = rand::weak_rng();

                let base = (chunk_i * chunk_size) as u32;
                let mut x = base % imgx;
                let mut y = base / imgx;
                for pixel in chunk.iter_mut() {
                    x += 1;
                    if x == imgx {
                        x = 0;
                        y += 1;
                    }

                    let cy = -(y as f32 * scaley - 2.0);
                    let cx = x as f32 * scalex - 2.0;

                    let mut total_light = 0.;
                    for _ in 0..rays_per_pixel {
                        let mut ray = Ray3 {
                            start: Point3::new(0., 0., -8.0),
                            dir: Vec3::new(cx, cy, 8.0)
                        };
                        let mut prev_object = None;
                        let mut scale = 1.;
                        loop {
                            if let Some(intersection) = scene.intersect(ray, prev_object) {
                                prev_object = Some(intersection.object);

                                total_light += scale * intersection.emitted;

                                ray = match intersection.reflection {
                                    Reflection::Specular => {
                                        let projected = intersection.normal * ray.dir.dot(intersection.normal) / intersection.normal.mag2();
                                        let new_dir = -ray.dir - projected * 2.;
                                        Ray3 {
                                            start: intersection.point,
                                            dir: new_dir
                                        }
                                    },
                                    Reflection::Diffuse => {
                                        let cand_dir = rand_sphere(&mut rng);
                                        let dir = if cand_dir.dot(intersection.normal) < 0. {
                                            -cand_dir
                                        } else {
                                            cand_dir
                                        };

                                        let p = dir.dot(intersection.normal) / intersection.normal.mag2().sqrt();
                                        if scale > 0.2 {
                                            scale *= p;
                                        } else if rng.next_f32() > p {
                                            break;
                                        }

                                        Ray3 {
                                            start: intersection.point,
                                            dir: dir
                                        }
                                    }
                                }
                            } else {
                                break;
                            }
                        }
                    }

                    // Create an 8bit pixel of type Luma and value i
                    // and assign in to the pixel at position (x, y)
                    *pixel = (clamp(total_light / rays_per_pixel as f32)*255.) as u8;
                }
            })
        }).collect::<Vec<_>>();
    }

    // Save the image as “out.png”
    let ref mut fout = File::create(&Path::new("out.png")).unwrap();

    // We must indicate the image’s color type and what format to save as
    let _ = image::ImageLuma8(imgbuf).save(fout, image::PNG);
}
<|endoftext|>


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

use lang::Lang;
use error::Result;
use macrogen;

/// Main struct for initiating localization for a project.
///
/// # Example
///
/// ```rust
/// use crowbook_localize::Localizer;
/// let fr = r#"
/// msgid "Hello, {}"
/// msgstr "Bonjour, {}"
/// "#;
/// let es = r#"
/// msgid "Hello, {}"
/// msgstr "Hola, {}"
/// "#;
/// let mut localizer = Localizer::new();
/// localizer.add_lang("fr", fr).unwrap();
/// localizer.add_lang("es", es).unwrap();
/// ```
pub struct Localizer {
    langs: Vec<Lang>,
}

impl Localizer {
    /// Create a new, empty Localizer
    pub fn new() -> Localizer {
        Localizer { langs: vec!() }
    }

    /// Add a lang to the localizer
    ///
    /// # Arguments
    ///
    /// * `lang`: the code of the language (e.g. "fr", "en", ...);
    /// * `s`: a string containing localization information. It should be foramtted
    /// similarly to gettext `mo` files.
    pub fn add_lang<S: Into<String>>(&mut self, lang: S, s: &str) -> Result<()> {
        let lang = try!(Lang::new_from_str(lang, s));
        self.langs.push(lang);
        Ok(())
    }

    /// Generate the `localization_macros.rs` file.
    pub fn generate_macro_file(mut self) -> String {
        macrogen::generate_macro_file(&mut self.langs)
    }
}
<commit_msg>Add write_macro_file to Localizer<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at https://mozilla.org/MPL/2.0/.

use lang::Lang;
use error::{Result, Error};
use macrogen;

use std::fs::File;
use std::io::Write;

/// Main struct for initiating localization for a project.
///
/// # Example
///
/// ```rust
/// use crowbook_localize::Localizer;
/// let fr = r#"
/// msgid "Hello, {}"
/// msgstr "Bonjour, {}"
/// "#;
/// let es = r#"
/// msgid "Hello, {}"
/// msgstr "Hola, {}"
/// "#;
/// let mut localizer = Localizer::new();
/// localizer.add_lang("fr", fr).unwrap();
/// localizer.add_lang("es", es).unwrap();
/// ```
pub struct Localizer {
    langs: Vec<Lang>,
}

impl Localizer {
    /// Create a new, empty Localizer
    pub fn new() -> Localizer {
        Localizer { langs: vec!() }
    }

    /// Add a lang to the localizer
    ///
    /// # Arguments
    ///
    /// * `lang`: the code of the language (e.g. "fr", "en", ...);
    /// * `s`: a string containing localization information. It should be foramtted
    /// similarly to gettext `mo` files.
    pub fn add_lang<S: Into<String>>(&mut self, lang: S, s: &str) -> Result<()> {
        let lang = try!(Lang::new_from_str(lang, s));
        self.langs.push(lang);
        Ok(())
    }

    /// Generate the `localization_macros.rs` file.
    pub fn generate_macro_file(mut self) -> String {
        macrogen::generate_macro_file(&mut self.langs)
    }

    /// Write the `localization_macros.rs` file to a file.
    pub fn write_macro_file(self, file: &str) -> Result<()> {
        let mut f = try!(File::create(file).map_err(|e| Error::new(format!("Could not create file {}: {}",
                                                                              file, e))));
        let content = self.generate_macro_file();
        try!(f.write_all(content.as_bytes())
             .map_err(|e| Error::new(format!("Could not write to file {}: {}",
                                             file, e))));
        Ok(())
    }
}
<|endoftext|>


<commit_before>use core::num::{One, Zero};
use core::vec::{from_elem, swap};
use traits::dim::Dim;
use traits::inv::Inv;
use traits::transpose::Transpose;
// use ndim::nvec::NVec;

// D is a phantom type parameter, used only as a dimensional token.
// Its allows use to encode the vector dimension at the type-level.
// It can be anything implementing the Dim trait. However, to avoid confusion,
// using d0, d1, d2, d3 and d4 tokens are prefered.
#[deriving(Eq)]
pub struct NMat<D, T>
{
  mij: ~[T]
}

impl<D: Dim, T: Copy> NMat<D, T>
{
  fn offset(i: uint, j: uint) -> uint
  { i * Dim::dim::<D>() + j }

  fn set(&mut self, i: uint, j: uint, t: &T)
  { self.mij[NMat::offset::<D, T>(i, j)] = *t }
}

impl<D: Dim, T> Dim for NMat<D, T>
{
  fn dim() -> uint
  { Dim::dim::<D>() }
}

impl<D: Dim, T:Copy> Index<(uint, uint), T> for NMat<D, T>
{
  fn index(&self, &(i, j): &(uint, uint)) -> T
  { self.mij[NMat::offset::<D, T>(i, j)] }
}

impl<D: Dim, T:Copy + One + Zero> One for NMat<D, T>
{
  fn one() -> NMat<D, T>
  {
    let     dim = Dim::dim::<D>();
    let mut res = NMat{ mij: from_elem(dim * dim, Zero::zero()) };
    let     _1  = One::one::<T>();

    for uint::range(0u, dim) |i|
    { res.set(i, i, &_1); }

    res
  }
}

impl<D: Dim, T:Copy + Zero> Zero for NMat<D, T>
{
  fn zero() -> NMat<D, T>
  {
    let dim = Dim::dim::<D>();

    NMat{ mij: from_elem(dim * dim, Zero::zero()) }
  }
}

impl<D: Dim, T:Copy + Mul<T, T> + Add<T, T> + Zero>
Mul<NMat<D, T>, NMat<D, T>> for NMat<D, T>
{
  fn mul(&self, other: &NMat<D, T>) -> NMat<D, T>
  {
    let     dim = Dim::dim::<D>();
    let mut res = Zero::zero::<NMat<D, T>>();

    for uint::range(0u, dim) |i|
    {
      for uint::range(0u, dim) |j|
      {
        let mut acc: T = Zero::zero();

        for uint::range(0u, dim) |k|
        { acc += self[(i, k)] * other[(k, j)]; }

        res.set(i, j, &acc);
      }
    }

    res
  }
}

impl<D: Dim,
     T: Copy + Mul<T, T> + Div<T, T> + Sub<T, T> + Neg<T> + Eq + One + Zero>
Inv for NMat<D, T>
{
  fn inv(&self) -> NMat<D, T>
  {
    let mut cpy = copy *self;
    let     dim = Dim::dim::<D>();
    let mut res = One::one::<NMat<D, T>>();
    let     _0T = Zero::zero::<T>();

    // inversion using Gauss-Jordan elimination
    for uint::range(0u, dim) |k|
    {
      // search a non-zero value on the k-th column
      // FIXME: is it worth it to spend some more time searching for the max
      // instead?

      // FIXME: this is kind of uggly…
      // … but we cannot use position_betwee since we are iterating on one
      // columns
      let mut n0 = dim; // index of a non-zero entry

      for uint::range(k, dim) |i|
      {
        n0 = k;

        if (cpy[(i, k)] != _0T)
        { break; }
      }

      assert!(n0 != dim); // non inversible matrix

      // swap pivot line
      for uint::range(0u, dim) |j|
      {
        swap(cpy.mij, NMat::offset::<D, T>(n0, j), NMat::offset::<D, T>(k, j));
        swap(res.mij, NMat::offset::<D, T>(n0, j), NMat::offset::<D, T>(k, j));
      }

      let pivot = cpy[(k, k)];

      for uint::range(k, dim) |j|
      {
        cpy.set(k, j, &(cpy[(k, j)] / pivot));
        res.set(k, j, &(res[(k, j)] / pivot));
      }

      for uint::range(0u, dim) |l|
      {
        if (l != k)
        {
          let normalizer = cpy[(l, k)] / pivot;

          for uint::range(k, dim) |j|
          {
            cpy.set(k, j, &(cpy[(l, j)] - cpy[(k, j)] * normalizer));
            res.set(k, j, &(res[(l, j)] - res[(k, j)] * normalizer));
          }
        }
      }
    }

    res
  }
}

impl<D: Dim, T:Copy> Transpose for NMat<D, T>
{
  fn transposed(&self) -> NMat<D, T>
  {
    let mut res = copy *self;

    res.transpose();

    res
  }

  fn transpose(&mut self)
  {
    let dim = Dim::dim::<D>();

    for uint::range(1u, dim) |i|
    {
      for uint::range(0u, dim - 1) |j|
      {
        swap(self.mij,
             NMat::offset::<D, T>(i, j),
             NMat::offset::<D, T>(j, i));
      }
    }
  }
}

impl<D: Dim, T:ToStr> ToStr for NMat<D, T>
{
  fn to_str(&self) -> ~str
  { ~"Mat" + Dim::dim::<D>().to_str() + " {" + self.mij.to_str() + " }" }
}
<commit_msg>Replaced an uggly for by a bit less uggly while for the matrix inversion.<commit_after>use core::num::{One, Zero};
use core::vec::{from_elem, swap};
use traits::dim::Dim;
use traits::inv::Inv;
use traits::transpose::Transpose;
// use ndim::nvec::NVec;

// D is a phantom type parameter, used only as a dimensional token.
// Its allows use to encode the vector dimension at the type-level.
// It can be anything implementing the Dim trait. However, to avoid confusion,
// using d0, d1, d2, d3 and d4 tokens are prefered.
#[deriving(Eq)]
pub struct NMat<D, T>
{
  mij: ~[T]
}

impl<D: Dim, T: Copy> NMat<D, T>
{
  fn offset(i: uint, j: uint) -> uint
  { i * Dim::dim::<D>() + j }

  fn set(&mut self, i: uint, j: uint, t: &T)
  { self.mij[NMat::offset::<D, T>(i, j)] = *t }
}

impl<D: Dim, T> Dim for NMat<D, T>
{
  fn dim() -> uint
  { Dim::dim::<D>() }
}

impl<D: Dim, T:Copy> Index<(uint, uint), T> for NMat<D, T>
{
  fn index(&self, &(i, j): &(uint, uint)) -> T
  { self.mij[NMat::offset::<D, T>(i, j)] }
}

impl<D: Dim, T:Copy + One + Zero> One for NMat<D, T>
{
  fn one() -> NMat<D, T>
  {
    let     dim = Dim::dim::<D>();
    let mut res = NMat{ mij: from_elem(dim * dim, Zero::zero()) };
    let     _1  = One::one::<T>();

    for uint::range(0u, dim) |i|
    { res.set(i, i, &_1); }

    res
  }
}

impl<D: Dim, T:Copy + Zero> Zero for NMat<D, T>
{
  fn zero() -> NMat<D, T>
  {
    let dim = Dim::dim::<D>();

    NMat{ mij: from_elem(dim * dim, Zero::zero()) }
  }
}

impl<D: Dim, T:Copy + Mul<T, T> + Add<T, T> + Zero>
Mul<NMat<D, T>, NMat<D, T>> for NMat<D, T>
{
  fn mul(&self, other: &NMat<D, T>) -> NMat<D, T>
  {
    let     dim = Dim::dim::<D>();
    let mut res = Zero::zero::<NMat<D, T>>();

    for uint::range(0u, dim) |i|
    {
      for uint::range(0u, dim) |j|
      {
        let mut acc: T = Zero::zero();

        for uint::range(0u, dim) |k|
        { acc += self[(i, k)] * other[(k, j)]; }

        res.set(i, j, &acc);
      }
    }

    res
  }
}

impl<D: Dim,
     T: Copy + Mul<T, T> + Div<T, T> + Sub<T, T> + Neg<T> + Eq + One + Zero>
Inv for NMat<D, T>
{
  fn inv(&self) -> NMat<D, T>
  {
    let mut cpy = copy *self;
    let     dim = Dim::dim::<D>();
    let mut res = One::one::<NMat<D, T>>();
    let     _0T = Zero::zero::<T>();

    // inversion using Gauss-Jordan elimination
    for uint::range(0u, dim) |k|
    {
      // search a non-zero value on the k-th column
      // FIXME: is it worth it to spend some more time searching for the max
      // instead?

      // FIXME: this is kind of uggly…
      // … but we cannot use position_betwee since we are iterating on one
      // columns
      let mut n0 = 0u; // index of a non-zero entry

      while (n0 != dim)
      {
        if (cpy[(n0, k)] != _0T)
        { break; }

        n0 += 1;
      }

      assert!(n0 != dim); // non inversible matrix

      // swap pivot line
      if (n0 != k)
      {
        for uint::range(0u, dim) |j|
        {
          swap(cpy.mij,
               NMat::offset::<D, T>(n0, j),
               NMat::offset::<D, T>(k, j));
          swap(res.mij,
               NMat::offset::<D, T>(n0, j),
               NMat::offset::<D, T>(k, j));
        }
      }

      let pivot = cpy[(k, k)];

      for uint::range(k, dim) |j|
      {
        cpy.set(k, j, &(cpy[(k, j)] / pivot));
        res.set(k, j, &(res[(k, j)] / pivot));
      }

      for uint::range(0u, dim) |l|
      {
        if (l != k)
        {
          let normalizer = cpy[(l, k)] / pivot;

          for uint::range(k, dim) |j|
          {
            cpy.set(k, j, &(cpy[(l, j)] - cpy[(k, j)] * normalizer));
            res.set(k, j, &(res[(l, j)] - res[(k, j)] * normalizer));
          }
        }
      }
    }

    res
  }
}

impl<D: Dim, T:Copy> Transpose for NMat<D, T>
{
  fn transposed(&self) -> NMat<D, T>
  {
    let mut res = copy *self;

    res.transpose();

    res
  }

  fn transpose(&mut self)
  {
    let dim = Dim::dim::<D>();

    for uint::range(1u, dim) |i|
    {
      for uint::range(0u, dim - 1) |j|
      {
        swap(self.mij,
             NMat::offset::<D, T>(i, j),
             NMat::offset::<D, T>(j, i));
      }
    }
  }
}

impl<D: Dim, T:ToStr> ToStr for NMat<D, T>
{
  fn to_str(&self) -> ~str
  { ~"Mat" + Dim::dim::<D>().to_str() + " {" + self.mij.to_str() + " }" }
}
<|endoftext|>


<commit_before>// Copyright 2014-2018 Optimal Computing (NZ) Ltd.
// Licensed under the MIT license.  See LICENSE for details.

use std::mem;
use num_traits::NumCast;

/// A trait for floating point numbers which computes the number of representable
/// values or ULPs (Units of Least Precision) that separate the two given values.
pub trait Ulps {
    type U: Copy + NumCast;

    /// The number of representable values or ULPs (Units of Least Precision) that
    /// separate `self` and `other`.  The result `U` is an integral value, and will
    /// be zero if `self` and `other` are exactly equal.
    fn ulps(&self, other: &Self) -> <Self as Ulps>::U;
}

impl Ulps for f32 {
    type U = i32;

    fn ulps(&self, other: &f32) -> i32 {

        // IEEE754 defined floating point storage representation to
        // maintain their order when their bit patterns are interpreted as
        // integers.  This is a huge boon to the task at hand, as we can
        // (unsafely) cast to integers to find out how many ULPs apart any
        // two floats are

        // Setup integer representations of the input
        let ai32: i32 = unsafe { mem::transmute::<f32,i32>(*self) };
        let bi32: i32 = unsafe { mem::transmute::<f32,i32>(*other) };

        ai32.wrapping_sub(bi32)
    }
}

#[test]
fn f32_ulps_test1() {
    let x: f32 = 1000000_f32;
    let y: f32 = 1000000.1_f32;
    println!("DIST IS {}",x.ulps(&y));
    assert!(x.ulps(&y) == -2);
}

#[test]
fn f32_ulps_test2() {
    let pzero: f32 = f32::from_bits(0x00000000_u32);
    let nzero: f32 = f32::from_bits(0x80000000_u32);
    println!("DIST IS {}",pzero.ulps(&nzero));
    assert!(pzero.ulps(&nzero) == -2147483648);
}
#[test]
fn f32_ulps_test3() {
    let pinf: f32 = f32::from_bits(0x7f800000_u32);
    let ninf: f32 = f32::from_bits(0xff800000_u32);
    println!("DIST IS {}",pinf.ulps(&ninf));
    assert!(pinf.ulps(&ninf) == -2147483648);
}

#[test]
fn f32_ulps_test4() {
    let x: f32 = f32::from_bits(0x63a7f026_u32);
    let y: f32 = f32::from_bits(0x63a7f023_u32);
    println!("DIST IS {}",x.ulps(&y));
    assert!(x.ulps(&y) == 3);
}

#[test]
fn f32_ulps_test5() {
    let x: f32 = 2.0;
    let ulps: i32 = unsafe { mem::transmute(x) };
    let x2: f32 = unsafe { mem::transmute(ulps) };
    assert_eq!(x, x2);
}

impl Ulps for f64 {
    type U = i64;

    fn ulps(&self, other: &f64) -> i64 {

        // IEEE754 defined floating point storage representation to
        // maintain their order when their bit patterns are interpreted as
        // integers.  This is a huge boon to the task at hand, as we can
        // (unsafely) cast to integers to find out how many ULPs apart any
        // two floats are

        // Setup integer representations of the input
        let ai64: i64 = unsafe { mem::transmute::<f64,i64>(*self) };
        let bi64: i64 = unsafe { mem::transmute::<f64,i64>(*other) };

        ai64.wrapping_sub(bi64)
    }
}

#[test]
fn f64_ulps_test1() {
    let x: f64 = 1000000_f64;
    let y: f64 = 1000000.00000001_f64;
    println!("DIST IS {}",x.ulps(&y));
    assert!(x.ulps(&y) == -86);
}

#[test]
fn f64_ulps_test2() {
    let pzero: f64 = f64::from_bits(0x0000000000000000_u64);
    let nzero: f64 = f64::from_bits(0x8000000000000000_u64);
    println!("DIST IS {}",pzero.ulps(&nzero));
    assert!(pzero.ulps(&nzero) == -9223372036854775808i64);
}
#[test]
fn f64_ulps_test3() {
    let pinf: f64 = f64::from_bits(0x7f80000000000000_u64);
    let ninf: f64 = f64::from_bits(0xff80000000000000_u64);
    println!("DIST IS {}",pinf.ulps(&ninf));
    assert!(pinf.ulps(&ninf) == -9223372036854775808i64);
}

#[test]
fn f64_ulps_test4() {
    let x: f64 = f64::from_bits(0xd017f6cc63a7f026_u64);
    let y: f64 = f64::from_bits(0xd017f6cc63a7f023_u64);
    println!("DIST IS {}",x.ulps(&y));
    assert!(x.ulps(&y) == 3);
}

#[test]
fn f64_ulps_test5() {
    let x: f64 = 2.0;
    let ulps: i64 = unsafe { mem::transmute(x) };
    let x2: f64 = unsafe { mem::transmute(ulps) };
    assert_eq!(x, x2);
}
<commit_msg>Ulps:  next() and prev() functions<commit_after>// Copyright 2014-2018 Optimal Computing (NZ) Ltd.
// Licensed under the MIT license.  See LICENSE for details.

use std::mem;
use num_traits::NumCast;

/// A trait for floating point numbers which computes the number of representable
/// values or ULPs (Units of Least Precision) that separate the two given values.
pub trait Ulps {
    type U: Copy + NumCast;

    /// The number of representable values or ULPs (Units of Least Precision) that
    /// separate `self` and `other`.  The result `U` is an integral value, and will
    /// be zero if `self` and `other` are exactly equal.
    fn ulps(&self, other: &Self) -> <Self as Ulps>::U;

    /// The next representable number above this one
    fn next(&self) -> Self;

    /// The previous representable number below this one
    fn prev(&self) -> Self;
}

impl Ulps for f32 {
    type U = i32;

    fn ulps(&self, other: &f32) -> i32 {

        // IEEE754 defined floating point storage representation to
        // maintain their order when their bit patterns are interpreted as
        // integers.  This is a huge boon to the task at hand, as we can
        // (unsafely) cast to integers to find out how many ULPs apart any
        // two floats are

        // Setup integer representations of the input
        let ai32: i32 = unsafe { mem::transmute::<f32,i32>(*self) };
        let bi32: i32 = unsafe { mem::transmute::<f32,i32>(*other) };

        ai32.wrapping_sub(bi32)
    }

    fn next(&self) -> Self {
        if self.is_infinite() && *self > 0.0 {
            *self
        } else if *self == -0.0 && self.is_sign_negative() {
            0.0
        } else {
            let mut u = self.to_bits();
            if *self >= 0.0 {
                u += 1;
            } else {
                u -= 1;
            }
            f32::from_bits(u)
        }
    }

    fn prev(&self) -> Self {
        if self.is_infinite() && *self < 0.0 {
            *self
        } else if *self == 0.0 && self.is_sign_positive() {
            -0.0
        } else {
            let mut u = self.to_bits();
            if *self <= -0.0 {
                u += 1;
            } else {
                u -= 1;
            }
            f32::from_bits(u)
        }
    }
}

#[test]
fn f32_ulps_test1() {
    let x: f32 = 1000000_f32;
    let y: f32 = 1000000.1_f32;
    println!("DIST IS {}",x.ulps(&y));
    assert!(x.ulps(&y) == -2);
}

#[test]
fn f32_ulps_test2() {
    let pzero: f32 = f32::from_bits(0x00000000_u32);
    let nzero: f32 = f32::from_bits(0x80000000_u32);
    println!("DIST IS {}",pzero.ulps(&nzero));
    assert!(pzero.ulps(&nzero) == -2147483648);
}
#[test]
fn f32_ulps_test3() {
    let pinf: f32 = f32::from_bits(0x7f800000_u32);
    let ninf: f32 = f32::from_bits(0xff800000_u32);
    println!("DIST IS {}",pinf.ulps(&ninf));
    assert!(pinf.ulps(&ninf) == -2147483648);
}

#[test]
fn f32_ulps_test4() {
    let x: f32 = f32::from_bits(0x63a7f026_u32);
    let y: f32 = f32::from_bits(0x63a7f023_u32);
    println!("DIST IS {}",x.ulps(&y));
    assert!(x.ulps(&y) == 3);
}

#[test]
fn f32_ulps_test5() {
    let x: f32 = 2.0;
    let ulps: i32 = unsafe { mem::transmute(x) };
    let x2: f32 = unsafe { mem::transmute(ulps) };
    assert_eq!(x, x2);
}

#[test]
fn f32_ulps_test6() {
    let negzero: f32 = -0.;
    let zero: f32 = 0.;
    assert_eq!(negzero.next(), zero);
    assert_eq!(zero.prev(), negzero);
    assert!(negzero.prev() < 0.0);
    assert!(zero.next() > 0.0);
}

impl Ulps for f64 {
    type U = i64;

    fn ulps(&self, other: &f64) -> i64 {

        // IEEE754 defined floating point storage representation to
        // maintain their order when their bit patterns are interpreted as
        // integers.  This is a huge boon to the task at hand, as we can
        // (unsafely) cast to integers to find out how many ULPs apart any
        // two floats are

        // Setup integer representations of the input
        let ai64: i64 = unsafe { mem::transmute::<f64,i64>(*self) };
        let bi64: i64 = unsafe { mem::transmute::<f64,i64>(*other) };

        ai64.wrapping_sub(bi64)
    }

    fn next(&self) -> Self {
        if self.is_infinite() && *self > 0.0 {
            *self
        } else if *self == -0.0 && self.is_sign_negative() {
            0.0
        } else {
            let mut u = self.to_bits();
            if *self >= 0.0 {
                u += 1;
            } else {
                u -= 1;
            }
            f64::from_bits(u)
        }
    }

    fn prev(&self) -> Self {
        if self.is_infinite() && *self < 0.0 {
            *self
        } else if *self == 0.0 && self.is_sign_positive() {
            -0.0
        } else {
            let mut u = self.to_bits();
            if *self <= -0.0 {
                u += 1;
            } else {
                u -= 1;
            }
            f64::from_bits(u)
        }
    }
}

#[test]
fn f64_ulps_test1() {
    let x: f64 = 1000000_f64;
    let y: f64 = 1000000.00000001_f64;
    println!("DIST IS {}",x.ulps(&y));
    assert!(x.ulps(&y) == -86);
}

#[test]
fn f64_ulps_test2() {
    let pzero: f64 = f64::from_bits(0x0000000000000000_u64);
    let nzero: f64 = f64::from_bits(0x8000000000000000_u64);
    println!("DIST IS {}",pzero.ulps(&nzero));
    assert!(pzero.ulps(&nzero) == -9223372036854775808i64);
}
#[test]
fn f64_ulps_test3() {
    let pinf: f64 = f64::from_bits(0x7f80000000000000_u64);
    let ninf: f64 = f64::from_bits(0xff80000000000000_u64);
    println!("DIST IS {}",pinf.ulps(&ninf));
    assert!(pinf.ulps(&ninf) == -9223372036854775808i64);
}

#[test]
fn f64_ulps_test4() {
    let x: f64 = f64::from_bits(0xd017f6cc63a7f026_u64);
    let y: f64 = f64::from_bits(0xd017f6cc63a7f023_u64);
    println!("DIST IS {}",x.ulps(&y));
    assert!(x.ulps(&y) == 3);
}

#[test]
fn f64_ulps_test5() {
    let x: f64 = 2.0;
    let ulps: i64 = unsafe { mem::transmute(x) };
    let x2: f64 = unsafe { mem::transmute(ulps) };
    assert_eq!(x, x2);
}

#[test]
fn f64_ulps_test6() {
    let negzero: f64 = -0.;
    let zero: f64 = 0.;
    assert_eq!(negzero.next(), zero);
    assert_eq!(zero.prev(), negzero);
    assert!(negzero.prev() < 0.0);
    assert!(zero.next() > 0.0);
}

<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::fs;
use std::path::{Path, PathBuf};
use std::str;

use csv;
use docopt::Docopt;
use rustc_serialize::Decodable;

use CliResult;
use config::{Config, Delimiter};

pub fn num_cpus() -> usize {
    unsafe {
        return rust_get_num_cpus() as usize;
    }

    extern {
        fn rust_get_num_cpus() -> ::libc::uintptr_t;
    }
}

pub fn version() -> String {
    let (maj, min, pat) = (
        option_env!("CARGO_PKG_VERSION_MAJOR"),
        option_env!("CARGO_PKG_VERSION_MINOR"),
        option_env!("CARGO_PKG_VERSION_PATCH"),
    );
    match (maj, min, pat) {
        (Some(maj), Some(min), Some(pat)) =>
            format!("{}.{}.{}", maj, min, pat),
        _ => "".to_string(),
    }
}

pub fn get_args<T>(usage: &str, argv: &[&str]) -> CliResult<T>
        where T: Decodable {
    Docopt::new(usage)
           .and_then(|d| d.argv(argv.iter().map(|&x| x))
                          .version(Some(version()))
                          .decode())
           .map_err(From::from)
}

pub fn many_configs(inps: &[String], delim: Option<Delimiter>,
                    no_headers: bool) -> Result<Vec<Config>, String> {
    let mut inps = inps.to_vec();
    if inps.is_empty() {
        inps.push("-".to_string()); // stdin
    }
    let confs = inps.into_iter()
                    .map(|p| Config::new(&Some(p))
                                    .delimiter(delim)
                                    .no_headers(no_headers))
                    .collect::<Vec<_>>();
    try!(errif_greater_one_stdin(&*confs));
    Ok(confs)
}

pub fn errif_greater_one_stdin(inps: &[Config]) -> Result<(), String> {
    let nstd = inps.iter().filter(|inp| inp.is_std()).count();
    if nstd > 1 {
        return Err("At most one <stdin> input is allowed.".to_string());
    }
    Ok(())
}

pub fn empty_field() -> csv::ByteString { vec![] }

pub fn chunk_size(nitems: usize, njobs: usize) -> usize {
    if nitems < njobs {
        nitems
    } else {
        nitems / njobs
    }
}

pub fn num_of_chunks(nitems: usize, chunk_size: usize) -> usize {
    if chunk_size == 0 {
        return nitems;
    }
    let mut n = nitems / chunk_size;
    if nitems % chunk_size != 0 {
        n += 1;
    }
    n
}

pub fn last_modified(md: &fs::Metadata) -> u64 {
    use filetime::FileTime;
    FileTime::from_last_modification_time(md).seconds_relative_to_1970()
}

pub fn condense<'a>(val: Cow<'a, [u8]>, n: Option<usize>) -> Cow<'a, [u8]> {
    match n {
        None => val,
        Some(n) => {
            // It would be much nicer to just use a `match` here, but the
            // borrow checker won't allow it. ---AG
            //
            // (We could circumvent it by allocating a new Unicode string,
            // but that seems excessive.)
            let mut is_short_utf8 = false;
            if let Ok(s) = str::from_utf8(&*val) {
                if n >= s.chars().count() {
                    is_short_utf8 = true;
                } else {
                    let mut s = s.chars().take(n).collect::<String>();
                    s.push_str("...");
                    return Cow::Owned(s.into_bytes());
                }
            }
            if is_short_utf8 || n >= (*val).len() { // already short enough
                val
            } else {
                // This is a non-Unicode string, so we just trim on bytes.
                let mut s = val[0..n].to_vec();
                s.extend(b"...".iter().cloned());
                Cow::Owned(s)
            }
        }
    }
}

pub fn idx_path(csv_path: &Path) -> PathBuf {
    let mut p = csv_path.to_path_buf().into_os_string().into_string().unwrap();
    p.push_str(".idx");
    PathBuf::from(&p)
}

pub type Idx = Option<usize>;

pub fn range(start: Idx, end: Idx, len: Idx, index: Idx)
            -> Result<(usize, usize), String> {
    match (start, end, len, index) {
        (None, None, None, Some(i)) => return Ok((i, i+1)),
        (_, _, _, Some(_)) => {
            return Err("--index cannot be used with \
                        --start, --end or --len".to_string());
        }
        (_, _, _, Some(i)) => return Ok((i, i+1)),
        (_, Some(_), Some(_), None) => {
            return Err("--end and --len cannot be used
                        at the same time.".to_string());
        }
        (_, None, None, None) => return Ok((start.unwrap_or(0), ::std::usize::MAX)),
        (_, Some(e), None, None) => {
            let s = start.unwrap_or(0);
            if s > e {
                return Err(format!(
                    "The end of the range ({}) must be greater than or\n\
                     equal to the start of the range ({}).", e, s));
            } else {
                return Ok((start.unwrap_or(0), e));
            }
        }
        (_, None, Some(l), None) => {
            let s = start.unwrap_or(0);
            return Ok((s, s + l));
        }
    }
}
<commit_msg>remove unreachable branch<commit_after>use std::borrow::Cow;
use std::fs;
use std::path::{Path, PathBuf};
use std::str;

use csv;
use docopt::Docopt;
use rustc_serialize::Decodable;

use CliResult;
use config::{Config, Delimiter};

pub fn num_cpus() -> usize {
    unsafe {
        return rust_get_num_cpus() as usize;
    }

    extern {
        fn rust_get_num_cpus() -> ::libc::uintptr_t;
    }
}

pub fn version() -> String {
    let (maj, min, pat) = (
        option_env!("CARGO_PKG_VERSION_MAJOR"),
        option_env!("CARGO_PKG_VERSION_MINOR"),
        option_env!("CARGO_PKG_VERSION_PATCH"),
    );
    match (maj, min, pat) {
        (Some(maj), Some(min), Some(pat)) =>
            format!("{}.{}.{}", maj, min, pat),
        _ => "".to_string(),
    }
}

pub fn get_args<T>(usage: &str, argv: &[&str]) -> CliResult<T>
        where T: Decodable {
    Docopt::new(usage)
           .and_then(|d| d.argv(argv.iter().map(|&x| x))
                          .version(Some(version()))
                          .decode())
           .map_err(From::from)
}

pub fn many_configs(inps: &[String], delim: Option<Delimiter>,
                    no_headers: bool) -> Result<Vec<Config>, String> {
    let mut inps = inps.to_vec();
    if inps.is_empty() {
        inps.push("-".to_string()); // stdin
    }
    let confs = inps.into_iter()
                    .map(|p| Config::new(&Some(p))
                                    .delimiter(delim)
                                    .no_headers(no_headers))
                    .collect::<Vec<_>>();
    try!(errif_greater_one_stdin(&*confs));
    Ok(confs)
}

pub fn errif_greater_one_stdin(inps: &[Config]) -> Result<(), String> {
    let nstd = inps.iter().filter(|inp| inp.is_std()).count();
    if nstd > 1 {
        return Err("At most one <stdin> input is allowed.".to_string());
    }
    Ok(())
}

pub fn empty_field() -> csv::ByteString { vec![] }

pub fn chunk_size(nitems: usize, njobs: usize) -> usize {
    if nitems < njobs {
        nitems
    } else {
        nitems / njobs
    }
}

pub fn num_of_chunks(nitems: usize, chunk_size: usize) -> usize {
    if chunk_size == 0 {
        return nitems;
    }
    let mut n = nitems / chunk_size;
    if nitems % chunk_size != 0 {
        n += 1;
    }
    n
}

pub fn last_modified(md: &fs::Metadata) -> u64 {
    use filetime::FileTime;
    FileTime::from_last_modification_time(md).seconds_relative_to_1970()
}

pub fn condense<'a>(val: Cow<'a, [u8]>, n: Option<usize>) -> Cow<'a, [u8]> {
    match n {
        None => val,
        Some(n) => {
            // It would be much nicer to just use a `match` here, but the
            // borrow checker won't allow it. ---AG
            //
            // (We could circumvent it by allocating a new Unicode string,
            // but that seems excessive.)
            let mut is_short_utf8 = false;
            if let Ok(s) = str::from_utf8(&*val) {
                if n >= s.chars().count() {
                    is_short_utf8 = true;
                } else {
                    let mut s = s.chars().take(n).collect::<String>();
                    s.push_str("...");
                    return Cow::Owned(s.into_bytes());
                }
            }
            if is_short_utf8 || n >= (*val).len() { // already short enough
                val
            } else {
                // This is a non-Unicode string, so we just trim on bytes.
                let mut s = val[0..n].to_vec();
                s.extend(b"...".iter().cloned());
                Cow::Owned(s)
            }
        }
    }
}

pub fn idx_path(csv_path: &Path) -> PathBuf {
    let mut p = csv_path.to_path_buf().into_os_string().into_string().unwrap();
    p.push_str(".idx");
    PathBuf::from(&p)
}

pub type Idx = Option<usize>;

pub fn range(start: Idx, end: Idx, len: Idx, index: Idx)
            -> Result<(usize, usize), String> {
    match (start, end, len, index) {
        (None, None, None, Some(i)) => return Ok((i, i+1)),
        (_, _, _, Some(_)) => {
            return Err("--index cannot be used with \
                        --start, --end or --len".to_string());
        }
        (_, Some(_), Some(_), None) => {
            return Err("--end and --len cannot be used
                        at the same time.".to_string());
        }
        (_, None, None, None) => return Ok((start.unwrap_or(0), ::std::usize::MAX)),
        (_, Some(e), None, None) => {
            let s = start.unwrap_or(0);
            if s > e {
                return Err(format!(
                    "The end of the range ({}) must be greater than or\n\
                     equal to the start of the range ({}).", e, s));
            } else {
                return Ok((start.unwrap_or(0), e));
            }
        }
        (_, None, Some(l), None) => {
            let s = start.unwrap_or(0);
            return Ok((s, s + l));
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Display, Formatter};
use std::future::Future;
use std::mem;
use std::pin::Pin;
use std::task::{Context, Poll};

use bytes::{Bytes, BytesMut};
use cfg_if::cfg_if;
use futures_core::{Stream, TryFuture, TryStream};
use futures_util::future::FutureExt;
use futures_util::ready;
use futures_util::stream::{Fuse, StreamExt};
use futures_util::try_future::TryFutureExt;
use futures_util::try_stream::{IntoStream, TryStreamExt};

use crate::error::{Error, HyperError};

macro_rules! ready_some {
    ($e:expr) => {
        match $e {
            std::task::Poll::Ready(Some(t)) => t,
            std::task::Poll::Ready(None) => return std::task::Poll::Ready(None),
            std::task::Poll::Pending => return std::task::Poll::Pending,
        }
    };
}

// Synonym of `twitter_stream_message::util::string_enums`
macro_rules! string_enums {
    (
        $(
            $(#[$attr:meta])*
            pub enum $E:ident {
                $(
                    $(#[$v_attr:meta])*
                    $V:ident($by:expr)
                ),*;
                $(#[$u_attr:meta])*
                $U:ident(_),
            }
        )*
    ) => {
        $(
            $(#[$attr])*
            pub enum $E {
                $(
                    $(#[$v_attr])*
                    $V,
                )*
                $(#[$u_attr])*
                $U(String),
            }

            impl std::convert::AsRef<str> for $E {
                fn as_ref(&self) -> &str {
                    match *self {
                        $($E::$V => $by,)*
                        $E::$U(ref s) => s,
                    }
                }
            }

            impl std::fmt::Display for $E {
                fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                    AsRef::<str>::as_ref(self).fmt(f)
                }
            }

            impl std::cmp::PartialEq for $E {
                fn eq(&self, other: &$E) -> bool {
                    match *self {
                        $($E::$V => match *other {
                            $E::$V => true,
                            $E::$U(ref s) if $by == s => true,
                            _ => false,
                        },)*
                        $E::$U(ref s) => match *other {
                            $($E::$V => $by == s,)*
                            $E::$U(ref t) => s == t,
                        },
                    }
                }
            }

            impl std::hash::Hash for $E {
                fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
                    match *self {
                        $($E::$V => $by.hash(state),)*
                        $E::$U(ref s) => s.hash(state),
                    }
                }
            }

            impl std::cmp::Eq for $E {}
        )*
    }
}

pub struct Lines<S> {
    stream: Fuse<IntoStream<S>>,
    buf: BytesMut,
}

/// Wrapper to map `T::Error` onto `Error`.
pub struct MapErr<T>(T);

pub trait IntoError {
    fn into_error(self) -> Error;
}

impl<S: TryStream> Lines<S> {
    pub fn new(stream: S) -> Self {
        Lines {
            stream: stream.into_stream().fuse(),
            buf: BytesMut::new(),
        }
    }
}

impl<S: TryStream<Error = Error> + Unpin> Stream for Lines<S>
where
    S::Ok: Into<Bytes>,
{
    type Item = Result<Bytes, Error>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        if let Some(line) = remove_first_line(&mut self.buf) {
            return Poll::Ready(Some(Ok(line.freeze())));
        }

        // Now `self.buf` does not have a CRLF.
        // Extend the buffer until a CRLF is found.

        loop {
            let mut chunk: BytesMut = loop {
                if let Some(c) = ready!(self.stream.poll_next_unpin(cx)) {
                    let c: Bytes = c?.into();
                    if !c.is_empty() {
                        break c.into();
                    }
                } else if !self.buf.is_empty() {
                    let ret = mem::replace(&mut self.buf, BytesMut::new()).freeze();
                    return Poll::Ready(Some(Ok(ret)));
                } else {
                    return Poll::Ready(None);
                }
            };

            if chunk[0] == b'\n' && self.buf.last() == Some(&b'\r') {
                // Drop the CRLF
                chunk.advance(1);
                let line_len = self.buf.len() - 1;
                self.buf.truncate(line_len);
                return Poll::Ready(Some(Ok(mem::replace(&mut self.buf, chunk).freeze())));
            } else if let Some(line) = remove_first_line(&mut chunk) {
                self.buf.unsplit(line);
                return Poll::Ready(Some(Ok(mem::replace(&mut self.buf, chunk).freeze())));
            } else {
                self.buf.unsplit(chunk);
            }
        }
    }
}

impl<F: TryFuture + Unpin> Future for MapErr<F>
where
    F::Error: IntoError,
{
    type Output = Result<F::Ok, Error>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        self.0.try_poll_unpin(cx).map_err(IntoError::into_error)
    }
}

impl<S: TryStream + Unpin> Stream for MapErr<S>
where
    S::Error: IntoError,
{
    type Item = Result<S::Ok, Error>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.0
            .try_poll_next_unpin(cx)
            .map(|opt| opt.map(|result| result.map_err(IntoError::into_error)))
    }
}

impl IntoError for Error {
    fn into_error(self) -> Error {
        self
    }
}

impl IntoError for HyperError {
    fn into_error(self) -> Error {
        Error::Hyper(self)
    }
}

pub fn fmt_join<T: Display>(t: &[T], sep: &str, f: &mut Formatter<'_>) -> fmt::Result {
    let mut iter = t.iter();
    if let Some(t) = iter.next() {
        Display::fmt(t, f)?;
        for t in iter {
            write!(f, "{}{}", sep, t)?;
        }
    }
    Ok(())
}

const COMMA: &str = "%2C";

pub fn fmt_follow(ids: &[u64], f: &mut Formatter<'_>) -> fmt::Result {
    fmt_join(ids, COMMA, f)
}

type Location = ((f64, f64), (f64, f64));

pub fn fmt_locations(locs: &[Location], f: &mut Formatter<'_>) -> fmt::Result {
    use std::mem::size_of;
    use std::slice;

    use static_assertions::const_assert;

    let locs: &[f64] = unsafe {
        let ptr: *const Location = locs.as_ptr();
        const_assert!(size_of::<Location>() % size_of::<f64>() == 0);
        let n = locs.len() * (size_of::<Location>() / size_of::<f64>());
        slice::from_raw_parts(ptr as *const f64, n)
    };

    fmt_join(locs, COMMA, f)
}

#[allow(clippy::trivially_copy_pass_by_ref)]
pub fn not(p: &bool) -> bool {
    !p
}

fn remove_first_line(buf: &mut BytesMut) -> Option<BytesMut> {
    if buf.len() < 2 {
        return None;
    }

    if let Some(i) = memchr::memchr(b'\n', &buf[1..]) {
        if buf[i] == b'\r' {
            let mut line = buf.split_to(i + 2);
            line.split_off(i); // Drop the CRLF
            return Some(line);
        }
    }

    None
}

cfg_if! {
    if #[cfg(feature = "runtime")] {
        use std::time::Duration;

        use futures_util::future::{self, Either};
        use futures_util::try_future::IntoFuture;

        pub struct Flatten<S>(IntoStream<S>);

        /// A `tokio_timer::Timeout`-like type that holds the original `Duration`
        /// which can be used to create another `Timeout`.
        pub struct Timeout<F> {
            tokio: tokio_timer::Timeout<IntoFuture<F>>,
            dur: Duration,
        }

        pub type MaybeTimeout<F> = Either<Timeout<F>, MapErr<F>>;

        pub type MaybeTimeoutStream<S> = Either<
            Flatten<tokio_timer::Timeout<IntoStream<S>>>, MapErr<S>,
        >;

        impl<S: TryStream> Flatten<S> {
            pub fn new(s: S) -> Self {
                Flatten(s.into_stream())
            }
        }

        impl<S: TryStream<Ok = Result<T, E>> + Unpin, T, E> Stream for Flatten<S>
        where
            S::Error: IntoError,
            E: IntoError,
        {
            type Item = Result<T, Error>;

            fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
                (&mut self.0)
                    .map_err(IntoError::into_error)
                    .and_then(|r| future::ready(r.map_err(IntoError::into_error)))
                    .poll_next_unpin(cx)
            }
        }

        impl<F: TryFuture> Timeout<F> {
            pub fn new(fut: F, dur: Duration) -> Self {
                Timeout {
                    tokio: tokio_timer::Timeout::new(fut.into_future(), dur),
                    dur,
                }
            }
        }

        impl<F: TryFuture + Unpin> Future for Timeout<F>
        where
            F::Error: IntoError,
        {
            type Output = Result<F::Ok, Error>;

            fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
                (&mut self.tokio)
                    .map_err(IntoError::into_error)
                    .and_then(|r| future::ready(r.map_err(IntoError::into_error)))
                    .poll_unpin(cx)
            }
        }

        impl IntoError for tokio_timer::timeout::Elapsed {
            fn into_error(self) -> Error {
                Error::TimedOut
            }
        }

        pub fn timeout<F: TryFuture>(fut: F, dur: Option<Duration>) -> MaybeTimeout<F> {
            match dur {
                Some(dur) => Either::Left(Timeout::new(fut, dur)),
                None => Either::Right(MapErr(fut)),
            }
        }

        pub fn timeout_to_stream<F, S>(timeout: &MaybeTimeout<F>, s: S) -> MaybeTimeoutStream<S>
        where
            S: TryStream,
        {
            match *timeout {
                Either::Left(ref t) => {
                    let timeout = tokio_timer::Timeout::new(s.into_stream(), t.dur);
                    Either::Left(Flatten::new(timeout))
                }
                Either::Right(_) => Either::Right(MapErr(s)),
            }
        }
    } else {
        pub type MaybeTimeout<F> = MapErr<F>;

        pub type MaybeTimeoutStream<S> = MapErr<S>;

        pub fn timeout<F: TryFuture>(fut: F) -> MaybeTimeout<F> {
            MapErr(fut)
        }

        pub fn timeout_to_stream<F, S>(_: &MaybeTimeout<F>, s: S) -> MaybeTimeoutStream<S>
        where
            S: TryStream,
        {
            MapErr(s)
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use bytes::Bytes;
    use futures_executor::block_on_stream;
    use futures_util::stream;

    #[test]
    fn lines() {
        let body = [
            "abc\r\n",
            "d\r\nefg\r\n",
            "hi",
            "jk",
            "",
            "\r\n",
            "\r\n",
            "lmn\r\nop",
            "q\rrs\r",
            "\n\n\rtuv\r\r\n",
            "wxyz\n",
        ];

        let concat = body.concat();
        let expected = concat.split("\r\n");
        let lines = Lines::new(stream::iter(&body).map(|&c| Ok(Bytes::from_static(c.as_bytes()))));
        let lines = block_on_stream(lines).map(|s| String::from_utf8(s.unwrap().to_vec()).unwrap());

        assert_eq!(lines.collect::<Vec<_>>(), expected.collect::<Vec<_>>());
    }
}
<commit_msg>Fix an `unused_imports` warning when compiling with `--no-default-features`<commit_after>use std::fmt::{self, Display, Formatter};
use std::future::Future;
use std::mem;
use std::pin::Pin;
use std::task::{Context, Poll};

use bytes::{Bytes, BytesMut};
use cfg_if::cfg_if;
use futures_core::{Stream, TryFuture, TryStream};
use futures_util::ready;
use futures_util::stream::{Fuse, StreamExt};
use futures_util::try_future::TryFutureExt;
use futures_util::try_stream::{IntoStream, TryStreamExt};

use crate::error::{Error, HyperError};

macro_rules! ready_some {
    ($e:expr) => {
        match $e {
            std::task::Poll::Ready(Some(t)) => t,
            std::task::Poll::Ready(None) => return std::task::Poll::Ready(None),
            std::task::Poll::Pending => return std::task::Poll::Pending,
        }
    };
}

// Synonym of `twitter_stream_message::util::string_enums`
macro_rules! string_enums {
    (
        $(
            $(#[$attr:meta])*
            pub enum $E:ident {
                $(
                    $(#[$v_attr:meta])*
                    $V:ident($by:expr)
                ),*;
                $(#[$u_attr:meta])*
                $U:ident(_),
            }
        )*
    ) => {
        $(
            $(#[$attr])*
            pub enum $E {
                $(
                    $(#[$v_attr])*
                    $V,
                )*
                $(#[$u_attr])*
                $U(String),
            }

            impl std::convert::AsRef<str> for $E {
                fn as_ref(&self) -> &str {
                    match *self {
                        $($E::$V => $by,)*
                        $E::$U(ref s) => s,
                    }
                }
            }

            impl std::fmt::Display for $E {
                fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
                    AsRef::<str>::as_ref(self).fmt(f)
                }
            }

            impl std::cmp::PartialEq for $E {
                fn eq(&self, other: &$E) -> bool {
                    match *self {
                        $($E::$V => match *other {
                            $E::$V => true,
                            $E::$U(ref s) if $by == s => true,
                            _ => false,
                        },)*
                        $E::$U(ref s) => match *other {
                            $($E::$V => $by == s,)*
                            $E::$U(ref t) => s == t,
                        },
                    }
                }
            }

            impl std::hash::Hash for $E {
                fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
                    match *self {
                        $($E::$V => $by.hash(state),)*
                        $E::$U(ref s) => s.hash(state),
                    }
                }
            }

            impl std::cmp::Eq for $E {}
        )*
    }
}

pub struct Lines<S> {
    stream: Fuse<IntoStream<S>>,
    buf: BytesMut,
}

/// Wrapper to map `T::Error` onto `Error`.
pub struct MapErr<T>(T);

pub trait IntoError {
    fn into_error(self) -> Error;
}

impl<S: TryStream> Lines<S> {
    pub fn new(stream: S) -> Self {
        Lines {
            stream: stream.into_stream().fuse(),
            buf: BytesMut::new(),
        }
    }
}

impl<S: TryStream<Error = Error> + Unpin> Stream for Lines<S>
where
    S::Ok: Into<Bytes>,
{
    type Item = Result<Bytes, Error>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        if let Some(line) = remove_first_line(&mut self.buf) {
            return Poll::Ready(Some(Ok(line.freeze())));
        }

        // Now `self.buf` does not have a CRLF.
        // Extend the buffer until a CRLF is found.

        loop {
            let mut chunk: BytesMut = loop {
                if let Some(c) = ready!(self.stream.poll_next_unpin(cx)) {
                    let c: Bytes = c?.into();
                    if !c.is_empty() {
                        break c.into();
                    }
                } else if !self.buf.is_empty() {
                    let ret = mem::replace(&mut self.buf, BytesMut::new()).freeze();
                    return Poll::Ready(Some(Ok(ret)));
                } else {
                    return Poll::Ready(None);
                }
            };

            if chunk[0] == b'\n' && self.buf.last() == Some(&b'\r') {
                // Drop the CRLF
                chunk.advance(1);
                let line_len = self.buf.len() - 1;
                self.buf.truncate(line_len);
                return Poll::Ready(Some(Ok(mem::replace(&mut self.buf, chunk).freeze())));
            } else if let Some(line) = remove_first_line(&mut chunk) {
                self.buf.unsplit(line);
                return Poll::Ready(Some(Ok(mem::replace(&mut self.buf, chunk).freeze())));
            } else {
                self.buf.unsplit(chunk);
            }
        }
    }
}

impl<F: TryFuture + Unpin> Future for MapErr<F>
where
    F::Error: IntoError,
{
    type Output = Result<F::Ok, Error>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        self.0.try_poll_unpin(cx).map_err(IntoError::into_error)
    }
}

impl<S: TryStream + Unpin> Stream for MapErr<S>
where
    S::Error: IntoError,
{
    type Item = Result<S::Ok, Error>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.0
            .try_poll_next_unpin(cx)
            .map(|opt| opt.map(|result| result.map_err(IntoError::into_error)))
    }
}

impl IntoError for Error {
    fn into_error(self) -> Error {
        self
    }
}

impl IntoError for HyperError {
    fn into_error(self) -> Error {
        Error::Hyper(self)
    }
}

pub fn fmt_join<T: Display>(t: &[T], sep: &str, f: &mut Formatter<'_>) -> fmt::Result {
    let mut iter = t.iter();
    if let Some(t) = iter.next() {
        Display::fmt(t, f)?;
        for t in iter {
            write!(f, "{}{}", sep, t)?;
        }
    }
    Ok(())
}

const COMMA: &str = "%2C";

pub fn fmt_follow(ids: &[u64], f: &mut Formatter<'_>) -> fmt::Result {
    fmt_join(ids, COMMA, f)
}

type Location = ((f64, f64), (f64, f64));

pub fn fmt_locations(locs: &[Location], f: &mut Formatter<'_>) -> fmt::Result {
    use std::mem::size_of;
    use std::slice;

    use static_assertions::const_assert;

    let locs: &[f64] = unsafe {
        let ptr: *const Location = locs.as_ptr();
        const_assert!(size_of::<Location>() % size_of::<f64>() == 0);
        let n = locs.len() * (size_of::<Location>() / size_of::<f64>());
        slice::from_raw_parts(ptr as *const f64, n)
    };

    fmt_join(locs, COMMA, f)
}

#[allow(clippy::trivially_copy_pass_by_ref)]
pub fn not(p: &bool) -> bool {
    !p
}

fn remove_first_line(buf: &mut BytesMut) -> Option<BytesMut> {
    if buf.len() < 2 {
        return None;
    }

    if let Some(i) = memchr::memchr(b'\n', &buf[1..]) {
        if buf[i] == b'\r' {
            let mut line = buf.split_to(i + 2);
            line.split_off(i); // Drop the CRLF
            return Some(line);
        }
    }

    None
}

cfg_if! {
    if #[cfg(feature = "runtime")] {
        use std::time::Duration;

        use futures_util::future::{self, Either, FutureExt};
        use futures_util::try_future::IntoFuture;

        pub struct Flatten<S>(IntoStream<S>);

        /// A `tokio_timer::Timeout`-like type that holds the original `Duration`
        /// which can be used to create another `Timeout`.
        pub struct Timeout<F> {
            tokio: tokio_timer::Timeout<IntoFuture<F>>,
            dur: Duration,
        }

        pub type MaybeTimeout<F> = Either<Timeout<F>, MapErr<F>>;

        pub type MaybeTimeoutStream<S> = Either<
            Flatten<tokio_timer::Timeout<IntoStream<S>>>, MapErr<S>,
        >;

        impl<S: TryStream> Flatten<S> {
            pub fn new(s: S) -> Self {
                Flatten(s.into_stream())
            }
        }

        impl<S: TryStream<Ok = Result<T, E>> + Unpin, T, E> Stream for Flatten<S>
        where
            S::Error: IntoError,
            E: IntoError,
        {
            type Item = Result<T, Error>;

            fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
                (&mut self.0)
                    .map_err(IntoError::into_error)
                    .and_then(|r| future::ready(r.map_err(IntoError::into_error)))
                    .poll_next_unpin(cx)
            }
        }

        impl<F: TryFuture> Timeout<F> {
            pub fn new(fut: F, dur: Duration) -> Self {
                Timeout {
                    tokio: tokio_timer::Timeout::new(fut.into_future(), dur),
                    dur,
                }
            }
        }

        impl<F: TryFuture + Unpin> Future for Timeout<F>
        where
            F::Error: IntoError,
        {
            type Output = Result<F::Ok, Error>;

            fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
                (&mut self.tokio)
                    .map_err(IntoError::into_error)
                    .and_then(|r| future::ready(r.map_err(IntoError::into_error)))
                    .poll_unpin(cx)
            }
        }

        impl IntoError for tokio_timer::timeout::Elapsed {
            fn into_error(self) -> Error {
                Error::TimedOut
            }
        }

        pub fn timeout<F: TryFuture>(fut: F, dur: Option<Duration>) -> MaybeTimeout<F> {
            match dur {
                Some(dur) => Either::Left(Timeout::new(fut, dur)),
                None => Either::Right(MapErr(fut)),
            }
        }

        pub fn timeout_to_stream<F, S>(timeout: &MaybeTimeout<F>, s: S) -> MaybeTimeoutStream<S>
        where
            S: TryStream,
        {
            match *timeout {
                Either::Left(ref t) => {
                    let timeout = tokio_timer::Timeout::new(s.into_stream(), t.dur);
                    Either::Left(Flatten::new(timeout))
                }
                Either::Right(_) => Either::Right(MapErr(s)),
            }
        }
    } else {
        pub type MaybeTimeout<F> = MapErr<F>;

        pub type MaybeTimeoutStream<S> = MapErr<S>;

        pub fn timeout<F: TryFuture>(fut: F) -> MaybeTimeout<F> {
            MapErr(fut)
        }

        pub fn timeout_to_stream<F, S>(_: &MaybeTimeout<F>, s: S) -> MaybeTimeoutStream<S>
        where
            S: TryStream,
        {
            MapErr(s)
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use bytes::Bytes;
    use futures_executor::block_on_stream;
    use futures_util::stream;

    #[test]
    fn lines() {
        let body = [
            "abc\r\n",
            "d\r\nefg\r\n",
            "hi",
            "jk",
            "",
            "\r\n",
            "\r\n",
            "lmn\r\nop",
            "q\rrs\r",
            "\n\n\rtuv\r\r\n",
            "wxyz\n",
        ];

        let concat = body.concat();
        let expected = concat.split("\r\n");
        let lines = Lines::new(stream::iter(&body).map(|&c| Ok(Bytes::from_static(c.as_bytes()))));
        let lines = block_on_stream(lines).map(|s| String::from_utf8(s.unwrap().to_vec()).unwrap());

        assert_eq!(lines.collect::<Vec<_>>(), expected.collect::<Vec<_>>());
    }
}
<|endoftext|>