<commit_before>use crate::source_analysis::prelude::*;
use quote::ToTokens;
use std::path::PathBuf;
use syn::{spanned::Spanned, *};

impl SourceAnalysis {
    pub(crate) fn process_items(&mut self, items: &[Item], ctx: &Context) -> SubResult {
        let mut res = SubResult::Ok;
        for item in items.iter() {
            match *item {
                Item::ExternCrate(ref i) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(i);
                }
                Item::Use(ref i) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(i);
                }
                Item::Mod(ref i) => self.visit_mod(&i, ctx),
                Item::Fn(ref i) => self.visit_fn(&i, ctx),
                Item::Struct(ref i) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(i);
                }
                Item::Enum(ref i) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(i);
                }
                Item::Union(ref i) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(i);
                }
                Item::Trait(ref i) => self.visit_trait(&i, ctx),
                Item::Impl(ref i) => self.visit_impl(&i, ctx),
                Item::Macro(ref i) => {
                    if self.visit_macro_call(&i.mac, ctx).is_unreachable() {
                        res = SubResult::Unreachable;
                    }
                }
                Item::Const(ref c) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(c);
                }
                _ => {}
            }
        }
        res
    }

    fn visit_mod(&mut self, module: &ItemMod, ctx: &Context) {
        let analysis = self.get_line_analysis(ctx.file.to_path_buf());
        analysis.ignore_tokens(module.mod_token);
        let mut check_insides = true;
        for attr in &module.attrs {
            if let Ok(x) = attr.parse_meta() {
                if check_cfg_attr(&x) {
                    analysis.ignore_tokens(module);
                    if let Some((ref braces, _)) = module.content {
                        analysis.ignore_span(braces.span);
                    }
                    check_insides = false;
                    break;
                } else if ctx.config.ignore_tests && x.path().is_ident("cfg") {
                    if let Meta::List(ref ml) = x {
                        for nested in &ml.nested {
                            if let NestedMeta::Meta(Meta::Path(ref i)) = *nested {
                                if i.is_ident("test") {
                                    check_insides = false;
                                    analysis.ignore_tokens(module.mod_token);
                                    if let Some((ref braces, _)) = module.content {
                                        analysis.ignore_span(braces.span);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        if check_insides {
            if let Some((_, ref items)) = module.content {
                self.process_items(items, ctx);
            }
        } else {
            // Get the file or directory name of the module
            let mut p = if let Some(parent) = ctx.file.parent() {
                parent.join(module.ident.to_string())
            } else {
                PathBuf::from(module.ident.to_string())
            };
            if !p.exists() {
                p.set_extension("rs");
            }
            ctx.ignore_mods.borrow_mut().insert(p);
        }
    }

    fn visit_fn(&mut self, func: &ItemFn, ctx: &Context) {
        let mut test_func = false;
        let mut ignored_attr = false;
        let mut is_inline = false;
        let mut ignore_span = false;
        for attr in &func.attrs {
            if let Ok(x) = attr.parse_meta() {
                let id = x.path();
                if id.is_ident("test") {
                    test_func = true;
                } else if id.is_ident("derive") {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_span(attr.bracket_token.span);
                } else if id.is_ident("inline") {
                    is_inline = true;
                } else if id.is_ident("ignore") {
                    ignored_attr = true;
                } else if check_cfg_attr(&x) {
                    ignore_span = true;
                    break;
                }
            }
        }
        if ignore_span
            || (test_func && ctx.config.ignore_tests)
            || (ignored_attr && !ctx.config.run_ignored)
        {
            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
            analysis.ignore_tokens(func);
        } else {
            if is_inline {
                let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                // We need to force cover!
                analysis.cover_span(func.block.brace_token.span, Some(ctx.file_contents));
            }
            if self
                .process_statements(&func.block.stmts, ctx)
                .is_unreachable()
            {
                // if the whole body of the function is unreachable, that means the function itself
                // cannot be called, so is unreachable as a whole
                let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                analysis.ignore_tokens(func);
                return;
            }
            self.visit_generics(&func.sig.generics, ctx);
            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
            let line_number = func.sig.fn_token.span().start().line;
            analysis.ignore.remove(&Lines::Line(line_number));
            // Ignore multiple lines of fn decl
            let decl_start = func.sig.fn_token.span().start().line + 1;
            let stmts_start = func.block.span().start().line;
            let lines = (decl_start..(stmts_start + 1)).collect::<Vec<_>>();
            analysis.add_to_ignore(&lines);
        }
    }

    fn visit_trait(&mut self, trait_item: &ItemTrait, ctx: &Context) {
        let check_cover = self.check_attr_list(&trait_item.attrs, ctx);
        if check_cover {
            for item in &trait_item.items {
                if let TraitItem::Method(ref i) = *item {
                    if self.check_attr_list(&i.attrs, ctx) {
                        if let Some(ref block) = i.default {
                            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                            analysis.cover_token_stream(
                                item.into_token_stream(),
                                Some(ctx.file_contents),
                            );
                            self.visit_generics(&i.sig.generics, ctx);
                            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                            analysis
                                .ignore
                                .remove(&Lines::Line(i.sig.span().start().line));

                            // Ignore multiple lines of fn decl
                            let decl_start = i.sig.fn_token.span().start().line + 1;
                            let stmts_start = block.span().start().line;
                            let lines = (decl_start..(stmts_start + 1)).collect::<Vec<_>>();
                            analysis.add_to_ignore(&lines);
                        }
                    } else {
                        let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                        analysis.ignore_tokens(i);
                    }
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    for a in &i.attrs {
                        analysis.ignore_tokens(a);
                    }
                }
            }
            self.visit_generics(&trait_item.generics, ctx);
        } else {
            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
            analysis.ignore_tokens(trait_item);
        }
    }

    fn visit_impl(&mut self, impl_blk: &ItemImpl, ctx: &Context) {
        let check_cover = self.check_attr_list(&impl_blk.attrs, ctx);
        if check_cover {
            for item in &impl_blk.items {
                if let ImplItem::Method(ref i) = *item {
                    if self.check_attr_list(&i.attrs, ctx) {
                        {
                            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                            analysis
                                .cover_token_stream(i.into_token_stream(), Some(ctx.file_contents));
                        }
                        if self
                            .process_statements(&i.block.stmts, ctx)
                            .is_unreachable()
                        {
                            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                            // if the body of this method is unreachable, this means that the method
                            // cannot be called, and is unreachable
                            analysis.ignore_tokens(i);
                            return;
                        }

                        self.visit_generics(&i.sig.generics, ctx);
                        let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                        analysis.ignore.remove(&Lines::Line(i.span().start().line));

                        // Ignore multiple lines of fn decl
                        let decl_start = i.sig.fn_token.span().start().line + 1;
                        let stmts_start = i.block.span().start().line;
                        let lines = (decl_start..(stmts_start + 1)).collect::<Vec<_>>();
                        analysis.add_to_ignore(&lines);
                    } else {
                        let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                        analysis.ignore_tokens(item);
                    }
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    for a in &i.attrs {
                        analysis.ignore_tokens(a);
                    }
                }
            }
            self.visit_generics(&impl_blk.generics, ctx);
        } else {
            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
            analysis.ignore_tokens(impl_blk);
        }
    }
}
<commit_msg>Unify the code for ImplItemMethod and ItemFn (#853)<commit_after>use crate::source_analysis::prelude::*;
use std::path::PathBuf;
use syn::{spanned::Spanned, *};

impl SourceAnalysis {
    pub(crate) fn process_items(&mut self, items: &[Item], ctx: &Context) -> SubResult {
        let mut res = SubResult::Ok;
        for item in items.iter() {
            match *item {
                Item::ExternCrate(ref i) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(i);
                }
                Item::Use(ref i) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(i);
                }
                Item::Mod(ref i) => self.visit_mod(&i, ctx),
                Item::Fn(ref i) => self.visit_fn(&i, ctx, false),
                Item::Struct(ref i) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(i);
                }
                Item::Enum(ref i) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(i);
                }
                Item::Union(ref i) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(i);
                }
                Item::Trait(ref i) => self.visit_trait(&i, ctx),
                Item::Impl(ref i) => self.visit_impl(&i, ctx),
                Item::Macro(ref i) => {
                    if self.visit_macro_call(&i.mac, ctx).is_unreachable() {
                        res = SubResult::Unreachable;
                    }
                }
                Item::Const(ref c) => {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_tokens(c);
                }
                _ => {}
            }
        }
        res
    }

    fn visit_mod(&mut self, module: &ItemMod, ctx: &Context) {
        let analysis = self.get_line_analysis(ctx.file.to_path_buf());
        analysis.ignore_tokens(module.mod_token);
        let mut check_insides = true;
        for attr in &module.attrs {
            if let Ok(x) = attr.parse_meta() {
                if check_cfg_attr(&x) {
                    analysis.ignore_tokens(module);
                    if let Some((ref braces, _)) = module.content {
                        analysis.ignore_span(braces.span);
                    }
                    check_insides = false;
                    break;
                } else if ctx.config.ignore_tests && x.path().is_ident("cfg") {
                    if let Meta::List(ref ml) = x {
                        for nested in &ml.nested {
                            if let NestedMeta::Meta(Meta::Path(ref i)) = *nested {
                                if i.is_ident("test") {
                                    check_insides = false;
                                    analysis.ignore_tokens(module.mod_token);
                                    if let Some((ref braces, _)) = module.content {
                                        analysis.ignore_span(braces.span);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        if check_insides {
            if let Some((_, ref items)) = module.content {
                self.process_items(items, ctx);
            }
        } else {
            // Get the file or directory name of the module
            let mut p = if let Some(parent) = ctx.file.parent() {
                parent.join(module.ident.to_string())
            } else {
                PathBuf::from(module.ident.to_string())
            };
            if !p.exists() {
                p.set_extension("rs");
            }
            ctx.ignore_mods.borrow_mut().insert(p);
        }
    }

    fn visit_fn(&mut self, func: &ItemFn, ctx: &Context, force_cover: bool) {
        let mut test_func = false;
        let mut ignored_attr = false;
        let mut is_inline = false;
        let mut ignore_span = false;
        let is_generic = !func.sig.generics.params.is_empty();
        for attr in &func.attrs {
            if let Ok(x) = attr.parse_meta() {
                let id = x.path();
                if id.is_ident("test") {
                    test_func = true;
                } else if id.is_ident("derive") {
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    analysis.ignore_span(attr.bracket_token.span);
                } else if id.is_ident("inline") {
                    is_inline = true;
                } else if id.is_ident("ignore") {
                    ignored_attr = true;
                } else if check_cfg_attr(&x) {
                    ignore_span = true;
                    break;
                }
            }
        }
        if ignore_span
            || (test_func && ctx.config.ignore_tests)
            || (ignored_attr && !ctx.config.run_ignored)
        {
            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
            analysis.ignore_tokens(func);
        } else {
            if is_inline || is_generic || force_cover {
                let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                // We need to force cover!
                analysis.cover_span(func.block.brace_token.span, Some(ctx.file_contents));
            }
            if self
                .process_statements(&func.block.stmts, ctx)
                .is_unreachable()
            {
                // if the whole body of the function is unreachable, that means the function itself
                // cannot be called, so is unreachable as a whole
                let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                analysis.ignore_tokens(func);
                return;
            }
            self.visit_generics(&func.sig.generics, ctx);
            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
            let line_number = func.sig.fn_token.span().start().line;
            analysis.ignore.remove(&Lines::Line(line_number));
            // Ignore multiple lines of fn decl
            let decl_start = func.sig.fn_token.span().start().line + 1;
            let stmts_start = func.block.span().start().line;
            let lines = (decl_start..(stmts_start + 1)).collect::<Vec<_>>();
            analysis.add_to_ignore(&lines);
        }
    }

    fn visit_trait(&mut self, trait_item: &ItemTrait, ctx: &Context) {
        let check_cover = self.check_attr_list(&trait_item.attrs, ctx);
        if check_cover {
            for item in &trait_item.items {
                if let TraitItem::Method(ref i) = *item {
                    if self.check_attr_list(&i.attrs, ctx) {
                        let item = i.clone();
                        if let Some(block) = item.default {
                            let item_fn = ItemFn {
                                attrs: item.attrs,
                                // Trait functions inherit visibility from the trait
                                vis: trait_item.vis.clone(),
                                sig: item.sig,
                                block: Box::new(block),
                            };
                            // We visit the function and force cover it
                            self.visit_fn(&item_fn, ctx, true);
                        } else {
                            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                            analysis.ignore_tokens(i);
                        }
                    } else {
                        let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                        analysis.ignore_tokens(i);
                    }
                    let analysis = self.get_line_analysis(ctx.file.to_path_buf());
                    for a in &i.attrs {
                        analysis.ignore_tokens(a);
                    }
                }
            }
            self.visit_generics(&trait_item.generics, ctx);
        } else {
            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
            analysis.ignore_tokens(trait_item);
        }
    }

    fn visit_impl(&mut self, impl_blk: &ItemImpl, ctx: &Context) {
        let check_cover = self.check_attr_list(&impl_blk.attrs, ctx);
        if check_cover {
            for item in &impl_blk.items {
                if let ImplItem::Method(ref i) = *item {
                    let item = i.clone();
                    let item_fn = ItemFn {
                        attrs: item.attrs,
                        vis: item.vis,
                        sig: item.sig,
                        block: Box::new(item.block),
                    };

                    // If the impl is on a generic, we need to force cover
                    let force_cover = !impl_blk.generics.params.is_empty();

                    self.visit_fn(&item_fn, ctx, force_cover);
                }
            }
            self.visit_generics(&impl_blk.generics, ctx);
        } else {
            let analysis = self.get_line_analysis(ctx.file.to_path_buf());
            analysis.ignore_tokens(impl_blk);
        }
    }
}
<|endoftext|>


<commit_before>use regex::Regex;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use super::file::{FileHeaderSpec, FileHeaderData};

pub struct ParserError {
    summary: String,
    parsertext: String,
    index: i32,
    explanation: Option<String>,
}

impl ParserError {
    pub fn new(sum: &'static str, text: String, idx: i32, expl: &'static str) -> ParserError {
        ParserError {
            summary: String::from(sum),
            parsertext: text,
            index: idx,
            explanation: Some(String::from(expl)),
        }
    }

    pub fn short(sum: &'static str, text: String, idx: i32) -> ParserError {
        ParserError {
            summary: String::from(sum),
            parsertext: text,
            index: idx,
            explanation: None
        }
    }
}

impl Error for ParserError {

    fn description(&self) -> &str {
        &self.summary[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Debug for ParserError {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "ParserError: {}\n\n", self.summary);

        if let Some(ref e) = self.explanation {
            write!(fmt, "{}\n\n", e);
        }

        write!(fmt, "On position {}\nin\n{}", self.index, self.parsertext);
        Ok(())
    }

}

impl Display for ParserError {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "ParserError: {}", self.summary);

        if let Some(ref e) = self.explanation {
            write!(fmt, "\n\n{}", e);
        }

        Ok(())
    }

}

pub trait FileHeaderParser<'a> : Sized {
    fn new(spec: &'a FileHeaderSpec) -> Self;
    fn read(&self, string: Option<String>) -> Result<FileHeaderData, ParserError>;
    fn write(&self, data: &FileHeaderData) -> Result<String, ParserError>;
}

type TextTpl = (Option<String>, Option<String>);

pub struct Parser<HP>
{
    headerp : HP,
}

impl<'a, HP> Parser<HP> where
    HP: FileHeaderParser<'a>,
{

    fn new(headerp: HP) -> Parser<HP> {
        Parser {
            headerp: headerp,
        }
    }

    pub fn read(&self, s: String) -> Result<(FileHeaderData, String), ParserError>
    {
        debug!("Reading into internal datastructure: '{}'", s);
        let divided = self.divide_text(&s);

        if divided.is_err() {
            debug!("Error reading into internal datastructure");
            return Err(divided.err().unwrap());
        }

        let (header, data) = divided.ok().unwrap();
        debug!("Header = '{:?}'", header);
        debug!("Data   = '{:?}'", data);

        let h_parseres = try!(self.headerp.read(header));
        debug!("Success parsing header");

        Ok((h_parseres, data.unwrap_or(String::new())))
    }

    pub fn write(&self, tpl : (FileHeaderData, String)) -> Result<String, ParserError>
    {
        debug!("Parsing internal datastructure to String");
        let (header, data) = tpl;
        let h_text = try!(self.headerp.write(&header));
        debug!("Success translating header");

        Ok(h_text + &data[..])
    }

    fn divide_text(&self, text: &String) -> Result<TextTpl, ParserError> {
        debug!("Splitting: '{}'", text);
        let re = Regex::new(r"(?m)^\-\-\-$\n(.*)^\-\-\-$\n(.*)").unwrap();

        let captures = re.captures(&text[..]).unwrap_or(
            return Err(ParserError::new("Cannot run regex on text",
                                        text.clone(), 0,
                                        "Cannot run regex on text to divide it into header and content."))
        );

        if captures.len() != 2 {
            return Err(ParserError::new("Unexpected Regex output",
                                        text.clone(), 0,
                                        "The regex to divide text into header and content had an unexpected output."))
        }

        let header  = captures.at(0).map(|s| String::from(s));
        let content = captures.at(1).map(|s| String::from(s));

        debug!("Splitted, Header = '{:?}'", header);
        debug!("Splitted, Data   = '{:?}'", content);
        Ok((header, content))
    }

}

<commit_msg>parser: Remove livetimes<commit_after>use regex::Regex;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use super::file::{FileHeaderSpec, FileHeaderData};

pub struct ParserError {
    summary: String,
    parsertext: String,
    index: i32,
    explanation: Option<String>,
}

impl ParserError {
    pub fn new(sum: &'static str, text: String, idx: i32, expl: &'static str) -> ParserError {
        ParserError {
            summary: String::from(sum),
            parsertext: text,
            index: idx,
            explanation: Some(String::from(expl)),
        }
    }

    pub fn short(sum: &'static str, text: String, idx: i32) -> ParserError {
        ParserError {
            summary: String::from(sum),
            parsertext: text,
            index: idx,
            explanation: None
        }
    }
}

impl Error for ParserError {

    fn description(&self) -> &str {
        &self.summary[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Debug for ParserError {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "ParserError: {}\n\n", self.summary);

        if let Some(ref e) = self.explanation {
            write!(fmt, "{}\n\n", e);
        }

        write!(fmt, "On position {}\nin\n{}", self.index, self.parsertext);
        Ok(())
    }

}

impl Display for ParserError {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "ParserError: {}", self.summary);

        if let Some(ref e) = self.explanation {
            write!(fmt, "\n\n{}", e);
        }

        Ok(())
    }

}

pub trait FileHeaderParser : Sized {
    fn read(&self, string: Option<String>) -> Result<FileHeaderData, ParserError>;
    fn write(&self, data: &FileHeaderData) -> Result<String, ParserError>;
}

type TextTpl = (Option<String>, Option<String>);

pub struct Parser<HP>
{
    headerp : HP,
}

impl<HP> Parser<HP> where
    HP: FileHeaderParser,
{

    pub fn new(headerp: HP) -> Parser<HP> {
        Parser {
            headerp: headerp,
        }
    }

    pub fn read(&self, s: String) -> Result<(FileHeaderData, String), ParserError>
    {
        debug!("Reading into internal datastructure: '{}'", s);
        let divided = self.divide_text(&s);

        if divided.is_err() {
            debug!("Error reading into internal datastructure");
            return Err(divided.err().unwrap());
        }

        let (header, data) = divided.ok().unwrap();
        debug!("Header = '{:?}'", header);
        debug!("Data   = '{:?}'", data);

        let h_parseres = try!(self.headerp.read(header));
        debug!("Success parsing header");

        Ok((h_parseres, data.unwrap_or(String::new())))
    }

    pub fn write(&self, tpl : (FileHeaderData, String)) -> Result<String, ParserError>
    {
        debug!("Parsing internal datastructure to String");
        let (header, data) = tpl;
        let h_text = try!(self.headerp.write(&header));
        debug!("Success translating header");

        Ok(h_text + &data[..])
    }

    fn divide_text(&self, text: &String) -> Result<TextTpl, ParserError> {
        debug!("Splitting: '{}'", text);
        let re = Regex::new(r"(?m)^\-\-\-$\n(.*)^\-\-\-$\n(.*)").unwrap();

        let captures = re.captures(&text[..]).unwrap_or(
            return Err(ParserError::new("Cannot run regex on text",
                                        text.clone(), 0,
                                        "Cannot run regex on text to divide it into header and content."))
        );

        if captures.len() != 2 {
            return Err(ParserError::new("Unexpected Regex output",
                                        text.clone(), 0,
                                        "The regex to divide text into header and content had an unexpected output."))
        }

        let header  = captures.at(0).map(|s| String::from(s));
        let content = captures.at(1).map(|s| String::from(s));

        debug!("Splitted, Header = '{:?}'", header);
        debug!("Splitted, Data   = '{:?}'", content);
        Ok((header, content))
    }

}

<|endoftext|>


<commit_before>use regex::Regex;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use super::file::{FileHeaderSpec, FileHeaderData};

pub struct ParserError {
    summary: String,
    parsertext: String,
    index: i32,
    explanation: Option<String>,
}

impl ParserError {
    pub fn new(sum: &'static str, text: String, idx: i32, expl: &'static str) -> ParserError {
        ParserError {
            summary: String::from(sum),
            parsertext: text,
            index: idx,
            explanation: Some(String::from(expl)),
        }
    }

    pub fn short(sum: &'static str, text: String, idx: i32) -> ParserError {
        ParserError {
            summary: String::from(sum),
            parsertext: text,
            index: idx,
            explanation: None
        }
    }
}

impl Error for ParserError {

    fn description(&self) -> &str {
        &self.summary[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Debug for ParserError {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "ParserError: {}\n\n", self.summary);

        if let Some(ref e) = self.explanation {
            write!(fmt, "{}\n\n", e);
        }

        write!(fmt, "On position {}\nin\n{}", self.index, self.parsertext);
        Ok(())
    }

}

impl Display for ParserError {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "ParserError: {}", self.summary);

        if let Some(ref e) = self.explanation {
            write!(fmt, "\n\n{}", e);
        }

        Ok(())
    }

}

pub trait FileHeaderParser : Sized {
    fn read(&self, string: Option<String>) -> Result<FileHeaderData, ParserError>;
    fn write(&self, data: &FileHeaderData) -> Result<String, ParserError>;
}

type TextTpl = (Option<String>, Option<String>);

pub struct Parser<HP>
{
    headerp : HP,
}

impl<HP> Parser<HP> where
    HP: FileHeaderParser,
{

    pub fn new(headerp: HP) -> Parser<HP> {
        Parser {
            headerp: headerp,
        }
    }

    pub fn read(&self, s: String) -> Result<(FileHeaderData, String), ParserError>
    {
        debug!("Reading into internal datastructure: '{}'", s);
        let divided = self.divide_text(&s);

        if divided.is_err() {
            debug!("Error reading into internal datastructure");
            return Err(divided.err().unwrap());
        }

        let (header, data) = divided.ok().unwrap();
        debug!("Header = '{:?}'", header);
        debug!("Data   = '{:?}'", data);

        let h_parseres = try!(self.headerp.read(header));
        debug!("Success parsing header");

        Ok((h_parseres, data.unwrap_or(String::new())))
    }

    pub fn write(&self, tpl : (FileHeaderData, String)) -> Result<String, ParserError>
    {
        debug!("Parsing internal datastructure to String");
        let (header, data) = tpl;
        let h_text = try!(self.headerp.write(&header));
        debug!("Success translating header");

        Ok(h_text + &data[..])
    }

    fn divide_text(&self, text: &String) -> Result<TextTpl, ParserError> {
        debug!("Splitting: '{}'", text);
        let re = Regex::new(r"(?m)^\-\-\-$\n(.*)^\-\-\-$\n(.*)").unwrap();

        let captures = re.captures(&text[..]).unwrap_or(
            return Err(ParserError::new("Cannot run regex on text",
                                        text.clone(), 0,
                                        "Cannot run regex on text to divide it into header and content."))
        );

        if captures.len() != 2 {
            return Err(ParserError::new("Unexpected Regex output",
                                        text.clone(), 0,
                                        "The regex to divide text into header and content had an unexpected output."))
        }

        let header  = captures.at(0).map(|s| String::from(s));
        let content = captures.at(1).map(|s| String::from(s));

        debug!("Splitted, Header = '{:?}'", header);
        debug!("Splitted, Data   = '{:?}'", content);
        Ok((header, content))
    }

}

<commit_msg>Remove static livetime in ParserError::short()<commit_after>use regex::Regex;
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use super::file::{FileHeaderSpec, FileHeaderData};

pub struct ParserError {
    summary: String,
    parsertext: String,
    index: i32,
    explanation: Option<String>,
}

impl ParserError {
    pub fn new(sum: &'static str, text: String, idx: i32, expl: &'static str) -> ParserError {
        ParserError {
            summary: String::from(sum),
            parsertext: text,
            index: idx,
            explanation: Some(String::from(expl)),
        }
    }

    pub fn short(sum: &str, text: String, idx: i32) -> ParserError {
        ParserError {
            summary: String::from(sum),
            parsertext: text,
            index: idx,
            explanation: None
        }
    }
}

impl Error for ParserError {

    fn description(&self) -> &str {
        &self.summary[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }

}

impl Debug for ParserError {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "ParserError: {}\n\n", self.summary);

        if let Some(ref e) = self.explanation {
            write!(fmt, "{}\n\n", e);
        }

        write!(fmt, "On position {}\nin\n{}", self.index, self.parsertext);
        Ok(())
    }

}

impl Display for ParserError {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "ParserError: {}", self.summary);

        if let Some(ref e) = self.explanation {
            write!(fmt, "\n\n{}", e);
        }

        Ok(())
    }

}

pub trait FileHeaderParser : Sized {
    fn read(&self, string: Option<String>) -> Result<FileHeaderData, ParserError>;
    fn write(&self, data: &FileHeaderData) -> Result<String, ParserError>;
}

type TextTpl = (Option<String>, Option<String>);

pub struct Parser<HP>
{
    headerp : HP,
}

impl<HP> Parser<HP> where
    HP: FileHeaderParser,
{

    pub fn new(headerp: HP) -> Parser<HP> {
        Parser {
            headerp: headerp,
        }
    }

    pub fn read(&self, s: String) -> Result<(FileHeaderData, String), ParserError>
    {
        debug!("Reading into internal datastructure: '{}'", s);
        let divided = self.divide_text(&s);

        if divided.is_err() {
            debug!("Error reading into internal datastructure");
            return Err(divided.err().unwrap());
        }

        let (header, data) = divided.ok().unwrap();
        debug!("Header = '{:?}'", header);
        debug!("Data   = '{:?}'", data);

        let h_parseres = try!(self.headerp.read(header));
        debug!("Success parsing header");

        Ok((h_parseres, data.unwrap_or(String::new())))
    }

    pub fn write(&self, tpl : (FileHeaderData, String)) -> Result<String, ParserError>
    {
        debug!("Parsing internal datastructure to String");
        let (header, data) = tpl;
        let h_text = try!(self.headerp.write(&header));
        debug!("Success translating header");

        Ok(h_text + &data[..])
    }

    fn divide_text(&self, text: &String) -> Result<TextTpl, ParserError> {
        debug!("Splitting: '{}'", text);
        let re = Regex::new(r"(?m)^\-\-\-$\n(.*)^\-\-\-$\n(.*)").unwrap();

        let captures = re.captures(&text[..]).unwrap_or(
            return Err(ParserError::new("Cannot run regex on text",
                                        text.clone(), 0,
                                        "Cannot run regex on text to divide it into header and content."))
        );

        if captures.len() != 2 {
            return Err(ParserError::new("Unexpected Regex output",
                                        text.clone(), 0,
                                        "The regex to divide text into header and content had an unexpected output."))
        }

        let header  = captures.at(0).map(|s| String::from(s));
        let content = captures.at(1).map(|s| String::from(s));

        debug!("Splitted, Header = '{:?}'", header);
        debug!("Splitted, Data   = '{:?}'", content);
        Ok((header, content))
    }

}

<|endoftext|>


<commit_before>use std::collections::BTreeSet;
use std::ops::Bound::Included;

// https://leetcode.com/problems/longest-uploaded-prefix/
struct LUPrefix {}

impl LUPrefix {
    fn new(n: i32) -> Self {
        LUPrefix {}
    }

    fn upload(&mut self, video: i32) {
        todo!()
    }

    fn longest(&self) -> i32 {
        todo!()
    }
}

fn main() {
    let mut server = LUPrefix::new(4);
    server.upload(3);
    println!("{}", server.longest()); // 0
    server.upload(1);
    println!("{}", server.longest()); // 1
    server.upload(2);
    println!("{}", server.longest()); // 3
}
<commit_msg>Solve problem 2424<commit_after>use std::collections::HashSet;

// https://leetcode.com/problems/longest-uploaded-prefix/
struct LUPrefix {
    set: HashSet<i32>,
    longest: i32,
}

impl LUPrefix {
    fn new(n: i32) -> Self {
        LUPrefix {
            set: HashSet::new(),
            longest: 0,
        }
    }

    fn upload(&mut self, video: i32) {
        self.set.insert(video);
        while self.set.contains(&(self.longest + 1)) {
            self.longest += 1;
        }
    }

    fn longest(&self) -> i32 {
        self.longest
    }
}

fn main() {
    let mut server = LUPrefix::new(4);
    server.upload(3);
    println!("{}", server.longest()); // 0
    server.upload(1);
    println!("{}", server.longest()); // 1
    server.upload(2);
    println!("{}", server.longest()); // 3
}
<|endoftext|>


<commit_before>extern crate libc;
extern crate image;

#[cfg(target_os = "windows")] extern crate winapi;
#[cfg(not(target_os = "windows"))] extern crate glutin;

/*
 mod platform {

   mod win32_platform;
   pub use self::win32_platform::*;
 }

mod platform {
   mod glutin_platform;
   pub use self::glutin_platform::*;
}
*/

mod bitmap;
mod platform;

pub mod palette;
pub mod default_font;
mod font;
mod input;

pub use bitmap::*;
pub use font::*;
pub use input::*;

use std::cell::RefCell;
use std::result::Result;
use std::cmp;
use std::time::{Instant, Duration};
use std::thread;
use std::fmt;

#[derive(Copy, Clone, PartialEq)]
pub struct Rect {
   pub left: i32,
   pub right: i32,
   pub top: i32,
   pub bottom: i32,
}

impl Rect {
   pub fn new(left: i32, top: i32, right: i32, bottom: i32) -> Rect {
      Rect {
         left: left,
         right: right,
         top: top,
         bottom: bottom,
      }
   }

   pub fn new_size(x: i32, y: i32, w: i32, h: i32) -> Rect {
      Rect {
         left: x,
         right: x + w,
         top: y,
         bottom: y + h,
      }
   }

   #[inline]
   pub fn inside(&self, x: i32, y: i32) -> bool {
       self.left <= x && x <= self.right && self.top <= y && y <= self.bottom
   }

   pub fn intersect(&self, r: Rect) -> Rect {
       Rect {
           left: cmp::min(r.right, cmp::max(self.left, r.left)),
           right: cmp::max(r.left, cmp::min(self.right, r.right)),
           top: cmp::min(r.bottom, cmp::max(self.top, r.top)),
           bottom: cmp::max(r.top, cmp::max(self.bottom, r.bottom)),
       }
   }

   #[inline]
   pub fn tr(&self, x: i32, y: i32) -> Rect {
       Rect {
           left: self.left + x,
           right: self.right + x,
           top: self.top + y,
           bottom: self.bottom + y,
       }
   }

   pub fn fit(&self, x: i32, y: i32, w: i32, h: i32) -> Rect {
       Rect {
           left: cmp::max(self.left, x),
           right: cmp::min(self.right, x + w),
           top: cmp::max(self.top, y),
           bottom: cmp::min(self.bottom, y + h),
       }
   }

   #[inline]
   pub fn grow(&self, w: i32, h: i32) -> Rect {
      Rect {
         left: self.left,
         right: self.right + w,
         top: self.top,
         bottom: self.bottom + h,
      }
   }

   #[inline]
   pub fn width(&self) -> i32 {
      self.right - self.left
   }

   #[inline]
   pub fn height(&self) -> i32 {
      self.bottom - self.top
   }
}

impl fmt::Display for Rect {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(left: {}, right: {}, top: {}, bottom: {})", self.left, self.right, self.top, self.bottom)
    }
}

#[derive(Copy, Clone, PartialEq)]
pub struct Color {
    pub rgba: u32,
}

impl Color {
   pub fn new(r: u8, g: u8, b: u8, a: u8) -> Color {
      Color { rgba: (a as u32) << platform::COLOR_OFFSET_A | (b as u32) << platform::COLOR_OFFSET_B | (g as u32) << platform::COLOR_OFFSET_G | (r as u32) << platform::COLOR_OFFSET_R }
   }

   #[inline]
   pub fn red(&self) -> u8 {
      ((self.rgba >> platform::COLOR_OFFSET_R) & 0xff) as u8
   }

   #[inline]
   pub fn green(&self) -> u8 {
      ((self.rgba >> platform::COLOR_OFFSET_G) & 0xff) as u8
   }

   #[inline]
   pub fn blue(&self) -> u8 {
      ((self.rgba >> platform::COLOR_OFFSET_B) & 0xff) as u8
   }

   #[inline]
   pub fn alpha(&self) -> u8 {
      ((self.rgba >> platform::COLOR_OFFSET_A) & 0xff) as u8
   }

   #[inline]
   pub fn redf(&self) -> f32 {
      self.red() as f32 / 255.0
   }

   #[inline]
   pub fn greenf(&self) -> f32 {
      self.green() as f32 / 255.0
   }

   #[inline]
   pub fn bluef(&self) -> f32 {
      self.blue() as f32 / 255.0
   }

   #[inline]
   pub fn alphaf(&self) -> f32 {
      self.alpha() as f32 / 255.0
   }
}

#[derive(Clone)]
pub struct Palette {
   colors: Vec<Color>,
}

impl Palette {
   fn new() -> Palette {
      Palette {
         colors: vec![Color::new(0, 0, 0, 0), Color::new(0, 0, 0, 255), Color::new(255, 255, 255, 255)],
      }
   }

   fn add_color(&mut self, color: Color) -> u8 {
      for i in 0..self.colors.len() {
         if self.colors[i].rgba == color.rgba {
            return i as u8;
         }
      }

      self.colors.push(color);
      (self.colors.len() - 1) as u8
   }
}

pub struct Config {
   title: String,
   width: u32,
   height: u32,
   scale: u32,
}

pub const DRAW_FLIP_H: u32 = (1 << 1);
pub const DRAW_MASK: u32 = (1 << 2);

pub trait Painter {
   fn size(&self) -> (u32, u32);

   fn clip(&self, rect: Option<Rect>);

   fn clear(&self, color: u8);

   fn pixel(&self, x: i32, y: i32, color: u8);

   fn line(&self, x1: i32, y1: i32, x2: i32, y2: i32, color: u8);

   fn rect_stroke(&self, rect: Rect, color: u8);
   fn rect_fill(&self, rect: Rect, color: u8);

   fn blit(&self, x: i32, y: i32, source: &Bitmap, source_rect: Rect, flags: u32, color: u8);

   fn text(&self, x: i32, y: i32, text: &str, color: u8, font: &Font);
   fn char(&self, x: i32, y: i32, ch: char, color: u8, font: &Font) -> (i32, i32);
}

pub trait Application : Sized {
   fn new(ctx: &mut Context) -> Result<Self, String>;

   fn step(&mut self, ctx: &Context) -> bool { !ctx.key_pressed(Key::Escape) }
   fn paint(&self, ctx: &Context, painter: &Painter);
}

use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
static IS_TINY_CONTEXT_ALIVE: AtomicBool = ATOMIC_BOOL_INIT;

pub const TRANSPARENT: u8 = 0;
pub const BLACK: u8 = 1;
pub const WHITE: u8 = 2;

pub struct Context {
   palette: RefCell<Palette>,
   window: platform::Window,

   pub frame_time: f64,
   pub step_time: f64,
   pub paint_time: f64,
   pub blit_time: f64,
   pub sleep_time: f64,
}

impl Context {
   fn new(window: platform::Window) -> Context {
      Context {
         palette: RefCell::new(Palette::new()),
         window: window,
         frame_time: 0.0,
         step_time: 0.0,
         paint_time: 0.0,
         blit_time: 0.0,
         sleep_time: 0.0,
      }
   }

   pub fn set_palette(&mut self, palette: Palette) {
      *self.palette.borrow_mut() = palette;
   }

   pub fn palette(&self) -> Palette {
      self.palette.borrow().clone()
   }

   pub fn palette_add(&self, color: Color) -> u8 {
       self.palette.borrow_mut().add_color(color)
   }

   pub fn key_down(&self, key: Key) -> bool {
       self.window.key_state[key as usize]
   }

   pub fn key_pressed(&self, key: Key) -> bool {
       self.window.key_state[key as usize] && self.window.key_delta[key as usize]
   }

   pub fn text_input<'a>(&'a self) -> &'a Vec<char> {
      &self.window.text_input
   }

   pub fn mouse_down(&self, mouse: Mouse) -> bool {
      self.window.mouse_state[mouse as usize]
   }

   pub fn mouse_pressed(&self, mouse: Mouse) -> bool {
       self.window.mouse_state[mouse as usize] && self.window.mouse_delta[mouse as usize]
   }

   pub fn mouse_position(&self) -> (u32, u32) {
      (self.window.mouse_x, self.window.mouse_y)
   }

   pub fn set_background_color(&mut self, color: Color) {
      self.window.set_background_color(color);
   }

   pub fn draw_timing(&self, painter: &Painter, font: &Font, background_color: u8, foreground_color: u8) {
      let text = format!("FRAME: {:4.1} MS\nPAINT: {:4.1} MS\n STEP: {:4.1} MS\n BLIT: {:4.1} MS\nSLEEP: {:4.1} MS", self.frame_time, self.paint_time, self.step_time, self.blit_time, self.sleep_time);
      let text_rect = font.measure(&text);
      let background_rect = text_rect.tr(2, 2).grow(4, 4);

      painter.clip(Some(background_rect));
      painter.rect_fill(background_rect, background_color);
      painter.text(background_rect.left + 2, background_rect.top + 2, &text, foreground_color, font);
      painter.clip(None);
   }
}

fn to_milisec(duration: Duration) -> f64 {
   (duration.as_secs() as f64 * 1_000f64) + (duration.subsec_nanos() as f64 / 1_000_000f64)
}

pub fn run<T: Application>(title: &str, width: u32, height: u32, scale: u32) -> Result<(), String> {
   use std::sync::atomic::Ordering;
   let was_alive = IS_TINY_CONTEXT_ALIVE.swap(true, Ordering::Relaxed);
   if was_alive {
      return Err("Cannot initialize Tiny more than once at a time".to_owned());
   }

   let config = Config {
      title: String::from(title),
      width: width,
      height: height,
      scale: scale,
   };

   println!("Starting '{}' with resolution {}x{} at scale {}", config.title, config.width, config.height, config.scale);

   let mut context = match platform::Window::new(&config) {
      Ok(window) => Context::new(window),
      Err(err) => return Err(err),
   };

   let mut canvas = Bitmap::new(config.width, config.height);

   // Initialize the application
   let mut app = match T::new(&mut context) {
      Ok(app) => app,
      Err(err) => return Err(err),
   };

   context.window.show();

   let target_frame_time = 33_333_333u32; // An fps of 30Hz

   let mut step_time;
   let mut paint_time;
   let mut blit_time;
   let mut frame_time;
   let mut sleep_time;

   // Main loop
   'main: loop {
      let frame_now = Instant::now();

      // Handle messages
      if !context.window.pump() {
         break;
      }

      {  // Step the application
         let step_now = Instant::now();

         if !app.step(&context) {
             break 'main;
         }

         step_time = to_milisec(step_now.elapsed());
      }

      {  // Let the application paint to the canvas
         let paint_now = Instant::now();

         let p = BitmapPainter::new(&mut canvas);
         app.paint(&context, &p);

         paint_time = to_milisec(paint_now.elapsed());
      }

      {  // Blit canvas to the window
         let blit_now = Instant::now();

         if let Err(err) = context.window.paint(&canvas, &context.palette.borrow_mut().colors) {
            return Err(err);
         }

         blit_time = to_milisec(blit_now.elapsed());
      }

      let frame_duration = frame_now.elapsed();
      frame_time = to_milisec(frame_duration);

      context.step_time = context.step_time * 0.98 + step_time * 0.02;
      context.paint_time = context.paint_time * 0.98 + paint_time * 0.02;
      context.blit_time = context.blit_time * 0.98 + blit_time * 0.02;
      context.frame_time = context.frame_time * 0.98 + frame_time * 0.02;

      // Sleep to force the frame time to 33ms
      if frame_duration.as_secs() == 0 && frame_duration.subsec_nanos() < target_frame_time {
         let sleep_duration = Duration::new(0, target_frame_time - frame_duration.subsec_nanos());

         sleep_time = to_milisec(sleep_duration);
         context.sleep_time = context.sleep_time * 0.98 + sleep_time * 0.02;

         thread::sleep(sleep_duration);
      }
   }

   let was_alive = IS_TINY_CONTEXT_ALIVE.swap(false, Ordering::Relaxed);
   assert!(was_alive);
   Ok(())
}

#[cfg(test)]
mod tests {
   #[test]
   fn it_works() {
   }
}
<commit_msg>Some cleanup<commit_after>extern crate libc;
extern crate image;

#[cfg(target_os = "windows")]
extern crate winapi;

#[cfg(not(target_os = "windows"))]
extern crate glutin;

mod bitmap;
mod platform;

pub mod palette;
pub mod default_font;
mod font;
mod input;

pub use bitmap::*;
pub use font::*;
pub use input::*;

use std::cell::RefCell;
use std::result::Result;
use std::cmp;
use std::time::{Instant, Duration};
use std::thread;
use std::fmt;

#[derive(Copy, Clone, PartialEq)]
pub struct Rect {
   pub left: i32,
   pub right: i32,
   pub top: i32,
   pub bottom: i32,
}

impl Rect {
   pub fn new(left: i32, top: i32, right: i32, bottom: i32) -> Rect {
      Rect {
         left: left,
         right: right,
         top: top,
         bottom: bottom,
      }
   }

   pub fn new_size(x: i32, y: i32, w: i32, h: i32) -> Rect {
      Rect {
         left: x,
         right: x + w,
         top: y,
         bottom: y + h,
      }
   }

   #[inline]
   pub fn inside(&self, x: i32, y: i32) -> bool {
       self.left <= x && x <= self.right && self.top <= y && y <= self.bottom
   }

   pub fn intersect(&self, r: Rect) -> Rect {
       Rect {
           left: cmp::min(r.right, cmp::max(self.left, r.left)),
           right: cmp::max(r.left, cmp::min(self.right, r.right)),
           top: cmp::min(r.bottom, cmp::max(self.top, r.top)),
           bottom: cmp::max(r.top, cmp::max(self.bottom, r.bottom)),
       }
   }

   #[inline]
   pub fn tr(&self, x: i32, y: i32) -> Rect {
       Rect {
           left: self.left + x,
           right: self.right + x,
           top: self.top + y,
           bottom: self.bottom + y,
       }
   }

   pub fn fit(&self, x: i32, y: i32, w: i32, h: i32) -> Rect {
       Rect {
           left: cmp::max(self.left, x),
           right: cmp::min(self.right, x + w),
           top: cmp::max(self.top, y),
           bottom: cmp::min(self.bottom, y + h),
       }
   }

   #[inline]
   pub fn grow(&self, w: i32, h: i32) -> Rect {
      Rect {
         left: self.left,
         right: self.right + w,
         top: self.top,
         bottom: self.bottom + h,
      }
   }

   #[inline]
   pub fn width(&self) -> i32 {
      self.right - self.left
   }

   #[inline]
   pub fn height(&self) -> i32 {
      self.bottom - self.top
   }
}

impl fmt::Display for Rect {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "(left: {}, right: {}, top: {}, bottom: {})", self.left, self.right, self.top, self.bottom)
    }
}

