<commit_before>/*
 * Interpreter for Basic C like language
 * Lexer Module
 */

#[derive(Debug, Clone, PartialEq)]
pub enum TokenType {
    Keyword(String),    // like int, string or let
    Identifier(String), // like variable names
    Char(String),       // Char variables, inside " ' "
    String(String),     // String variables, inside quotes
    Number(String),     // Number variable
    True,               // Boolean true
    False,              // Boolean false
    Equals,             // =
    Plus,               // +
    Minus,              // -
    Multiple,           // *
    Divide,             // /
    Mod,                // %
    Greater,            // >
    Lesser,             // <
    GreaterEqual,       // >=
    LesserEqual,        // <=
    LParen,             // (
    RParen,             // )
    LBrace,             // {
    RBrace,             // }
    LBracket,           // [
    RBracket,           // ]
    Comma,              // ,
    Semicolon,          // ;
    Comment,            // '//'
    EOF                 // End of File
}

impl TokenType {
    pub fn toString(&self) -> &str {
        match *self {
            TokenType::Keyword(ref x) => "Keyword",
            TokenType::Identifier(ref x) => "Identifier",
            TokenType::Char(ref x) => "Char",
            TokenType::String(ref x) => "String",
            TokenType::Number(ref x) => "Number",
            TokenType::True => "True",
            TokenType::False => "False",
            TokenType::Equals => "Equals",
            TokenType::Plus => "Plus",
            TokenType::Minus => "Minus",
            TokenType::Multiple => "Multiple",
            TokenType::Divide => "Divide",
            TokenType::Mod => "Mod",
            TokenType::Greater => "Greater",
            TokenType::Lesser => "Lesser",
            TokenType::GreaterEqual => "GreaterEqual",
            TokenType::LesserEqual => "LesserEqual",
            TokenType::LParen => "LParen",
            TokenType::RParen => "RParen",
            TokenType::LBrace => "LBrace",
            TokenType::RBrace => "RBrace",
            TokenType::LBracket => "LBracket",
            TokenType::RBracket => "RBracket",
            TokenType::Comma => "Comma",
            TokenType::Semicolon => "Semicolon",
            TokenType::Comment => "Comment",
            TokenType::EOF => "EOF"
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct Span {
    pub lo: usize,
    pub hi: usize,
}

#[derive(Debug, Clone)]
pub struct Token {
    pub tokenType: TokenType,
    pub span: Option
}

#[derive(Debug, Clone)]
pub struct TokenStream {
    pub code: String,
    pub tokens: Vec<Token>,
    pub pos: usize,
    pub curr: Option<char>
}

impl TokenStream {
    pub fn new(_code: String) -> TokenStream {
        let mut newTokenStream = TokenStream {
            code: _code,
            tokens: vec![],
            pos: 0,
            curr: None
        };

        newTokenStream.tokenize();
        newTokenStream
    }

    pub fn tokenize (&mut self) {
        let mut tokens : Vec<Token> = vec![]; // OR Vec::new();
        let charCount = self.code.chars().count();
        let mut i = 0;

        while i < charCount {
            let currentChar = self.code.chars().nth(i).unwrap();

            // If char is whitespace, just pass the current char
            if currentChar.is_whitespace() {
                i += 1;
            }
            // If char starts with alphabetic characters
            else if currentChar.is_alphabetic() {
                let mut tmp = "".to_string();

                // If current char is not out of our code scope and char starts with alphanumeric (alphabetic or numeric) characters
                while i < charCount && self.nthChar(i).is_alphanumeric() {

                    tmp = tmp + &*self.nthChar(i).to_string();
                    i += 1;
                }

                //We have the word, now we need to find what it is and tokenize it.
                let tmpStr = tmp.to_lowercase();
                if self.isKeyword(&tmpStr) {
                    tokens.push(Token { tokenType: TokenType::Keyword(tmpStr), span: None });
                } else if tmpStr == "true" {
                    tokens.push(Token {tokenType: TokenType::True, span: None });
                } else if tmpStr == "false" {
                    tokens.push(Token {tokenType: TokenType::False, span: None });
                } else {
                    tokens.push(Token {tokenType: TokenType::Identifier(tmpStr), span: None });
                }
            }
            // If current char is a numerical character
            else if currentChar.is_numeric() {
                let mut tmp = "".to_string();

                while i < charCount && self.nthChar(i).is_numeric() {
                    tmp = tmp + &*self.nthChar(i).to_string();
                    i += 1;
                }

                tokens.push(Token { tokenType: TokenType::Number(tmp), span: None });
            }
            // If current char is a starting of a string
            else if currentChar == '"' {
                let mut tmp = "".to_string();
                i += 1;

                while i < charCount && self.nthChar(i) != '"'  {
                    tmp = tmp + &*self.nthChar(i).to_string();
                    i += 1;
                }

                i += 1;
                tokens.push(Token { tokenType: TokenType::String(tmp), span: None });
            }
            // If current char is a real char
            else if currentChar == '\'' {
                let tmp = self.code.chars().nth(i + 1).unwrap();
                i += 2;

                if self.nthChar(i) == '\'' {
                    tokens.push(Token { tokenType: TokenType::Char(tmp.to_string()), span: None });
                    i += 1;
                } else {
                    self.unexpectedToken(self.nthChar(i), i);
                }
            }
            // If current char is an equals (=)
            else if currentChar == '=' {
                tokens.push(Token { tokenType: TokenType::Equals, span: None });
                i += 1;
            }
            // If current char is a plus (+)
            else if currentChar == '+' {
                tokens.push(Token { tokenType: TokenType::Plus, span: None });
                i += 1;
            }
            // If current char is a minus (-)
            else if currentChar == '-' {
                tokens.push(Token { tokenType: TokenType::Minus, span: None });
                i += 1;
            }
            // If current char is a multiple (*)
            else if currentChar == '*' {
                tokens.push(Token { tokenType: TokenType::Multiple, span: None });
                i += 1;
            }
            // If current char is a divide (/) or comment ( starts with // )
            else if currentChar == '/' {

                i += 1;
                if i < charCount && self.nthChar(i) == '/' {
                    while i < charCount && self.nthChar(i) != '\n' {
                        i += 1;
                    }

                    i += 1;
                    tokens.push(Token { tokenType: TokenType::Comment, span: None });
                } else {
                    tokens.push(Token { tokenType: TokenType::Divide, span: None });
                }
            }
            // If current char is a mod (%)
            else if currentChar == '%' {
                tokens.push(Token { tokenType: TokenType::Mod, span: None });
                i += 1;
            }
            // If current char is a greater than (>) or greater than or equal to (>=)
            else if currentChar == '>' {
                if i + 1 < charCount && self.code.chars().nth(i + 1).unwrap() == '=' {
                    tokens.push(Token { tokenType: TokenType::GreaterEqual, span: None });
                    i += 1;
                } else {
                    tokens.push(Token { tokenType: TokenType::Greater, span: None });
                }

                i += 1;
            }
            // If current char is a lesser than (<) or lesser than or equal to (<=)
            else if currentChar == '<' {
                if i < charCount && self.code.chars().nth(i + 1).unwrap() == '=' {
                    tokens.push(Token { tokenType: TokenType::LesserEqual, span: None });
                    i += 1;
                } else {
                    tokens.push(Token { tokenType: TokenType::Lesser, span: None });
                }
                i += 1;
            }
            // If current char is an Open Paranthesis ( ( )
            else if currentChar == '(' {
                tokens.push(Token { tokenType: TokenType::LParen, span: None });
                i += 1;
            }
            // If current char is a Close Paranthesis ( ) )
            else if currentChar == ')' {
                tokens.push(Token { tokenType: TokenType::RParen, span: None });
                i += 1;
            }
            // If current char is an Open Braces ( { )
            else if currentChar == '{' {
                tokens.push(Token { tokenType: TokenType::LBrace, span: None });
                i += 1;
            }
            // If current char is a Close Braces ( } )
            else if currentChar == '}' {
                tokens.push(Token { tokenType: TokenType::RBrace, span: None });
                i += 1;
            }
            // If current char is an Open Brackets ( [ )
            else if currentChar == '[' {
                tokens.push(Token { tokenType: TokenType::LBracket, span: None });
                i += 1;
            }
            // If current char is a Close Brackets ( ] )
            else if currentChar == ']' {
                tokens.push(Token { tokenType: TokenType::RBracket, span: None });
                i += 1;
            }
            // If current char is an semicolon ( ; )
            else if currentChar == ',' {
                tokens.push(Token { tokenType: TokenType::Comma, span: None });
                i += 1;
            }
            // If current char is an semicolon ( ; )
            else if currentChar == ';' {
                tokens.push(Token { tokenType: TokenType::Semicolon, span: None });
                i += 1;
            }
            // Else throw an exception
            else {
                self.unexpectedToken(currentChar, i);
            }
        }

        // End od file Token
        tokens.push(Token {tokenType: TokenType::EOF, span: None});

        self.tokens = tokens;
    }

    fn isKeyword (&self, value: &String) -> bool {
        let valueStr = &*value;
        value == "main" || value == "int" || value == "string" || value == "bool" || value == "return"
    }

    fn unexpectedToken (&self, c: char, i: usize) {
        let mut lineCount = 1;
        let mut column : usize = 0;
        let mut isFirstLine = true;

        for currIndex in (0..i).rev() {
            if self.code.chars().nth(currIndex).unwrap() == '\n' {
                if isFirstLine {
                    column = i - currIndex;
                    isFirstLine = false;
                }
                lineCount += 1;
            }
        }

        panic!("Unexpected token: {:?} at line {:?}, column {:?}!", c, lineCount, column);
    }

    pub fn currentToken (&mut self) -> Token {
        self.tokens[self.pos].to_owned()
    }

    pub fn nextToken (&mut self) -> Token {
        self.pos += 1;

        loop {
            if self.tokens[self.pos].tokenType == TokenType::Comment {
                self.pos += 1;
            } else {
                break;
            }
        }

        self.tokens[self.pos].to_owned()
    }

    fn nthChar(& self, index : usize) -> char {
        self.code.chars().nth(index).unwrap()
    }
}
<commit_msg>Previous Update Completed<commit_after>/*
 * Interpreter for Basic C like language
 * Lexer Module
 */

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TokenType {
    Keyword(String),    // like int, string or let
    Identifier(String), // like variable names
    Char(String),       // Char variables, inside " ' "
    String(String),     // String variables, inside quotes
    Number(String),     // Number variable
    True,               // Boolean true
    False,              // Boolean false
    Equals,             // =
    Plus,               // +
    Minus,              // -
    Multiple,           // *
    Divide,             // /
    Mod,                // %
    Greater,            // >
    Lesser,             // <
    GreaterEqual,       // >=
    LesserEqual,        // <=
    LParen,             // (
    RParen,             // )
    LBrace,             // {
    RBrace,             // }
    LBracket,           // [
    RBracket,           // ]
    Comma,              // ,
    Semicolon,          // ;
    Comment,            // '//'
    EOF                 // End of File
}

impl TokenType {
    pub fn toString(&self) -> &str {
        match *self {
            TokenType::Keyword(ref x) => "Keyword",
            TokenType::Identifier(ref x) => "Identifier",
            TokenType::Char(ref x) => "Char",
            TokenType::String(ref x) => "String",
            TokenType::Number(ref x) => "Number",
            TokenType::True => "True",
            TokenType::False => "False",
            TokenType::Equals => "Equals",
            TokenType::Plus => "Plus",
            TokenType::Minus => "Minus",
            TokenType::Multiple => "Multiple",
            TokenType::Divide => "Divide",
            TokenType::Mod => "Mod",
            TokenType::Greater => "Greater",
            TokenType::Lesser => "Lesser",
            TokenType::GreaterEqual => "GreaterEqual",
            TokenType::LesserEqual => "LesserEqual",
            TokenType::LParen => "LParen",
            TokenType::RParen => "RParen",
            TokenType::LBrace => "LBrace",
            TokenType::RBrace => "RBrace",
            TokenType::LBracket => "LBracket",
            TokenType::RBracket => "RBracket",
            TokenType::Comma => "Comma",
            TokenType::Semicolon => "Semicolon",
            TokenType::Comment => "Comment",
            TokenType::EOF => "EOF"
        }
    }
}

#[derive(Debug, Clone, Copy)]
pub struct Span {
    pub lo: usize,
    pub hi: usize,
}

#[derive(Debug, Clone)]
pub struct Token {
    pub tokenType: TokenType,
    pub span: Option
}

#[derive(Debug, Clone)]
pub struct TokenStream {
    pub code: String,
    pub tokens: Vec<Token>,
    pub pos: usize,
    pub curr: Option<char>
}

impl TokenStream {
    pub fn new(_code: String) -> TokenStream {
        let mut newTokenStream = TokenStream {
            code: _code,
            tokens: vec![],
            pos: 0,
            curr: None
        };

        newTokenStream.tokenize();
        newTokenStream
    }

    pub fn tokenize (&mut self) {
        let mut tokens : Vec<Token> = vec![]; // OR Vec::new();
        let charCount = self.code.chars().count();
        let mut i = 0;

        while i < charCount {
            let currentChar = self.nthChar(i);

            // If char is whitespace, just pass the current char
            if currentChar.is_whitespace() {
                i += 1;
            }
            // If char starts with alphabetic characters
            else if currentChar.is_alphabetic() {
                let mut tmp = "".to_string();

                // If current char is not out of our code scope and char starts with alphanumeric (alphabetic or numeric) characters
                while i < charCount && self.nthChar(i).is_alphanumeric() {

                    tmp = tmp + &*self.nthChar(i).to_string();
                    i += 1;
                }

                //We have the word, now we need to find what it is and tokenize it.
                let tmpStr = tmp.to_lowercase();
                if self.isKeyword(&tmpStr) {
                    tokens.push(Token { tokenType: TokenType::Keyword(tmpStr), span: None });
                } else if tmpStr == "true" {
                    tokens.push(Token {tokenType: TokenType::True, span: None });
                } else if tmpStr == "false" {
                    tokens.push(Token {tokenType: TokenType::False, span: None });
                } else {
                    tokens.push(Token {tokenType: TokenType::Identifier(tmpStr), span: None });
                }
            }
            // If current char is a numerical character
            else if currentChar.is_numeric() {
                let mut tmp = "".to_string();

                while i < charCount && self.nthChar(i).is_numeric() {
                    tmp = tmp + &*self.nthChar(i).to_string();
                    i += 1;
                }

                tokens.push(Token { tokenType: TokenType::Number(tmp), span: None });
            }
            // If current char is a starting of a string
            else if currentChar == '"' {
                let mut tmp = "".to_string();
                i += 1;

                while i < charCount && self.nthChar(i) != '"'  {
                    tmp = tmp + &*self.nthChar(i).to_string();
                    i += 1;
                }

                i += 1;
                tokens.push(Token { tokenType: TokenType::String(tmp), span: None });
            }
            // If current char is a real char
            else if currentChar == '\'' {
                let tmp = self.code.chars().nth(i + 1).unwrap();
                i += 2;

                if self.nthChar(i) == '\'' {
                    tokens.push(Token { tokenType: TokenType::Char(tmp.to_string()), span: None });
                    i += 1;
                } else {
                    self.unexpectedToken(self.nthChar(i), i);
                }
            }
            // If current char is an equals (=)
            else if currentChar == '=' {
                tokens.push(Token { tokenType: TokenType::Equals, span: None });
                i += 1;
            }
            // If current char is a plus (+)
            else if currentChar == '+' {
                tokens.push(Token { tokenType: TokenType::Plus, span: None });
                i += 1;
            }
            // If current char is a minus (-)
            else if currentChar == '-' {
                tokens.push(Token { tokenType: TokenType::Minus, span: None });
                i += 1;
            }
            // If current char is a multiple (*)
            else if currentChar == '*' {
                tokens.push(Token { tokenType: TokenType::Multiple, span: None });
                i += 1;
            }
            // If current char is a divide (/) or comment ( starts with // )
            else if currentChar == '/' {

                i += 1;
                if i < charCount && self.nthChar(i) == '/' {
                    while i < charCount && self.nthChar(i) != '\n' {
                        i += 1;
                    }

                    i += 1;
                    tokens.push(Token { tokenType: TokenType::Comment, span: None });
                } else {
                    tokens.push(Token { tokenType: TokenType::Divide, span: None });
                }
            }
            // If current char is a mod (%)
            else if currentChar == '%' {
                tokens.push(Token { tokenType: TokenType::Mod, span: None });
                i += 1;
            }
            // If current char is a greater than (>) or greater than or equal to (>=)
            else if currentChar == '>' {
                if i + 1 < charCount && self.code.chars().nth(i + 1).unwrap() == '=' {
                    tokens.push(Token { tokenType: TokenType::GreaterEqual, span: None });
                    i += 1;
                } else {
                    tokens.push(Token { tokenType: TokenType::Greater, span: None });
                }

                i += 1;
            }
            // If current char is a lesser than (<) or lesser than or equal to (<=)
            else if currentChar == '<' {
                if i < charCount && self.code.chars().nth(i + 1).unwrap() == '=' {
                    tokens.push(Token { tokenType: TokenType::LesserEqual, span: None });
                    i += 1;
                } else {
                    tokens.push(Token { tokenType: TokenType::Lesser, span: None });
                }
                i += 1;
            }
            // If current char is an Open Paranthesis ( ( )
            else if currentChar == '(' {
                tokens.push(Token { tokenType: TokenType::LParen, span: None });
                i += 1;
            }
            // If current char is a Close Paranthesis ( ) )
            else if currentChar == ')' {
                tokens.push(Token { tokenType: TokenType::RParen, span: None });
                i += 1;
            }
            // If current char is an Open Braces ( { )
            else if currentChar == '{' {
                tokens.push(Token { tokenType: TokenType::LBrace, span: None });
                i += 1;
            }
            // If current char is a Close Braces ( } )
            else if currentChar == '}' {
                tokens.push(Token { tokenType: TokenType::RBrace, span: None });
                i += 1;
            }
            // If current char is an Open Brackets ( [ )
            else if currentChar == '[' {
                tokens.push(Token { tokenType: TokenType::LBracket, span: None });
                i += 1;
            }
            // If current char is a Close Brackets ( ] )
            else if currentChar == ']' {
                tokens.push(Token { tokenType: TokenType::RBracket, span: None });
                i += 1;
            }
            // If current char is an semicolon ( ; )
            else if currentChar == ',' {
                tokens.push(Token { tokenType: TokenType::Comma, span: None });
                i += 1;
            }
            // If current char is an semicolon ( ; )
            else if currentChar == ';' {
                tokens.push(Token { tokenType: TokenType::Semicolon, span: None });
                i += 1;
            }
            // Else throw an exception
            else {
                self.unexpectedToken(currentChar, i);
            }
        }

        // End od file Token
        tokens.push(Token {tokenType: TokenType::EOF, span: None});

        self.tokens = tokens;
    }

    fn isKeyword (&self, value: &String) -> bool {
        let valueStr = &*value;
        value == "main" || value == "int" || value == "string" || value == "bool" || value == "return"
    }

    fn unexpectedToken (&self, c: char, i: usize) {
        let mut lineCount = 1;
        let mut column : usize = 0;
        let mut isFirstLine = true;

        for currIndex in (0..i).rev() {
            if self.code.chars().nth(currIndex).unwrap() == '\n' {
                if isFirstLine {
                    column = i - currIndex;
                    isFirstLine = false;
                }
                lineCount += 1;
            }
        }

        panic!("Unexpected token: {:?} at line {:?}, column {:?}!", c, lineCount, column);
    }

    pub fn currentToken (&mut self) -> Token {
        self.tokens[self.pos].to_owned()
    }

    pub fn nextToken (&mut self) -> Token {
        self.pos += 1;

        loop {
            if self.tokens[self.pos].tokenType == TokenType::Comment {
                self.pos += 1;
            } else {
                break;
            }
        }

        self.tokens[self.pos].to_owned()
    }

    fn nthChar(& self, index : usize) -> char {
        self.code.chars().nth(index).unwrap()
    }
}
<|endoftext|>


<commit_before>use std::path::{Path};

use glium::{VertexBuffer, IndexBuffer};
use glium::index::{PrimitiveType};
use glium::backend::glutin_backend::{GlutinFacade};
use tobj;
use cgmath::{Point3, Vector3, EuclideanVector};

use vertex3::{Vertex3};

pub struct Model {
	pub vertex_buffer: VertexBuffer<Vertex3>,
	pub index_buffer: IndexBuffer<u32>,
}

impl Model {
	pub fn new(context: &GlutinFacade) -> Model {
		const MODEL_PATH_STRING: &'static str = "../data/buddha.obj";
		let path = Path::new(MODEL_PATH_STRING);

		let model = match tobj::load_obj(path) {
			Ok((ref mut models, _)) => {
				match models.pop() {
					Some(m) => m,
					None => { panic!("Unable to load Model({})", MODEL_PATH_STRING) },
				}
			},
			Err(_) => { panic!("Unable to load Model({})", MODEL_PATH_STRING) },
		};

		let normals = if model.mesh.normals.is_empty() {
			Model::calculate_normals(&model.mesh.positions, &model.mesh.indices)
		} else {
			model.mesh.normals.chunks(3).map(|v| [v[0], v[1], v[2]]).collect()
		};

		// TODO: can we do a Vec::from_raw_parts or a transmute here
		//
		let mut vertices: Vec<Vertex3> = Vec::with_capacity(model.mesh.positions.len()/3);
		let iterator = model.mesh.positions.chunks(3).zip(normals);

		for (v, n) in iterator {
			vertices.push(Vertex3 {
				position: [v[0], v[1], v[2]],
				normal: n,
			});
		}

		let indices = model.mesh.indices;

		Model {
			vertex_buffer: VertexBuffer::new(context, &vertices).unwrap(),
			index_buffer: IndexBuffer::new(context, PrimitiveType::TrianglesList, &indices).unwrap(),
		}
	}

	fn calculate_normals(vertices: &[f32], indices: &[u32]) -> Vec<[f32;3]> {
		let mut face_normals: Vec<Vector3<f32>> = Vec::with_capacity(indices.len()/3);

		let mut associated_tris: Vec<Vec<u32>> = Vec::with_capacity(vertices.len()/3);
		for _ in 0..associated_tris.capacity() { associated_tris.push(Vec::new()) } // TODO: look up if this can be avoided

		for (i, tri) in indices.chunks(3).enumerate() {
			for vertex in tri {
				associated_tris[*vertex as usize].push(i as u32);
				// model.mesh.positions.chunks(3)[vertex] is used by model.mesh.indices.chunks(3)[i]
			}

			let points: Vec<Point3<f32>> = tri.iter().map(|&idx| {
				let i = idx as usize;
				let v = &vertices[(i*3)..((i+1)*3)];
				Point3::new(v[0], v[1], v[2])
			}).collect();
			let ba = points[1] - points[0];
			let ca = points[2] - points[0];

			face_normals.push(ba.cross(ca).normalize());
		}

		let mut normals = Vec::with_capacity(vertices.len());

		for index in 0..(vertices.len()/3) {
			let normal = associated_tris[index].iter().fold(
				Vector3::new(0f32, 0f32, 0f32), |acc, &i| {
				acc + face_normals[i as usize]
			});

			let normal = normal.normalize();

			normals.push([normal.x, normal.y, normal.z]);
		}
		normals
	}
}
<commit_msg>Refactor an instance of vector initialization<commit_after>use std::path::{Path};

use glium::{VertexBuffer, IndexBuffer};
use glium::index::{PrimitiveType};
use glium::backend::glutin_backend::{GlutinFacade};
use tobj;
use cgmath::{Point3, Vector3, EuclideanVector};

use vertex3::{Vertex3};

pub struct Model {
	pub vertex_buffer: VertexBuffer<Vertex3>,
	pub index_buffer: IndexBuffer<u32>,
}

impl Model {
	pub fn new(context: &GlutinFacade) -> Model {
		const MODEL_PATH_STRING: &'static str = "../data/buddha.obj";
		let path = Path::new(MODEL_PATH_STRING);

		let model = match tobj::load_obj(path) {
			Ok((ref mut models, _)) => {
				match models.pop() {
					Some(m) => m,
					None => { panic!("Unable to load Model({})", MODEL_PATH_STRING) },
				}
			},
			Err(_) => { panic!("Unable to load Model({})", MODEL_PATH_STRING) },
		};

		let normals = if model.mesh.normals.is_empty() {
			Model::calculate_normals(&model.mesh.positions, &model.mesh.indices)
		} else {
			model.mesh.normals.chunks(3).map(|v| [v[0], v[1], v[2]]).collect()
		};

		// TODO: can we do a Vec::from_raw_parts or a transmute here
		//
		let mut vertices: Vec<Vertex3> = Vec::with_capacity(model.mesh.positions.len()/3);
		let iterator = model.mesh.positions.chunks(3).zip(normals);

		for (v, n) in iterator {
			vertices.push(Vertex3 {
				position: [v[0], v[1], v[2]],
				normal: n,
			});
		}

		let indices = model.mesh.indices;

		Model {
			vertex_buffer: VertexBuffer::new(context, &vertices).unwrap(),
			index_buffer: IndexBuffer::new(context, PrimitiveType::TrianglesList, &indices).unwrap(),
		}
	}

	fn calculate_normals(vertices: &[f32], indices: &[u32]) -> Vec<[f32;3]> {
		let mut face_normals: Vec<Vector3<f32>> = Vec::with_capacity(indices.len()/3);
		let mut associated_tris: Vec<Vec<u32>> = (0..(vertices.len()/3)).map(|_| Vec::new()).collect();

		for (i, tri) in indices.chunks(3).enumerate() {
			for vertex in tri {
				associated_tris[*vertex as usize].push(i as u32);
				// model.mesh.positions.chunks(3)[vertex] is used by model.mesh.indices.chunks(3)[i]
			}

			let points: Vec<Point3<f32>> = tri.iter().map(|&idx| {
				let i = idx as usize;
				let v = &vertices[(i*3)..((i+1)*3)];
				Point3::new(v[0], v[1], v[2])
			}).collect();
			let ba = points[1] - points[0];
			let ca = points[2] - points[0];

			face_normals.push(ba.cross(ca).normalize());
		}

		let mut normals = Vec::with_capacity(vertices.len());

		for index in 0..(vertices.len()/3) {
			let normal = associated_tris[index].iter().fold(
				Vector3::new(0f32, 0f32, 0f32), |acc, &i| {
				acc + face_normals[i as usize]
			});

			let normal = normal.normalize();

			normals.push([normal.x, normal.y, normal.z]);
		}
		normals
	}
}
<|endoftext|>


<commit_before>#[derive(RustcDecodable)]
pub struct ListTopicTitleItem {
    pub url: String,
    pub url_query: UrlQueryItem,
    pub text: String,
    pub num_of_pages: usize
}

#[derive(RustcDecodable)]
pub struct ListTopicAuthorItem {
    pub url: String,
    pub name: String,
}

#[derive(RustcDecodable)]
pub struct ListTopicItem {
    pub title: ListTopicTitleItem,
    pub author: ListTopicAuthorItem,
    pub last_replied_date: String,
    pub last_replied_time: String,
    pub reply_count: String,
    pub rating: String,
}

#[derive(RustcDecodable)]
pub struct ShowItem {
    pub url_query: UrlQueryItem,
    pub title: String,
    pub reply_count: String,
    pub page: usize,
    pub max_page: usize,
    pub replies: Vec<ShowReplyItem>
}

#[derive(RustcDecodable, Debug)]
pub struct ShowReplyItem {
    pub userid: String,
    pub username: String,
    pub content: String,
    pub published_at: String
}

#[derive(RustcDecodable)]
pub struct UrlQueryItem {
    // pub type: String,
    pub message: String
}
<commit_msg>model debugable<commit_after>#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct ListTopicTitleItem {
    pub url: String,
    pub url_query: UrlQueryItem,
    pub text: String,
    pub num_of_pages: usize
}

#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct ListTopicAuthorItem {
    pub url: String,
    pub name: String,
}

#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct ListTopicItem {
    pub title: ListTopicTitleItem,
    pub author: ListTopicAuthorItem,
    pub last_replied_date: String,
    pub last_replied_time: String,
    pub reply_count: String,
    pub rating: String,
}