#[derive(Copy, Clone, PartialEq)]
pub struct Color {
    pub rgba: u32,
}

impl Color {
   pub fn new(r: u8, g: u8, b: u8, a: u8) -> Color {
      Color { rgba: (a as u32) << platform::COLOR_OFFSET_A | (b as u32) << platform::COLOR_OFFSET_B | (g as u32) << platform::COLOR_OFFSET_G | (r as u32) << platform::COLOR_OFFSET_R }
   }

   #[inline]
   pub fn red(&self) -> u8 {
      ((self.rgba >> platform::COLOR_OFFSET_R) & 0xff) as u8
   }

   #[inline]
   pub fn green(&self) -> u8 {
      ((self.rgba >> platform::COLOR_OFFSET_G) & 0xff) as u8
   }

   #[inline]
   pub fn blue(&self) -> u8 {
      ((self.rgba >> platform::COLOR_OFFSET_B) & 0xff) as u8
   }

   #[inline]
   pub fn alpha(&self) -> u8 {
      ((self.rgba >> platform::COLOR_OFFSET_A) & 0xff) as u8
   }

   #[inline]
   pub fn redf(&self) -> f32 {
      self.red() as f32 / 255.0
   }

   #[inline]
   pub fn greenf(&self) -> f32 {
      self.green() as f32 / 255.0
   }