#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct ShowItem {
    pub url_query: UrlQueryItem,
    pub title: String,
    pub reply_count: String,
    pub page: usize,
    pub max_page: usize,
    pub replies: Vec<ShowReplyItem>
}

#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct ShowReplyItem {
    pub userid: String,
    pub username: String,
    pub content: String,
    pub published_at: String
}

#[derive(Debug)]
#[derive(RustcDecodable)]
pub struct UrlQueryItem {
    // pub type: String,
    pub message: String
}
<|endoftext|>


<commit_before>/*
* This file contains the datastructures of the staticjson tool
*/
#[derive(Clone, Debug)]
pub enum TargetLanguage {
  SWIFT, C, RUST, HTMLDOC, JSVALIDATE, JAXRS, JAVACLIENT, JQUERY
}

#[derive(Clone, Debug)]
pub enum ParserState {
  INITIAL, INTYPENAME, INTYPE,

  INTYPEPARAMNAME,    // Neu, noch unbenutzt
  INTYPEPARAMVALUE,   // Neu, noch unbenutzt
  INTYPEPARAMSTRING,  // Neu, noch unbenutzt
  OUTOFFTYPEPARAMLIST,// Neu, noch unbenutzt

  INATTRIBUTENAME, INATTRIBUTETYPE,
  INATTRIBUTEARRAY,

  INATTRIBUTEPARAMLIST,
  INATTRIBUTEPARAMNAME,
  INATTRIBUTEPARAMVALUE,
  INATTRIBUTEPARAMSTRING,

  INOUTERCMT, // in comment outside of typedefinition
  ININNERCMT, // in comment inside of typedefinition

  // Special States for Interface-Definitions
  ININTERFACECMT,

  ININTERFACENAME,
  ININTERFACEPARAMNAME,
  ININTERFACEPARAMVALUE,
  ININTERFACEPARAMSTRING,
  OUTOFINTERFACEPARAMLIST,

  INFUNCTIONNAME, INFUNCTIONRETURNTYPE,
  INFUNCTIONRETURNTYPEARRAY, BEHINDFUNCTIONRETURNTYPEARRAY,

  INFUNCTIONPARAMNAME,
  INFUNCTIONPARAMTYPE, INFUNCTION,
  INFUNCTIONPARAMTYPEARRAY, BEHINDFUNCTIONPARAMTYPEARRAY,

  // Special: Function Params can have Parameters
  INFUNCTIONPARAMPARAMNAME, INFUNCTIONPARAMPARAMVALUE,
  INFUNCTIONPARAMPARAMSTRING, INFUNCTIONPARAMPARAMLIST,
  // --