   #[inline]
   pub fn bluef(&self) -> f32 {
      self.blue() as f32 / 255.0
   }

   #[inline]
   pub fn alphaf(&self) -> f32 {
      self.alpha() as f32 / 255.0
   }
}

#[derive(Clone)]
pub struct Palette {
   colors: Vec<Color>,
}

impl Palette {
   fn new() -> Palette {
      Palette {
         colors: vec![Color::new(0, 0, 0, 0), Color::new(0, 0, 0, 255), Color::new(255, 255, 255, 255)],
      }
   }

   fn add_color(&mut self, color: Color) -> u8 {
      for i in 0..self.colors.len() {
         if self.colors[i].rgba == color.rgba {
            return i as u8;
         }
      }

      self.colors.push(color);
      (self.colors.len() - 1) as u8
   }
}

pub struct Config {
   title: String,
   width: u32,
   height: u32,
   scale: u32,
}

pub const DRAW_FLIP_H: u32 = (1 << 1);
pub const DRAW_MASK: u32 = (1 << 2);

pub trait Painter {
   fn size(&self) -> (u32, u32);

   fn clip(&self, rect: Option<Rect>);

   fn clear(&self, color: u8);

   fn pixel(&self, x: i32, y: i32, color: u8);

   fn line(&self, x1: i32, y1: i32, x2: i32, y2: i32, color: u8);

   fn rect_stroke(&self, rect: Rect, color: u8);
   fn rect_fill(&self, rect: Rect, color: u8);

   fn blit(&self, x: i32, y: i32, source: &Bitmap, source_rect: Rect, flags: u32, color: u8);

   fn text(&self, x: i32, y: i32, text: &str, color: u8, font: &Font);
   fn char(&self, x: i32, y: i32, ch: char, color: u8, font: &Font) -> (i32, i32);
}

pub trait Application : Sized {
   fn new(ctx: &mut Context) -> Result<Self, String>;

   fn step(&mut self, ctx: &Context) -> bool { !ctx.key_pressed(Key::Escape) }
   fn paint(&self, ctx: &Context, painter: &Painter);
}

use std::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT};
static IS_TINY_CONTEXT_ALIVE: AtomicBool = ATOMIC_BOOL_INIT;

pub const TRANSPARENT: u8 = 0;
pub const BLACK: u8 = 1;
pub const WHITE: u8 = 2;

pub struct Context {
   palette: RefCell<Palette>,
   window: platform::Window,

   pub frame_time: f64,
   pub step_time: f64,
   pub paint_time: f64,
   pub blit_time: f64,
   pub sleep_time: f64,
}

impl Context {
   fn new(window: platform::Window) -> Context {
      Context {
         palette: RefCell::new(Palette::new()),
         window: window,
         frame_time: 0.0,
         step_time: 0.0,
         paint_time: 0.0,
         blit_time: 0.0,
         sleep_time: 0.0,
      }
   }