  INFUNCTIONATTRIBUTENAME,
  INFUNCTIONATTRIBUTEVALUE,
  INFUNCTIONATTRIBUTESTRING,
  // End of special States for Interface Definitions
}

#[derive(Clone, Debug)]
pub enum ParserSubState {
  LEADINGBLANKS, // Fuehrende Leerzeichen
  VALUE, // Wert
  TRAILINGBLANKS, // Auf den Wert folgende Leerzeichen
}

#[derive(Clone, Debug)]
pub struct CommandlineOptions {
  pub filename:String,
  pub target_language:TargetLanguage,
  pub target_folder:String,
  pub debug:bool
}

#[derive(Clone, Debug)]
pub struct ParserResult {
  pub types: Box<Vec<Box<Type>>>,
  pub interfaces: Box<Vec<Box<Interface>>>
}

#[derive(Clone, Debug)]
pub struct Parameter {
  pub name:String,
  pub value:String
}

#[derive(Clone, Debug)]
pub struct Attribute {
  pub name:String,
  pub attribute_type:String,
  pub is_array:bool,
  pub params:Vec<Box<Parameter>>
}

impl Attribute {
  /// Checks if a param with the given name is present in
  /// params attribute
  pub fn is_param_present(&self, param_name:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return true;
      }
    }
    return false;
  }

  // Checks if a param with the given name has the given value
  pub fn is_param_value_present(&self, param_name:&str, param_value:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return p.value == param_value;
      }
    }
    return false;
  }

  // Gets the value of the parameter with the given name
  pub fn get_param_value(&self, param_name:&str) -> String {
    for p in self.params.iter() {
      if p.name == param_name {
        return (*p).value.clone();
      }
    }
    return String::new();
  }
}

#[derive(Clone, Debug)]
pub struct Type {
  pub typename:String,
  pub attributes:Vec<Box<Attribute>>,
  pub params:Vec<Box<Parameter>>
}

impl Type {
  pub fn new() -> Type {
    Type {
      typename:String::new(),
      attributes:Vec::new(),
      params:Vec::new()
    }
  }

  pub fn is_basic_type(name:&str) -> bool {
    return name == "string"
        || name == "int"
        || name == "decimal"
        || name == "byte"
        || name == "char"
        || name == "uint"
        || name == "long"
        || name == "ulong"
        || name == "date"
        || name == "time"
        || name == "datetime";
  }