   pub fn set_palette(&mut self, palette: Palette) {
      *self.palette.borrow_mut() = palette;
   }

   pub fn palette(&self) -> Palette {
      self.palette.borrow().clone()
   }

   pub fn palette_add(&self, color: Color) -> u8 {
       self.palette.borrow_mut().add_color(color)
   }

   pub fn key_down(&self, key: Key) -> bool {
       self.window.key_state[key as usize]
   }

   pub fn key_pressed(&self, key: Key) -> bool {
       self.window.key_state[key as usize] && self.window.key_delta[key as usize]
   }

   pub fn text_input<'a>(&'a self) -> &'a Vec<char> {
      &self.window.text_input
   }

   pub fn mouse_down(&self, mouse: Mouse) -> bool {
      self.window.mouse_state[mouse as usize]
   }

   pub fn mouse_pressed(&self, mouse: Mouse) -> bool {
       self.window.mouse_state[mouse as usize] && self.window.mouse_delta[mouse as usize]
   }

   pub fn mouse_position(&self) -> (u32, u32) {
      (self.window.mouse_x, self.window.mouse_y)
   }

   pub fn set_background_color(&mut self, color: Color) {
      self.window.set_background_color(color);
   }

   pub fn draw_timing(&self, painter: &Painter, font: &Font, background_color: u8, foreground_color: u8) {
      let text = format!("FRAME: {:4.1} MS\nPAINT: {:4.1} MS\n STEP: {:4.1} MS\n BLIT: {:4.1} MS\nSLEEP: {:4.1} MS", self.frame_time, self.paint_time, self.step_time, self.blit_time, self.sleep_time);
      let text_rect = font.measure(&text);
      let background_rect = text_rect.tr(2, 2).grow(4, 4);

      painter.clip(Some(background_rect));
      painter.rect_fill(background_rect, background_color);
      painter.text(background_rect.left + 2, background_rect.top + 2, &text, foreground_color, font);
      painter.clip(None);
   }
}