  /// Checks if a param with the given name is present in
  /// params attribute
  pub fn is_param_present(&self, param_name:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return true;
      }
    }
    return false;
  }
  // Checks if a param with the given name has the given value
  pub fn is_param_value_present(&self, param_name:&str, param_value:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return p.value == param_value;
      }
    }
    return false;
  }

  // Gets the value of the parameter with the given name
  pub fn get_param_value(&self, param_name:&str) -> String {
    for p in self.params.iter() {
      if p.name == param_name {
        return (*p).value.clone();
      }
    }
    return String::new();
  }

  pub fn is_attribute_param_present(&self, param_name:&str) -> bool {
    for a in self.attributes.iter() {
      if a.is_param_present(param_name) {
        return true;
      }
    }
    return false;
  }
}

#[derive(Clone, Debug)]
pub struct Interface {
  pub name:String,
  pub functions:Vec<Box<Function>>,
  pub params:Vec<Box<Parameter>>
}

impl Interface {
  pub fn new() -> Interface {
    Interface {
      name:String::new(),
      functions:Vec::new(),
      params:Vec::new()
    }
  }

  /// Checks if a param with the given name is present in
  /// params attribute
  pub fn is_param_present(&self, param_name:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return true;
      }
    }
    return false;
  }

  // Checks if a param with the given name has the given value
  pub fn is_param_value_present(&self, param_name:&str, param_value:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return p.value == param_value;
      }
    }
    return false;
  }

  // Gets the value of the parameter with the given name
  pub fn get_param_value(&self, param_name:&str) -> String {
    for p in self.params.iter() {
      if p.name == param_name {
        return (*p).value.clone();
      }
    }
    return String::new();
  }

  pub fn is_function_attribute_present(&self, attr_name:&str) -> bool {
    for f in self.functions.iter() {
      if f.is_attribute_present(attr_name) {
        return true;
      }
    }
    return false;
  }

  pub fn is_function_attribute_value_present(&self, attr_name:&str, attr_value:&str) -> bool {
    for f in self.functions.iter() {
      if f.is_attribute_value_present(attr_name, attr_value) {
        return true;
      }
    }
    return false;
  }

  pub fn has_function_with_complex_returntype(&self) -> bool {
    for f in self.functions.iter() {
      if f.returntype != "void"
          && !Type::is_basic_type(&f.returntype) {
            return true;
      }
    }
    return false;
  }
}

#[derive(Clone, Debug)]
pub struct Function {
  pub name:String,
  pub returntype:String,
  pub returntype_is_array:bool,
  pub params:Vec<Box<FunctionParameter>>,
  pub attributes:Vec<Box<Parameter>>
}

impl Function {
  pub fn new() -> Function {
    Function {
      name:String::new(),
      returntype:String::new(),
      returntype_is_array:false,
      params:Vec::new(),
      attributes:Vec::new()
    }
  }

  /// Checks if a param with the given name is present in
  /// params attribute
  pub fn is_attribute_present(&self, param_name:&str) -> bool {
    for p in self.attributes.iter() {
      if p.name == param_name {
        return true;
      }
    }
    return false;
  }
  // Checks if a param with the given name has the given value
  pub fn is_attribute_value_present(&self, param_name:&str, param_value:&str) -> bool {
    for p in self.attributes.iter() {
      if p.name == param_name {
        return p.value == param_value;
      }
    }
    return false;
  }

  pub fn get_attribute_value(&self, attr_name:&str) -> String {
    for attr in self.attributes.iter() {
      if attr.name == attr_name {
        return (*attr).value.clone();
      }
    }
    return String::new();
  }

  pub fn has_complex_functionparam(&self) -> bool {
    for fp in self.params.iter() {
      if fp.typename != "void"
          && !Type::is_basic_type(&fp.typename) {
            return true;
      }
    }
    return false;
  }

  // Checks if the function has a param which must be serialized as json object
  pub fn has_serialized_functionparam(&self) -> bool {
    for fp in self.params.iter() {
      if !(fp.typename == "void"
           || fp.is_param_present("query-param")
           || fp.is_param_present("path-param")) {
        return true;
      }
    }
    return false;
  }

  // Checks if the function has a param which must be serialized as json object
  pub fn get_serialized_functionparam_name(&self) -> String {
    for fp in self.params.iter() {
      if !(fp.typename == "void"
           || fp.is_param_present("query-param")
           || fp.is_param_present("path-param")) {
        return fp.name.clone();
      }
    }
    return format!("#UNKNOWN#");
  }
}

#[derive(Clone, Debug)]
pub struct FunctionParameter {
  pub name:String,
  pub typename:String,
  pub is_array:bool,
  pub params:Vec<Box<Parameter>>
}

impl FunctionParameter {
  /// Checks if a param with the given name is present in
  /// params attribute
  pub fn is_param_present(&self, param_name:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return true;
      }
    }
    return false;
  }

  // Checks if a param with the given name has the given value
  pub fn is_param_value_present(&self, param_name:&str, param_value:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return p.value == param_value;
      }
    }
    return false;
  }

  pub fn get_param_value(&self, param_name:&str) -> String {
    for param in self.params.iter() {
      if param.name == param_name {
        return (*param).value.clone();
      }
    }
    return String::new();
  }
}

pub struct GeneralModel<'a> {
  pub options:&'a CommandlineOptions,
  pub code:String,
}
<commit_msg>removed outdated comments<commit_after>/*
* This file contains the datastructures of the staticjson tool
*/
#[derive(Clone, Debug)]
pub enum TargetLanguage {
  SWIFT, C, RUST, HTMLDOC, JSVALIDATE, JAXRS, JAVACLIENT, JQUERY
}

#[derive(Clone, Debug)]
pub enum ParserState {
  INITIAL, INTYPENAME, INTYPE,

  INTYPEPARAMNAME,
  INTYPEPARAMVALUE,
  INTYPEPARAMSTRING,
  OUTOFFTYPEPARAMLIST,

  INATTRIBUTENAME, INATTRIBUTETYPE,
  INATTRIBUTEARRAY,

  INATTRIBUTEPARAMLIST,
  INATTRIBUTEPARAMNAME,
  INATTRIBUTEPARAMVALUE,
  INATTRIBUTEPARAMSTRING,

  INOUTERCMT, // in comment outside of typedefinition
  ININNERCMT, // in comment inside of typedefinition

  // Special States for Interface-Definitions
  ININTERFACECMT,

  ININTERFACENAME,
  ININTERFACEPARAMNAME,
  ININTERFACEPARAMVALUE,
  ININTERFACEPARAMSTRING,
  OUTOFINTERFACEPARAMLIST,

  INFUNCTIONNAME, INFUNCTIONRETURNTYPE,
  INFUNCTIONRETURNTYPEARRAY, BEHINDFUNCTIONRETURNTYPEARRAY,

  INFUNCTIONPARAMNAME,
  INFUNCTIONPARAMTYPE, INFUNCTION,
  INFUNCTIONPARAMTYPEARRAY, BEHINDFUNCTIONPARAMTYPEARRAY,

  // Special: Function Params can have Parameters
  INFUNCTIONPARAMPARAMNAME, INFUNCTIONPARAMPARAMVALUE,
  INFUNCTIONPARAMPARAMSTRING, INFUNCTIONPARAMPARAMLIST,
  // --

  INFUNCTIONATTRIBUTENAME,
  INFUNCTIONATTRIBUTEVALUE,
  INFUNCTIONATTRIBUTESTRING,
  // End of special States for Interface Definitions
}

#[derive(Clone, Debug)]
pub enum ParserSubState {
  LEADINGBLANKS, // Fuehrende Leerzeichen
  VALUE, // Wert
  TRAILINGBLANKS, // Auf den Wert folgende Leerzeichen
}

#[derive(Clone, Debug)]
pub struct CommandlineOptions {
  pub filename:String,
  pub target_language:TargetLanguage,
  pub target_folder:String,
  pub debug:bool
}

#[derive(Clone, Debug)]
pub struct ParserResult {
  pub types: Box<Vec<Box<Type>>>,
  pub interfaces: Box<Vec<Box<Interface>>>
}

#[derive(Clone, Debug)]
pub struct Parameter {
  pub name:String,
  pub value:String
}