fn to_milisec(duration: Duration) -> f64 {
   (duration.as_secs() as f64 * 1_000f64) + (duration.subsec_nanos() as f64 / 1_000_000f64)
}

pub fn run<T: Application>(title: &str, width: u32, height: u32, scale: u32) -> Result<(), String> {
   use std::sync::atomic::Ordering;
   let was_alive = IS_TINY_CONTEXT_ALIVE.swap(true, Ordering::Relaxed);
   if was_alive {
      return Err("Cannot initialize Tiny more than once at a time".to_owned());
   }

   let config = Config {
      title: String::from(title),
      width: width,
      height: height,
      scale: scale,
   };

   println!("Starting '{}' with resolution {}x{} at scale {}", config.title, config.width, config.height, config.scale);

   let mut context = match platform::Window::new(&config) {
      Ok(window) => Context::new(window),
      Err(err) => return Err(err),
   };

   let mut canvas = Bitmap::new(config.width, config.height);

   // Initialize the application
   let mut app = match T::new(&mut context) {
      Ok(app) => app,
      Err(err) => return Err(err),
   };

   context.window.show();

   let target_frame_time = 33_333_333u32; // An fps of 30Hz

   let mut step_time;
   let mut paint_time;
   let mut blit_time;
   let mut frame_time;
   let mut sleep_time;

   // Main loop
   'main: loop {
      let frame_now = Instant::now();

      // Handle messages
      if !context.window.pump() {
         break;
      }

      {  // Step the application
         let step_now = Instant::now();

         if !app.step(&context) {
             break 'main;
         }

         step_time = to_milisec(step_now.elapsed());
      }

      {  // Let the application paint to the canvas
         let paint_now = Instant::now();

         let p = BitmapPainter::new(&mut canvas);
         app.paint(&context, &p);

         paint_time = to_milisec(paint_now.elapsed());
      }

      {  // Blit canvas to the window
         let blit_now = Instant::now();

         if let Err(err) = context.window.paint(&canvas, &context.palette.borrow_mut().colors) {
            return Err(err);
         }

         blit_time = to_milisec(blit_now.elapsed());
      }

      let frame_duration = frame_now.elapsed();
      frame_time = to_milisec(frame_duration);

      context.step_time = context.step_time * 0.98 + step_time * 0.02;
      context.paint_time = context.paint_time * 0.98 + paint_time * 0.02;
      context.blit_time = context.blit_time * 0.98 + blit_time * 0.02;
      context.frame_time = context.frame_time * 0.98 + frame_time * 0.02;

      // Sleep to force the frame time to 33ms
      if frame_duration.as_secs() == 0 && frame_duration.subsec_nanos() < target_frame_time {
         let sleep_duration = Duration::new(0, target_frame_time - frame_duration.subsec_nanos());

         sleep_time = to_milisec(sleep_duration);
         context.sleep_time = context.sleep_time * 0.98 + sleep_time * 0.02;

         thread::sleep(sleep_duration);
      }
   }

   let was_alive = IS_TINY_CONTEXT_ALIVE.swap(false, Ordering::Relaxed);
   assert!(was_alive);
   Ok(())
}

#[cfg(test)]
mod tests {
   #[test]
   fn it_works() {
   }
}
<|endoftext|>


<commit_before>use byteorder::{LittleEndian, ReadBytesExt};
use serde_json;
use std::ffi::OsStr;
use std::io::{BufReader, ErrorKind as IoErrorKind, Read, Result as IoResult};
use std::process::{Child, Command, Stdio};
use super::{AudioSource, AudioType, DcaError, DcaMetadata, VoiceError};
use internal::prelude::*;

use std::fs::File;
use std::result::Result as StdResult;

struct ChildContainer(Child);

impl Read for ChildContainer {
    fn read(&mut self, buffer: &mut [u8]) -> IoResult<usize> {
        self.0.stdout.as_mut().unwrap().read(buffer)
    }
}

struct InputSource<R: Read + Send + 'static> {
    stereo: bool,
    reader: R,
    kind: AudioType,
}

impl<R: Read + Send> AudioSource for InputSource<R> {
    fn is_stereo(&mut self) -> bool { self.stereo }

    fn get_type(&self) -> AudioType { self.kind.clone() }

    fn read_pcm_frame(&mut self, buffer: &mut [i16]) -> Option<usize> {
        for (i, v) in buffer.iter_mut().enumerate() {
            *v = match self.reader.read_i16::<LittleEndian>() {
                Ok(v) => v,
                Err(ref e) => {
                    return if e.kind() == IoErrorKind::UnexpectedEof {
                        Some(i)
                    } else {
                        None
                    }
                },
            }
        }

        Some(buffer.len())
    }

    fn read_opus_frame(&mut self) -> Option<Vec<u8>> {
        match self.reader.read_i16::<LittleEndian>() {
            Ok(size) => {
                if size <= 0 {
                    warn!("Invalid opus frame size: {}", size);
                    return None;
                }

                let mut frame = Vec::with_capacity(size as usize);

                {
                    let reader = self.reader.by_ref();

                    if reader.take(size as u64).read_to_end(&mut frame).is_err() {
                        return None;
                    }
                }

                Some(frame)
            },
            Err(ref e) => {
                if e.kind() == IoErrorKind::UnexpectedEof {
                    Some(Vec::new())
                } else {
                    None
                }
            },
        }
    }
}

/// Opens an audio file through `ffmpeg` and creates an audio source.
pub fn ffmpeg<P: AsRef<OsStr>>(path: P) -> Result<Box<AudioSource>> {
    let path = path.as_ref();

    // Will fail if the path is not to a file on the fs. Likely a YouTube URI.
    let is_stereo = is_stereo(path).unwrap_or(false);
    let stereo_val = if is_stereo { "2" } else { "1" };

    let args = [
        "-f",
        "s16le",
        "-ac",
        stereo_val,
        "-ar",
        "48000",
        "-acodec",
        "pcm_s16le",
        "-",
    ];

    let command = Command::new("ffmpeg")
        .arg("-i")
        .arg(path)
        .args(&args)
        .stderr(Stdio::null())
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    Ok(pcm(is_stereo, ChildContainer(command)))
}