#[derive(Clone, Debug)]
pub struct Attribute {
  pub name:String,
  pub attribute_type:String,
  pub is_array:bool,
  pub params:Vec<Box<Parameter>>
}

impl Attribute {
  /// Checks if a param with the given name is present in
  /// params attribute
  pub fn is_param_present(&self, param_name:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return true;
      }
    }
    return false;
  }

  // Checks if a param with the given name has the given value
  pub fn is_param_value_present(&self, param_name:&str, param_value:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return p.value == param_value;
      }
    }
    return false;
  }

  // Gets the value of the parameter with the given name
  pub fn get_param_value(&self, param_name:&str) -> String {
    for p in self.params.iter() {
      if p.name == param_name {
        return (*p).value.clone();
      }
    }
    return String::new();
  }
}

#[derive(Clone, Debug)]
pub struct Type {
  pub typename:String,
  pub attributes:Vec<Box<Attribute>>,
  pub params:Vec<Box<Parameter>>
}

impl Type {
  pub fn new() -> Type {
    Type {
      typename:String::new(),
      attributes:Vec::new(),
      params:Vec::new()
    }
  }

  pub fn is_basic_type(name:&str) -> bool {
    return name == "string"
        || name == "int"
        || name == "decimal"
        || name == "byte"
        || name == "char"
        || name == "uint"
        || name == "long"
        || name == "ulong"
        || name == "date"
        || name == "time"
        || name == "datetime";
  }

  /// Checks if a param with the given name is present in
  /// params attribute
  pub fn is_param_present(&self, param_name:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return true;
      }
    }
    return false;
  }
  // Checks if a param with the given name has the given value
  pub fn is_param_value_present(&self, param_name:&str, param_value:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return p.value == param_value;
      }
    }
    return false;
  }

  // Gets the value of the parameter with the given name
  pub fn get_param_value(&self, param_name:&str) -> String {
    for p in self.params.iter() {
      if p.name == param_name {
        return (*p).value.clone();
      }
    }
    return String::new();
  }

  pub fn is_attribute_param_present(&self, param_name:&str) -> bool {
    for a in self.attributes.iter() {
      if a.is_param_present(param_name) {
        return true;
      }
    }
    return false;
  }
}

#[derive(Clone, Debug)]
pub struct Interface {
  pub name:String,
  pub functions:Vec<Box<Function>>,
  pub params:Vec<Box<Parameter>>
}

impl Interface {
  pub fn new() -> Interface {
    Interface {
      name:String::new(),
      functions:Vec::new(),
      params:Vec::new()
    }
  }

  /// Checks if a param with the given name is present in
  /// params attribute
  pub fn is_param_present(&self, param_name:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return true;
      }
    }
    return false;
  }

  // Checks if a param with the given name has the given value
  pub fn is_param_value_present(&self, param_name:&str, param_value:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return p.value == param_value;
      }
    }
    return false;
  }

  // Gets the value of the parameter with the given name
  pub fn get_param_value(&self, param_name:&str) -> String {
    for p in self.params.iter() {
      if p.name == param_name {
        return (*p).value.clone();
      }
    }
    return String::new();
  }

  pub fn is_function_attribute_present(&self, attr_name:&str) -> bool {
    for f in self.functions.iter() {
      if f.is_attribute_present(attr_name) {
        return true;
      }
    }
    return false;
  }

  pub fn is_function_attribute_value_present(&self, attr_name:&str, attr_value:&str) -> bool {
    for f in self.functions.iter() {
      if f.is_attribute_value_present(attr_name, attr_value) {
        return true;
      }
    }
    return false;
  }

  pub fn has_function_with_complex_returntype(&self) -> bool {
    for f in self.functions.iter() {
      if f.returntype != "void"
          && !Type::is_basic_type(&f.returntype) {
            return true;
      }
    }
    return false;
  }
}

#[derive(Clone, Debug)]
pub struct Function {
  pub name:String,
  pub returntype:String,
  pub returntype_is_array:bool,
  pub params:Vec<Box<FunctionParameter>>,
  pub attributes:Vec<Box<Parameter>>
}

impl Function {
  pub fn new() -> Function {
    Function {
      name:String::new(),
      returntype:String::new(),
      returntype_is_array:false,
      params:Vec::new(),
      attributes:Vec::new()
    }
  }

  /// Checks if a param with the given name is present in
  /// params attribute
  pub fn is_attribute_present(&self, param_name:&str) -> bool {
    for p in self.attributes.iter() {
      if p.name == param_name {
        return true;
      }
    }
    return false;
  }
  // Checks if a param with the given name has the given value
  pub fn is_attribute_value_present(&self, param_name:&str, param_value:&str) -> bool {
    for p in self.attributes.iter() {
      if p.name == param_name {
        return p.value == param_value;
      }
    }
    return false;
  }

  pub fn get_attribute_value(&self, attr_name:&str) -> String {
    for attr in self.attributes.iter() {
      if attr.name == attr_name {
        return (*attr).value.clone();
      }
    }
    return String::new();
  }

  pub fn has_complex_functionparam(&self) -> bool {
    for fp in self.params.iter() {
      if fp.typename != "void"
          && !Type::is_basic_type(&fp.typename) {
            return true;
      }
    }
    return false;
  }

  // Checks if the function has a param which must be serialized as json object
  pub fn has_serialized_functionparam(&self) -> bool {
    for fp in self.params.iter() {
      if !(fp.typename == "void"
           || fp.is_param_present("query-param")
           || fp.is_param_present("path-param")) {
        return true;
      }
    }
    return false;
  }

  // Checks if the function has a param which must be serialized as json object
  pub fn get_serialized_functionparam_name(&self) -> String {
    for fp in self.params.iter() {
      if !(fp.typename == "void"
           || fp.is_param_present("query-param")
           || fp.is_param_present("path-param")) {
        return fp.name.clone();
      }
    }
    return format!("#UNKNOWN#");
  }
}

#[derive(Clone, Debug)]
pub struct FunctionParameter {
  pub name:String,
  pub typename:String,
  pub is_array:bool,
  pub params:Vec<Box<Parameter>>
}

impl FunctionParameter {
  /// Checks if a param with the given name is present in
  /// params attribute
  pub fn is_param_present(&self, param_name:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return true;
      }
    }
    return false;
  }

  // Checks if a param with the given name has the given value
  pub fn is_param_value_present(&self, param_name:&str, param_value:&str) -> bool {
    for p in self.params.iter() {
      if p.name == param_name {
        return p.value == param_value;
      }
    }
    return false;
  }

  pub fn get_param_value(&self, param_name:&str) -> String {
    for param in self.params.iter() {
      if param.name == param_name {
        return (*param).value.clone();
      }
    }
    return String::new();
  }
}

pub struct GeneralModel<'a> {
  pub options:&'a CommandlineOptions,
  pub code:String,
}
<|endoftext|>


<commit_before>use std::io::{self, Read, Write, Seek, SeekFrom};
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::ops::{Deref, DerefMut};
use std::error;
use std::fmt;
use std::env;
use std;
use util;

use super::imp;

/// A named temporary file.
///
/// This variant is *NOT* secure/reliable in the presence of a pathological temporary file cleaner.
///
/// NamedTempFiles are deleted on drop. As rust doesn't guarantee that a struct will ever be
/// dropped, these temporary files will not be deleted on abort, resource leak, early exit, etc.
///
/// Please use TempFile unless you absolutely need a named file.
///
pub struct NamedTempFile(Option<NamedTempFileInner>);

struct NamedTempFileInner {
    file: File,
    path: PathBuf,
}

impl fmt::Debug for NamedTempFile {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "NamedTempFile({:?})", self.0.as_ref().unwrap().path)
    }
}

impl Deref for NamedTempFile {
    type Target = File;
    #[inline]
    fn deref(&self) -> &File {
        &self.inner().file
    }
}

impl DerefMut for NamedTempFile {
    #[inline]
    fn deref_mut(&mut self) -> &mut File {
        &mut self.inner_mut().file
    }
}

/// Error returned when persisting a temporary file fails
#[derive(Debug)]
pub struct PersistError {
    /// The underlying IO error.
    pub error: io::Error,
    /// The temporary file that couldn't be persisted.
    pub file: NamedTempFile,
}

impl From<PersistError> for io::Error {
    #[inline]
    fn from(error: PersistError) -> io::Error {
        error.error
    }
}

impl From<PersistError> for NamedTempFile {
    #[inline]
    fn from(error: PersistError) -> NamedTempFile {
        error.file
    }
}

impl fmt::Display for PersistError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "failed to persist temporary file: {}", self.error)
    }
}

impl error::Error for PersistError {
    fn description(&self) -> &str {
        "failed to persist temporary file"
    }
    fn cause(&self) -> Option<&error::Error> {
        Some(&self.error)
    }
}

impl NamedTempFile {
    #[inline]
    fn inner(&self) -> &NamedTempFileInner {
        self.0.as_ref().unwrap()
    }

    #[inline]
    fn inner_mut(&mut self) -> &mut NamedTempFileInner {
        self.0.as_mut().unwrap()
    }

    /// Create a new temporary file.
    ///
    /// *SECURITY WARNING:* This will create a temporary file in the default temporary file
    /// directory (platform dependent). These directories are often patrolled by temporary file
    /// cleaners so only use this method if you're *positive* that the temporary file cleaner won't
    /// delete your file.
    ///
    /// Reasons to use this method:
    ///   1. The file has a short lifetime and your temporary file cleaner is sane (doesn't delete
    ///      recently accessed files).
    ///   2. You trust every user on your system (i.e. you are the only user).
    ///   3. You have disabled your system's temporary file cleaner or verified that your system
    ///      doesn't have a temporary file cleaner.
    ///
    /// Reasons not to use this method:
    ///   1. You'll fix it later. No you won't.
    ///   2. You don't care about the security of the temporary file. If none of the "reasons to
    ///      use this method" apply, referring to a temporary file by name may allow an attacker
    ///      to create/overwrite your non-temporary files. There are exceptions but if you don't
    ///      already know them, don't use this method.
    pub fn new() -> io::Result<NamedTempFile> {
        NamedTempFileOptions::new().create()
    }

    /// Create a new temporary file in the specified directory.
    pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<NamedTempFile> {
        NamedTempFileOptions::new().create_in(dir)
    }

    /// Get the temporary file's path.
    ///
    /// *SECURITY WARNING:* Only use this method if you're positive that a temporary file cleaner
    /// won't have deleted your file. Otherwise, the path returned by this method may refer to an
    /// attacker controlled file.
    #[inline]
    pub fn path(&self) -> &Path {
        &self.inner().path
    }

    /// Close and remove the temporary file.
    ///
    /// Use this if you want to detect errors in deleting the file.
    pub fn close(mut self) -> io::Result<()> {
        let NamedTempFileInner { path, file } = self.0.take().unwrap();
        drop(file);
        fs::remove_file(path)
    }

    /// Persist the temporary file at the target path.
    ///
    /// If a file exists at the target path, persist will atomically replace it. If this method
    /// fails, it will return `self` in the resulting PersistError.
    ///
    /// Note: Temporary files cannot be persisted across filesystems.
    ///
    /// *SECURITY WARNING:* Only use this method if you're positive that a temporary file cleaner
    /// won't have deleted your file. Otherwise, you might end up persisting an attacker controlled
    /// file.
    pub fn persist<P: AsRef<Path>>(mut self, new_path: P) -> Result<File, PersistError> {
        match imp::persist(&self.inner().path, new_path.as_ref(), true) {
            Ok(_) => Ok(self.0.take().unwrap().file),
            Err(e) => Err(PersistError { file: self, error: e }),
        }
    }

    /// Persist the temporary file at the target path iff no file exists there.
    ///
    /// If a file exists at the target path, fail. If this method fails, it will return `self` in
    /// the resulting PersistError.
    ///
    /// Note: Temporary files cannot be persisted across filesystems.
    /// Also Note: This method is not atomic. It can leave the original link to the temporary file
    /// behind.
    ///
    /// *SECURITY WARNING:* Only use this method if you're positive that a temporary file cleaner
    /// won't have deleted your file. Otherwise, you might end up persisting an attacker controlled
    /// file.
    pub fn persist_noclobber<P: AsRef<Path>>(mut self, new_path: P) -> Result<File, PersistError> {
        match imp::persist(&self.inner().path, new_path.as_ref(), false) {
            Ok(_) => Ok(self.0.take().unwrap().file),
            Err(e) => Err(PersistError { file: self, error: e }),
        }
    }
}

impl Drop for NamedTempFile {
    fn drop(&mut self) {
        if let Some(NamedTempFileInner { file, path }) = self.0.take() {
            drop(file);
            let _ = fs::remove_file(path);
        }
    }
}

impl Read for NamedTempFile {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (**self).read(buf)
    }
}

impl Write for NamedTempFile {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        (**self).write(buf)
    }
    #[inline]
    fn flush(&mut self) -> io::Result<()> {
        (**self).flush()
    }
}

impl Seek for NamedTempFile {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        (**self).seek(pos)
    }
}

#[cfg(unix)]
impl std::os::unix::io::AsRawFd for NamedTempFile {
    #[inline]
    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
        (**self).as_raw_fd()
    }
}

#[cfg(windows)]
impl std::os::windows::io::AsRawHandle for NamedTempFile {
    #[inline]
    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
        (**self).as_raw_handle()
    }
}

/// Create a new temporary file with custom parameters.
///
/// # Example
/// ```
/// use tempfile::NamedTempFileOptions;
///
/// let named_temp_file = NamedTempFileOptions::new()
///                         .prefix("hogehoge")
///                         .suffix(".rs")
///                         .rand_bytes(5)
///                         .create_in("/tmp")
///                         .unwrap();
/// println!("{:?}", named_temp_file);        //Something like "NamedTempFile(\"/tmp/hogehoge65R8Y.rs\")"
/// ```
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct NamedTempFileOptions<'a , 'b> {
    random_len: usize,
    prefix: &'a str,
    suffix: &'b str
}

impl<'a, 'b> NamedTempFileOptions<'a, 'b> {
    /// Create a new NamedTempFileOptions
    pub fn new() -> Self {
        NamedTempFileOptions {
            random_len: ::NUM_RAND_CHARS,
            prefix: ".tmp",
            suffix: ""
        }
    }

    /// Set a custom filename prefix.
    ///
    /// Path separators are legal but not advisable.
    /// Default: ".tmp"
    pub fn prefix(&mut self, prefix: &'a str) -> &mut Self {
        self.prefix = prefix;
        self
    }

    /// Set a custom filename suffix.
    ///
    /// Path separators are legal but not advisable.
    /// Default: ""
    pub fn suffix(&mut self, suffix: &'b str) -> &mut Self {
        self.suffix = suffix;
        self
    }

    /// Set the number of random bytes.
    ///
    /// Default: 6
    pub fn rand_bytes(&mut self, rand: usize) -> &mut Self {
        self.random_len = rand;
        self
    }

    /// Create the named temporary file.
    pub fn create(&self) -> io::Result<NamedTempFile> {
        self.create_in(&env::temp_dir())
    }

    /// Create the named temporary file in the specified directory.
    pub fn create_in<P: AsRef<Path>>(&self, dir: P) -> io::Result<NamedTempFile> {
        for _ in 0..::NUM_RETRIES {
            let path = dir.as_ref().join(util::tmpname(self.prefix, self.suffix, self.random_len));
            return match imp::create_named(&path) {
                Ok(file) => Ok(NamedTempFile(Some(NamedTempFileInner { path: path, file: file, }))),
                Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => continue,
                Err(e) => Err(e),
            }
        }
        Err(io::Error::new(io::ErrorKind::AlreadyExists,
                           "too many temporary files exist"))

    }
}
<commit_msg>Fix doctest on windows<commit_after>use std::io::{self, Read, Write, Seek, SeekFrom};
use std::fs::{self, File};
use std::path::{Path, PathBuf};
use std::ops::{Deref, DerefMut};
use std::error;
use std::fmt;
use std::env;
use std;
use util;

use super::imp;

/// A named temporary file.
///
/// This variant is *NOT* secure/reliable in the presence of a pathological temporary file cleaner.
///
/// NamedTempFiles are deleted on drop. As rust doesn't guarantee that a struct will ever be
/// dropped, these temporary files will not be deleted on abort, resource leak, early exit, etc.
///
/// Please use TempFile unless you absolutely need a named file.
///
pub struct NamedTempFile(Option<NamedTempFileInner>);

struct NamedTempFileInner {
    file: File,
    path: PathBuf,
}

impl fmt::Debug for NamedTempFile {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "NamedTempFile({:?})", self.0.as_ref().unwrap().path)
    }
}