/// Creates a streamed audio source from a DCA file.
/// Currently only accepts the DCA1 format.
pub fn dca<P: AsRef<OsStr>>(path: P) -> StdResult<Box<AudioSource>, DcaError> {
    let file = File::open(path.as_ref()).map_err(DcaError::IoError)?;

    let mut reader = BufReader::new(file);

    let mut header = [0u8; 4];

    // Read in the magic number to verify it's a DCA file.
    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    if header != b"DCA1"[..] {
        return Err(DcaError::InvalidHeader);
    }

    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    let size = (&header[..]).read_i32::<LittleEndian>().unwrap();

    // Sanity check
    if size < 2 {
        return Err(DcaError::InvalidSize(size));
    }

    let mut raw_json = Vec::with_capacity(size as usize);

    {
        let json_reader = reader.by_ref();
        json_reader
            .take(size as u64)
            .read_to_end(&mut raw_json)
            .map_err(DcaError::IoError)?;
    }

    let metadata = serde_json::from_slice::<DcaMetadata>(raw_json.as_slice())
        .map_err(DcaError::InvalidMetadata)?;

    Ok(opus(metadata.is_stereo(), reader))
}

/// Creates an Opus audio source.
pub fn opus<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader: reader,
        kind: AudioType::Opus,
    })
}

/// Creates a PCM audio source.
pub fn pcm<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader: reader,
        kind: AudioType::Pcm,
    })
}

/// Creates a streamed audio source with `youtube-dl` and `ffmpeg`.
pub fn ytdl(uri: &str) -> Result<Box<AudioSource>> {
    let args = [
        "-f",
        "webm[abr>0]/bestaudio/best",
        "--no-playlist",
        "--print-json",
        "--skip-download",
        uri,
    ];

    let out = Command::new("youtube-dl")
        .args(&args)
        .stdin(Stdio::null())
        .output()?;

    if !out.status.success() {
        return Err(Error::Voice(VoiceError::YouTubeDLRun(out)));
    }

    let value = serde_json::from_reader(&out.stdout[..])?;
    let mut obj = match value {
        Value::Object(obj) => obj,
        other => return Err(Error::Voice(VoiceError::YouTubeDLProcessing(other))),
    };

    let uri = match obj.remove("url") {
        Some(v) => {
            match v {
                Value::String(uri) => uri,
                other => return Err(Error::Voice(VoiceError::YouTubeDLUrl(other))),
            }
        },
        None => return Err(Error::Voice(VoiceError::YouTubeDLUrl(Value::Object(obj)))),
    };

    ffmpeg(&uri)
}

fn is_stereo(path: &OsStr) -> Result<bool> {
    let args = ["-v", "quiet", "-of", "json", "-show-streams", "-i"];

    let out = Command::new("ffprobe")
        .args(&args)
        .arg(path)
        .stdin(Stdio::null())
        .output()?;

    let value: Value = serde_json::from_reader(&out.stdout[..])?;

    let streams = value
        .as_object()
        .and_then(|m| m.get("streams"))
        .and_then(|v| v.as_array())
        .ok_or(Error::Voice(VoiceError::Streams))?;

    let check = streams.iter().any(|stream| {
        let channels = stream.as_object().and_then(|m| {
            m.get("channels").and_then(|v| v.as_i64())
        });

        channels == Some(2)
    });

    Ok(check)
}
<commit_msg>Split frame reading for PCM and Opus<commit_after>use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use serde_json;
use std::ffi::OsStr;
use std::io::{BufReader, ErrorKind as IoErrorKind, Read, Result as IoResult};
use std::process::{Child, Command, Stdio};
use super::{AudioSource, AudioType, DcaError, DcaMetadata, VoiceError};
use internal::prelude::*;

use std::fs::File;
use std::result::Result as StdResult;

struct ChildContainer(Child);

impl Read for ChildContainer {
    fn read(&mut self, buffer: &mut [u8]) -> IoResult<usize> {
        self.0.stdout.as_mut().unwrap().read(buffer)
    }
}

struct InputSource<R: Read + Send + 'static> {
    stereo: bool,
    reader: R,
    kind: AudioType,
}

impl<R: Read + Send> AudioSource for InputSource<R> {
    fn is_stereo(&mut self) -> bool { self.stereo }

    fn get_type(&self) -> AudioType { self.kind.clone() }

    fn read_pcm_frame(&mut self, buffer: &mut [i16]) -> Option<usize> {
        for (i, v) in buffer.iter_mut().enumerate() {
            *v = match self.reader.read_i16::<LittleEndian>() {
                Ok(v) => v,
                Err(ref e) => {
                    return if e.kind() == IoErrorKind::UnexpectedEof {
                        Some(i)
                    } else {
                        None
                    }
                },
            }
        }

        Some(buffer.len())
    }

    fn read_opus_frame(&mut self) -> Option<Vec<u8>> {
        match self.reader.read_i16::<LittleEndian>() {
            Ok(size) => {
                if size <= 0 {
                    warn!("Invalid opus frame size: {}", size);
                    return None;
                }

                let mut frame = Vec::with_capacity(size as usize);

                {
                    let reader = self.reader.by_ref();

                    if reader.take(size as u64).read_to_end(&mut frame).is_err() {
                        return None;
                    }
                }

                Some(frame)
            },
            Err(ref e) => {
                if e.kind() == IoErrorKind::UnexpectedEof {
                    Some(Vec::new())
                } else {
                    None
                }
            },
        }
    }
}

/// Opens an audio file through `ffmpeg` and creates an audio source.
pub fn ffmpeg<P: AsRef<OsStr>>(path: P) -> Result<Box<AudioSource>> {
    let path = path.as_ref();

    // Will fail if the path is not to a file on the fs. Likely a YouTube URI.
    let is_stereo = is_stereo(path).unwrap_or(false);
    let stereo_val = if is_stereo { "2" } else { "1" };

    let args = [
        "-f",
        "s16le",
        "-ac",
        stereo_val,
        "-ar",
        "48000",
        "-acodec",
        "pcm_s16le",
        "-",
    ];

    let command = Command::new("ffmpeg")
        .arg("-i")
        .arg(path)
        .args(&args)
        .stderr(Stdio::null())
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    Ok(pcm(is_stereo, ChildContainer(command)))
}

/// Creates a streamed audio source from a DCA file.
/// Currently only accepts the DCA1 format.
pub fn dca<P: AsRef<OsStr>>(path: P) -> StdResult<Box<AudioSource>, DcaError> {
    let file = File::open(path.as_ref()).map_err(DcaError::IoError)?;

    let mut reader = BufReader::new(file);

    let mut header = [0u8; 4];

    // Read in the magic number to verify it's a DCA file.
    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    if header != b"DCA1"[..] {
        return Err(DcaError::InvalidHeader);
    }

    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    let size = (&header[..]).read_i32::<LittleEndian>().unwrap();

    // Sanity check
    if size < 2 {
        return Err(DcaError::InvalidSize(size));
    }

    let mut raw_json = Vec::with_capacity(size as usize);

    {
        let json_reader = reader.by_ref();
        json_reader
            .take(size as u64)
            .read_to_end(&mut raw_json)
            .map_err(DcaError::IoError)?;
    }

    let metadata = serde_json::from_slice::<DcaMetadata>(raw_json.as_slice())
        .map_err(DcaError::InvalidMetadata)?;

    Ok(opus(metadata.is_stereo(), reader))
}

/// Creates an Opus audio source.
pub fn opus<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader: reader,
        kind: AudioType::Opus,
    })
}

/// Creates a PCM audio source.
pub fn pcm<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader: reader,
        kind: AudioType::Pcm,
    })
}

/// Creates a streamed audio source with `youtube-dl` and `ffmpeg`.
pub fn ytdl(uri: &str) -> Result<Box<AudioSource>> {
    let args = [
        "-f",
        "webm[abr>0]/bestaudio/best",
        "--no-playlist",
        "--print-json",
        "--skip-download",
        uri,
    ];

    let out = Command::new("youtube-dl")
        .args(&args)
        .stdin(Stdio::null())
        .output()?;

    if !out.status.success() {
        return Err(Error::Voice(VoiceError::YouTubeDLRun(out)));
    }

    let value = serde_json::from_reader(&out.stdout[..])?;
    let mut obj = match value {
        Value::Object(obj) => obj,
        other => return Err(Error::Voice(VoiceError::YouTubeDLProcessing(other))),
    };

    let uri = match obj.remove("url") {
        Some(v) => {
            match v {
                Value::String(uri) => uri,
                other => return Err(Error::Voice(VoiceError::YouTubeDLUrl(other))),
            }
        },
        None => return Err(Error::Voice(VoiceError::YouTubeDLUrl(Value::Object(obj)))),
    };

    ffmpeg(&uri)
}

fn is_stereo(path: &OsStr) -> Result<bool> {
    let args = ["-v", "quiet", "-of", "json", "-show-streams", "-i"];

    let out = Command::new("ffprobe")
        .args(&args)
        .arg(path)
        .stdin(Stdio::null())
        .output()?;

    let value: Value = serde_json::from_reader(&out.stdout[..])?;

    let streams = value
        .as_object()
        .and_then(|m| m.get("streams"))
        .and_then(|v| v.as_array())
        .ok_or(Error::Voice(VoiceError::Streams))?;

    let check = streams.iter().any(|stream| {
        let channels = stream.as_object().and_then(|m| {
            m.get("channels").and_then(|v| v.as_i64())
        });

        channels == Some(2)
    });

    Ok(check)
}
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::path::Path;
use std::borrow::Borrow;
use std::ops::Deref;