impl Deref for NamedTempFile {
    type Target = File;
    #[inline]
    fn deref(&self) -> &File {
        &self.inner().file
    }
}

impl DerefMut for NamedTempFile {
    #[inline]
    fn deref_mut(&mut self) -> &mut File {
        &mut self.inner_mut().file
    }
}

/// Error returned when persisting a temporary file fails
#[derive(Debug)]
pub struct PersistError {
    /// The underlying IO error.
    pub error: io::Error,
    /// The temporary file that couldn't be persisted.
    pub file: NamedTempFile,
}

impl From<PersistError> for io::Error {
    #[inline]
    fn from(error: PersistError) -> io::Error {
        error.error
    }
}

impl From<PersistError> for NamedTempFile {
    #[inline]
    fn from(error: PersistError) -> NamedTempFile {
        error.file
    }
}

impl fmt::Display for PersistError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "failed to persist temporary file: {}", self.error)
    }
}

impl error::Error for PersistError {
    fn description(&self) -> &str {
        "failed to persist temporary file"
    }
    fn cause(&self) -> Option<&error::Error> {
        Some(&self.error)
    }
}

impl NamedTempFile {
    #[inline]
    fn inner(&self) -> &NamedTempFileInner {
        self.0.as_ref().unwrap()
    }

    #[inline]
    fn inner_mut(&mut self) -> &mut NamedTempFileInner {
        self.0.as_mut().unwrap()
    }

    /// Create a new temporary file.
    ///
    /// *SECURITY WARNING:* This will create a temporary file in the default temporary file
    /// directory (platform dependent). These directories are often patrolled by temporary file
    /// cleaners so only use this method if you're *positive* that the temporary file cleaner won't
    /// delete your file.
    ///
    /// Reasons to use this method:
    ///   1. The file has a short lifetime and your temporary file cleaner is sane (doesn't delete
    ///      recently accessed files).
    ///   2. You trust every user on your system (i.e. you are the only user).
    ///   3. You have disabled your system's temporary file cleaner or verified that your system
    ///      doesn't have a temporary file cleaner.
    ///
    /// Reasons not to use this method:
    ///   1. You'll fix it later. No you won't.
    ///   2. You don't care about the security of the temporary file. If none of the "reasons to
    ///      use this method" apply, referring to a temporary file by name may allow an attacker
    ///      to create/overwrite your non-temporary files. There are exceptions but if you don't
    ///      already know them, don't use this method.
    pub fn new() -> io::Result<NamedTempFile> {
        NamedTempFileOptions::new().create()
    }

    /// Create a new temporary file in the specified directory.
    pub fn new_in<P: AsRef<Path>>(dir: P) -> io::Result<NamedTempFile> {
        NamedTempFileOptions::new().create_in(dir)
    }

    /// Get the temporary file's path.
    ///
    /// *SECURITY WARNING:* Only use this method if you're positive that a temporary file cleaner
    /// won't have deleted your file. Otherwise, the path returned by this method may refer to an
    /// attacker controlled file.
    #[inline]
    pub fn path(&self) -> &Path {
        &self.inner().path
    }

    /// Close and remove the temporary file.
    ///
    /// Use this if you want to detect errors in deleting the file.
    pub fn close(mut self) -> io::Result<()> {
        let NamedTempFileInner { path, file } = self.0.take().unwrap();
        drop(file);
        fs::remove_file(path)
    }

    /// Persist the temporary file at the target path.
    ///
    /// If a file exists at the target path, persist will atomically replace it. If this method
    /// fails, it will return `self` in the resulting PersistError.
    ///
    /// Note: Temporary files cannot be persisted across filesystems.
    ///
    /// *SECURITY WARNING:* Only use this method if you're positive that a temporary file cleaner
    /// won't have deleted your file. Otherwise, you might end up persisting an attacker controlled
    /// file.
    pub fn persist<P: AsRef<Path>>(mut self, new_path: P) -> Result<File, PersistError> {
        match imp::persist(&self.inner().path, new_path.as_ref(), true) {
            Ok(_) => Ok(self.0.take().unwrap().file),
            Err(e) => Err(PersistError { file: self, error: e }),
        }
    }

    /// Persist the temporary file at the target path iff no file exists there.
    ///
    /// If a file exists at the target path, fail. If this method fails, it will return `self` in
    /// the resulting PersistError.
    ///
    /// Note: Temporary files cannot be persisted across filesystems.
    /// Also Note: This method is not atomic. It can leave the original link to the temporary file
    /// behind.
    ///
    /// *SECURITY WARNING:* Only use this method if you're positive that a temporary file cleaner
    /// won't have deleted your file. Otherwise, you might end up persisting an attacker controlled
    /// file.
    pub fn persist_noclobber<P: AsRef<Path>>(mut self, new_path: P) -> Result<File, PersistError> {
        match imp::persist(&self.inner().path, new_path.as_ref(), false) {
            Ok(_) => Ok(self.0.take().unwrap().file),
            Err(e) => Err(PersistError { file: self, error: e }),
        }
    }
}

impl Drop for NamedTempFile {
    fn drop(&mut self) {
        if let Some(NamedTempFileInner { file, path }) = self.0.take() {
            drop(file);
            let _ = fs::remove_file(path);
        }
    }
}

impl Read for NamedTempFile {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        (**self).read(buf)
    }
}

impl Write for NamedTempFile {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        (**self).write(buf)
    }
    #[inline]
    fn flush(&mut self) -> io::Result<()> {
        (**self).flush()
    }
}

impl Seek for NamedTempFile {
    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
        (**self).seek(pos)
    }
}

#[cfg(unix)]
impl std::os::unix::io::AsRawFd for NamedTempFile {
    #[inline]
    fn as_raw_fd(&self) -> std::os::unix::io::RawFd {
        (**self).as_raw_fd()
    }
}

#[cfg(windows)]
impl std::os::windows::io::AsRawHandle for NamedTempFile {
    #[inline]
    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
        (**self).as_raw_handle()
    }
}

/// Create a new temporary file with custom parameters.
///
/// # Example
/// ```
/// use tempfile::NamedTempFileOptions;
///
/// let named_temp_file = NamedTempFileOptions::new()
///                         .prefix("hogehoge")
///                         .suffix(".rs")
///                         .rand_bytes(5)
///                         .create()
///                         .unwrap();
/// println!("{:?}", named_temp_file);        //Something like "NamedTempFile(\"/tmp/hogehoge65R8Y.rs\")"
/// ```
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct NamedTempFileOptions<'a , 'b> {
    random_len: usize,
    prefix: &'a str,
    suffix: &'b str
}

impl<'a, 'b> NamedTempFileOptions<'a, 'b> {
    /// Create a new NamedTempFileOptions
    pub fn new() -> Self {
        NamedTempFileOptions {
            random_len: ::NUM_RAND_CHARS,
            prefix: ".tmp",
            suffix: ""
        }
    }

    /// Set a custom filename prefix.
    ///
    /// Path separators are legal but not advisable.
    /// Default: ".tmp"
    pub fn prefix(&mut self, prefix: &'a str) -> &mut Self {
        self.prefix = prefix;
        self
    }

    /// Set a custom filename suffix.
    ///
    /// Path separators are legal but not advisable.
    /// Default: ""
    pub fn suffix(&mut self, suffix: &'b str) -> &mut Self {
        self.suffix = suffix;
        self
    }

    /// Set the number of random bytes.
    ///
    /// Default: 6
    pub fn rand_bytes(&mut self, rand: usize) -> &mut Self {
        self.random_len = rand;
        self
    }

    /// Create the named temporary file.
    pub fn create(&self) -> io::Result<NamedTempFile> {
        self.create_in(&env::temp_dir())
    }

    /// Create the named temporary file in the specified directory.
    pub fn create_in<P: AsRef<Path>>(&self, dir: P) -> io::Result<NamedTempFile> {
        for _ in 0..::NUM_RETRIES {
            let path = dir.as_ref().join(util::tmpname(self.prefix, self.suffix, self.random_len));
            return match imp::create_named(&path) {
                Ok(file) => Ok(NamedTempFile(Some(NamedTempFileInner { path: path, file: file, }))),
                Err(ref e) if e.kind() == io::ErrorKind::AlreadyExists => continue,
                Err(e) => Err(e),
            }
        }
        Err(io::Error::new(io::ErrorKind::AlreadyExists,
                           "too many temporary files exist"))

    }
}
<|endoftext|>