use semver::Version;
use std::fmt::{Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;

use error::{StoreError as SE, StoreErrorKind as SEK};
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId(PathBuf);

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        self.0
    }

}

impl Deref for StoreId {
    type Target = PathBuf;

    fn deref(&self) -> &PathBuf {
        &self.0
    }

}

impl From<PathBuf> for StoreId {

    fn from(pb: PathBuf) -> StoreId {
        StoreId(pb)
    }

}

impl From<String> for StoreId {

    fn from(string: String) -> StoreId {
        StoreId(string.into())
    }

}

impl AsRef<Path> for StoreId {

    fn as_ref(&self) -> &Path {
        self.0.as_ref()
    }

}

impl Borrow<Path> for StoreId {

    fn borrow(&self) -> &Path {
        self.0.borrow()
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        StoreId(self)
    }
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> StoreId {
        self
    }
}

pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
    debug!("Checking path element for version");
    if path_elem.split('~').last().map_or(false, |v| Version::parse(v).is_err()) {
        debug!("Version cannot be parsed from {:?}", path_elem);
        debug!("Path does not contain version!");
        return Err(SE::new(SEK::StorePathLacksVersion, None));
    }
    debug!("Version checking succeeded");

    debug!("Building path from {:?}", path_elem);
    let mut path = store.path().clone();

    if path_elem.starts_with('/') {
        path.push(&path_elem[1..]);
    } else {
        path.push(path_elem);
    }

    Ok(path)
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> $crate::storeid::StoreId {
                    StoreId::from(self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
    }

}
<commit_msg>Use error.into() instead of building full type<commit_after>use std::path::PathBuf;
use std::path::Path;
use std::borrow::Borrow;
use std::ops::Deref;

use semver::Version;
use std::fmt::{Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;

use error::StoreErrorKind as SEK;
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId(PathBuf);

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        self.0
    }

}

impl Deref for StoreId {
    type Target = PathBuf;

    fn deref(&self) -> &PathBuf {
        &self.0
    }

}

impl From<PathBuf> for StoreId {

    fn from(pb: PathBuf) -> StoreId {
        StoreId(pb)
    }

}

impl From<String> for StoreId {

    fn from(string: String) -> StoreId {
        StoreId(string.into())
    }

}

impl AsRef<Path> for StoreId {

    fn as_ref(&self) -> &Path {
        self.0.as_ref()
    }

}

impl Borrow<Path> for StoreId {

    fn borrow(&self) -> &Path {
        self.0.borrow()
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        StoreId(self)
    }
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> StoreId {
        self
    }
}

pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
    debug!("Checking path element for version");
    if path_elem.split('~').last().map_or(false, |v| Version::parse(v).is_err()) {
        debug!("Version cannot be parsed from {:?}", path_elem);
        debug!("Path does not contain version!");
        return Err(SEK::StorePathLacksVersion.into());
    }
    debug!("Version checking succeeded");

    debug!("Building path from {:?}", path_elem);
    let mut path = store.path().clone();

    if path_elem.starts_with('/') {
        path.push(&path_elem[1..]);
    } else {
        path.push(path_elem);
    }

    Ok(path)
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> $crate::storeid::StoreId {
                    StoreId::from(self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
    }

}
<|endoftext|>


<commit_before>static CONST1: i32 = 20091;
static CONST2: i32 = 35468;

pub fn idct4x4(block: &mut [i32]) {
    for i in 0usize..4 {
        let a1 = block[i] + block[8 + i];
        let b1 = block[i] - block[8 + i];

        let t1 = (block[4 + i] * CONST2) >> 16;
        let t2 = block[12 + i] + ((block[12 + i] * CONST1) >> 16);
        let c1 = t1 - t2;

        let t1 = block[4 + i] + ((block[4 + i] * CONST1) >> 16);
        let t2 = (block[12 + i] * CONST2) >> 16;
        let d1 = t1 + t2;

        block[i] = a1 + d1;
        block[4 + i] = b1 + c1;
        block[4 * 3 + i] = a1 - d1;
        block[4 * 2 + i] = b1 - c1;
    }

    for i in 0usize..4 {
        let a1 = block[4 * i] + block[4 * i + 2];
        let b1 = block[4 * i] - block[4 * i + 2];

        let t1 = (block[4 * i + 1] * CONST2) >> 16;
        let t2 = block[4 * i + 3] + ((block[4 * i + 3] * CONST1) >> 16);
        let c1 = t1 - t2;

        let t1 = block[4 * i + 1] + ((block[4 * i + 1] * CONST1) >> 16);
        let t2 = (block[4 * i + 3] * CONST2) >> 16;
        let d1 = t1 + t2;

        block[4 * i] = (a1 + d1 + 4) >> 3;
        block[4 * i + 3] = (a1 - d1 + 4) >> 3;
        block[4 * i + 1] = (b1 + c1 + 4) >> 3;
        block[4 * i + 2] = (b1 - c1 + 4) >> 3;
    }
}

// 14.3
pub fn iwht4x4(block: &mut [i32]) {
    for i in 0usize..4 {
        let a1 = block[i] + block[12 + i];
        let b1 = block[4 + i] + block[8 + i];
        let c1 = block[4 + i] - block[8 + i];
        let d1 = block[i] - block[12 + i];

        block[i] = a1 + b1;
        block[4 + i] = c1 + d1;
        block[8 + i] = a1 - b1;
        block[12 + i] = d1 - c1;
    }

    for i in 0usize..4 {
        let a1 = block[4 * i] + block[4 * i + 3];
        let b1 = block[4 * i + 1] + block[4 * i + 2];
        let c1 = block[4 * i + 1] - block[4 * i + 2];
        let d1 = block[4 * i] - block[4 * i + 3];

        let a2 = a1 + b1;
        let b2 = c1 + d1;
        let c2 = a1 - b1;
        let d2 = d1 - c1;

        block[4 * i] = (a2 + 3) >> 3;
        block[4 * i + 1] = (b2 + 3) >> 3;
        block[4 * i + 2] = (c2 + 3) >> 3;
        block[4 * i + 3] = (d2 + 3) >> 3;
    }
}
<commit_msg>Fix intermediate transformation math types<commit_after>static CONST1: i64 = 20091;
static CONST2: i64 = 35468;

pub fn idct4x4(block: &mut [i32]) {
    // The intermediate results may overflow the types, so we stretch the type.
    fn fetch(block: &mut [i32], idx: usize) -> i64 {
        i64::from(block[idx])
    }

    for i in 0usize..4 {
        let a1 = fetch(block, i) + fetch(block, 8 + i);
        let b1 = fetch(block, i) - fetch(block, 8 + i);

        let t1 = (fetch(block, 4 + i) * CONST2) >> 16;
        let t2 = fetch(block, 12 + i) + ((fetch(block, 12 + i) * CONST1) >> 16);
        let c1 = t1 - t2;

        let t1 = fetch(block, 4 + i) + ((fetch(block, 4 + i) * CONST1) >> 16);
        let t2 = (fetch(block, 12 + i) * CONST2) >> 16;
        let d1 = t1 + t2;

        block[i] = (a1 + d1) as i32;
        block[4 + i] = (b1 + c1) as i32;
        block[4 * 3 + i] = (a1 - d1) as i32;
        block[4 * 2 + i] = (b1 - c1) as i32;
    }

    for i in 0usize..4 {
        let a1 = fetch(block, 4 * i) + fetch(block, 4 * i + 2);
        let b1 = fetch(block, 4 * i) - fetch(block, 4 * i + 2);

        let t1 = (fetch(block, 4 * i + 1) * CONST2) >> 16;
        let t2 = fetch(block, 4 * i + 3) + ((fetch(block, 4 * i + 3) * CONST1) >> 16);
        let c1 = t1 - t2;

        let t1 = fetch(block, 4 * i + 1) + ((fetch(block, 4 * i + 1) * CONST1) >> 16);
        let t2 = (fetch(block, 4 * i + 3) * CONST2) >> 16;
        let d1 = t1 + t2;

        block[4 * i] = ((a1 + d1 + 4) >> 3) as i32;
        block[4 * i + 3] = ((a1 - d1 + 4) >> 3) as i32;
        block[4 * i + 1] = ((b1 + c1 + 4) >> 3) as i32;
        block[4 * i + 2] = ((b1 - c1 + 4) >> 3) as i32;
    }
}

// 14.3
pub fn iwht4x4(block: &mut [i32]) {
    for i in 0usize..4 {
        let a1 = block[i] + block[12 + i];
        let b1 = block[4 + i] + block[8 + i];
        let c1 = block[4 + i] - block[8 + i];
        let d1 = block[i] - block[12 + i];

        block[i] = a1 + b1;
        block[4 + i] = c1 + d1;
        block[8 + i] = a1 - b1;
        block[12 + i] = d1 - c1;
    }

    for i in 0usize..4 {
        let a1 = block[4 * i] + block[4 * i + 3];
        let b1 = block[4 * i + 1] + block[4 * i + 2];
        let c1 = block[4 * i + 1] - block[4 * i + 2];
        let d1 = block[4 * i] - block[4 * i + 3];

        let a2 = a1 + b1;
        let b2 = c1 + d1;
        let c2 = a1 - b1;
        let d2 = d1 - c1;

        block[4 * i] = (a2 + 3) >> 3;
        block[4 * i + 1] = (b2 + 3) >> 3;
        block[4 * i + 2] = (c2 + 3) >> 3;
        block[4 * i + 3] = (d2 + 3) >> 3;
    }
}
<|endoftext|>