<commit_before>use rustbox;
use yoga;
use yoga_wrapper;

use measurer;

pub struct Builder {
    measurer: measurer::Measurer,
}

impl Builder {
    pub fn new() -> Self {
        Builder { measurer: measurer::Measurer {} }
    }
}

impl<'meas> yoga::Builds<'meas, rustbox::Color> for Builder {
    fn create_context<'text>(&'meas self, text: &'text str) -> yoga_wrapper::Context<'text, 'meas> {
        yoga_wrapper::Context::new(text, &self.measurer)
    }

    fn view<'r>(&self) -> yoga::View<'r, rustbox::Color> {
        yoga::View::new()
    }

    fn text<'t, 'a: 't>(&'a self, text: &'t str) -> yoga::Text<'t, rustbox::Color> {
        yoga::Text::new(text, &mut self.create_context(text))
    }
}
<commit_msg>fix(Builder): return box; fix lifetimes<commit_after>use rustbox;
use yoga;
use yoga_wrapper;

use measurer;

pub struct Builder {
    measurer: measurer::Measurer,
}

impl Builder {
    pub fn new() -> Self {
        Builder { measurer: measurer::Measurer {} }
    }
}

impl<'meas> yoga::Builds<'meas, rustbox::Color> for Builder {
    fn create_context<'text>(&'meas self,
                             text: &'text str)
                             -> Box<yoga_wrapper::Context<'text, 'meas>> {
        Box::new(yoga_wrapper::Context::new(text, &self.measurer))
    }

    fn view<'r>(&self) -> yoga::View<'r, rustbox::Color> {
        yoga::View::new()
    }

    fn text<'text>(&'meas self, text: &'text str) -> yoga::Text<'text, 'meas, rustbox::Color> {
        yoga::Text::new(text, self.create_context(text))
    }
}
<|endoftext|>


<commit_before>
use std::collections;
use serialize::json::{self, ToJson};

use helpers;
use param;

use coercers;
use validation;

use ValicoResult;

pub struct Builder {
    requires: Vec<param::Param>,
    optional: Vec<param::Param>,
    validators: Vec<Box<validation::MultipleParamValidator + Send + Sync>>
}

unsafe impl Send for Builder { }

impl Builder {

    pub fn new() -> Builder {
        Builder {
            requires: vec![],
            optional: vec![],
            validators: vec![]
        }
    }

    pub fn build<F>(rules: F) -> Builder where F: FnOnce(&mut Builder) {
        let mut builder = Builder::new();
        rules(&mut builder);

        builder
    }

    pub fn req_defined(&mut self, name: &str) {
        let params = param::Param::new(name);
        self.requires.push(params);
    }

    pub fn req_typed(&mut self, name: &str, coercer: Box<coercers::Coercer + Send + Sync>) {
        let params = param::Param::new_with_coercer(name, coercer);
        self.requires.push(params);
    }

    pub fn req_nested<F>(&mut self, name: &str, coercer: Box<coercers::Coercer + Send + Sync>, nest_def: F) where F: FnOnce(&mut Builder) {
        let nest_builder = Builder::build(nest_def);
        let params = param::Param::new_with_nest(name, coercer, nest_builder);
        self.requires.push(params);
    }

    pub fn req<F>(&mut self, name: &str, param_builder: F) where F: FnOnce(&mut param::Param) {
        let params = param::Param::build(name, param_builder);
        self.requires.push(params);
    }

    pub fn opt_defined(&mut self, name: &str) {
        let params = param::Param::new(name);
        self.optional.push(params);
    }

    pub fn opt_typed(&mut self, name: &str, coercer: Box<coercers::Coercer + Send + Sync>) {
        let params = param::Param::new_with_coercer(name, coercer);
        self.optional.push(params);
    }

    pub fn opt_nested<F>(&mut self, name: &str, coercer: Box<coercers::Coercer + Send + Sync>, nest_def: F) where F: FnOnce(&mut Builder) {
        let nest_builder = Builder::build(nest_def);
        let params = param::Param::new_with_nest(name, coercer, nest_builder);
        self.optional.push(params);
    }

    pub fn opt<F>(&mut self, name: &str, param_builder: F) where F: FnOnce(&mut param::Param) {
        let params = param::Param::build(name, param_builder);
        self.optional.push(params);
    }

    pub fn validate(&mut self, validator: Box<validation::MutuallyExclusiveValidator>) {
        self.validators.push(validator);
    }

    pub fn validate_with(&mut self, validator: fn(&json::Object) -> Result<(), String>) {
        self.validators.push(Box::new(validation::FunctionMultipleValidator::new(validator)));
    }

    pub fn mutually_exclusive(&mut self, params: &[&str]) {
        let validator = Box::new(validation::MutuallyExclusiveValidator::new(params));
        self.validators.push(validator);
    }

    pub fn exactly_one_of(&mut self, params: &[&str]) {
        let validator = Box::new(validation::ExactlyOneOfValidator::new(params));
        self.validators.push(validator);
    }

    pub fn at_least_one_of(&mut self, params: &[&str]) {
        let validator = Box::new(validation::AtLeastOneOfValidator::new(params));
        self.validators.push(validator);
    }

    pub fn process(&self, tree: &mut json::Object) -> ValicoResult<()>  {

        let mut errors = collections::BTreeMap::new();

        for param in self.requires.iter() {
            let ref name = param.name;
            let present = helpers::has_value(tree, name);
            if present {
                match param.process(tree.get_mut(name).unwrap()) {
                    Ok(result) => {
                        match result {
                            Some(new_value) => { tree.insert(name.clone(), new_value); },
                            None => ()
                        }
                    },
                    Err(err) => {
                        errors.insert(name.to_string(), err.to_json());
                    }
                }
            } else {
                errors.insert(name.to_string(), helpers::validation_error("Field is required".to_string()).to_json());
            }
        }

        for param in self.optional.iter() {
            let ref name = param.name;
            let present = helpers::has_value(tree, name);
            if present {
                match param.process(tree.get_mut(name).unwrap()) {
                    Ok(result) => {
                        match result {
                            Some(new_value) => { tree.insert(name.clone(), new_value); },
                            None => ()
                        }
                    },
                    Err(err) => {
                        errors.insert(name.to_string(), err.to_json());
                    }
                }
            }
        }

        let mut i = 0us;
        for validator in self.validators.iter() {
            match validator.validate(tree) {
                Ok(()) => (),
                Err(err) => {
                    errors.insert(format!("$${}", i.to_string()), err.to_json());
                    i = i + 1;
                }
            };
        }

        if errors.len() == 0 {
            // second pass we need to validate without default values in optionals
            for param in self.optional.iter() {
                let ref name = param.name;
                let present = helpers::has_value(tree, name);
                if !present {
                    match param.default.as_ref() {
                        Some(val) => { tree.insert(name.clone(), val.clone()); },
                        None => ()
                    };
                }
            }

            Ok(())
        } else {
            Err(errors)
        }
    }
}

<commit_msg>feat(builder): expose getters<commit_after>
use std::collections;
use serialize::json::{self, ToJson};

use helpers;
use param;

use coercers;
use validation;

use ValicoResult;

pub struct Builder {
    requires: Vec<param::Param>,
    optional: Vec<param::Param>,
    validators: Vec<Box<validation::MultipleParamValidator + Send + Sync>>
}

unsafe impl Send for Builder { }

impl Builder {

    pub fn new() -> Builder {
        Builder {
            requires: vec![],
            optional: vec![],
            validators: vec![]
        }
    }

    pub fn build<F>(rules: F) -> Builder where F: FnOnce(&mut Builder) {
        let mut builder = Builder::new();
        rules(&mut builder);

        builder
    }

    pub fn get_required(&self) -> &Vec<param::Param> {
        return &self.requires;
    }

    pub fn get_optional(&self) -> &Vec<param::Param> {
        return &self.optional;
    }

    pub fn get_validators(&self) -> &Vec<Box<validation::MultipleParamValidator + Send + Sync>> {
        return &self.validators;
    }

    pub fn req_defined(&mut self, name: &str) {
        let params = param::Param::new(name);
        self.requires.push(params);
    }

    pub fn req_typed(&mut self, name: &str, coercer: Box<coercers::Coercer + Send + Sync>) {
        let params = param::Param::new_with_coercer(name, coercer);
        self.requires.push(params);
    }

    pub fn req_nested<F>(&mut self, name: &str, coercer: Box<coercers::Coercer + Send + Sync>, nest_def: F) where F: FnOnce(&mut Builder) {
        let nest_builder = Builder::build(nest_def);
        let params = param::Param::new_with_nest(name, coercer, nest_builder);
        self.requires.push(params);
    }

    pub fn req<F>(&mut self, name: &str, param_builder: F) where F: FnOnce(&mut param::Param) {
        let params = param::Param::build(name, param_builder);
        self.requires.push(params);
    }

    pub fn opt_defined(&mut self, name: &str) {
        let params = param::Param::new(name);
        self.optional.push(params);
    }

    pub fn opt_typed(&mut self, name: &str, coercer: Box<coercers::Coercer + Send + Sync>) {
        let params = param::Param::new_with_coercer(name, coercer);
        self.optional.push(params);
    }

    pub fn opt_nested<F>(&mut self, name: &str, coercer: Box<coercers::Coercer + Send + Sync>, nest_def: F) where F: FnOnce(&mut Builder) {
        let nest_builder = Builder::build(nest_def);
        let params = param::Param::new_with_nest(name, coercer, nest_builder);
        self.optional.push(params);
    }

    pub fn opt<F>(&mut self, name: &str, param_builder: F) where F: FnOnce(&mut param::Param) {
        let params = param::Param::build(name, param_builder);
        self.optional.push(params);
    }

    pub fn validate(&mut self, validator: Box<validation::MutuallyExclusiveValidator>) {
        self.validators.push(validator);
    }

    pub fn validate_with(&mut self, validator: fn(&json::Object) -> Result<(), String>) {
        self.validators.push(Box::new(validation::FunctionMultipleValidator::new(validator)));
    }

    pub fn mutually_exclusive(&mut self, params: &[&str]) {
        let validator = Box::new(validation::MutuallyExclusiveValidator::new(params));
        self.validators.push(validator);
    }

    pub fn exactly_one_of(&mut self, params: &[&str]) {
        let validator = Box::new(validation::ExactlyOneOfValidator::new(params));
        self.validators.push(validator);
    }

    pub fn at_least_one_of(&mut self, params: &[&str]) {
        let validator = Box::new(validation::AtLeastOneOfValidator::new(params));
        self.validators.push(validator);
    }

    pub fn process(&self, tree: &mut json::Object) -> ValicoResult<()>  {

        let mut errors = collections::BTreeMap::new();

        for param in self.requires.iter() {
            let ref name = param.name;
            let present = helpers::has_value(tree, name);
            if present {
                match param.process(tree.get_mut(name).unwrap()) {
                    Ok(result) => {
                        match result {
                            Some(new_value) => { tree.insert(name.clone(), new_value); },
                            None => ()
                        }
                    },
                    Err(err) => {
                        errors.insert(name.to_string(), err.to_json());
                    }
                }
            } else {
                errors.insert(name.to_string(), helpers::validation_error("Field is required".to_string()).to_json());
            }
        }

        for param in self.optional.iter() {
            let ref name = param.name;
            let present = helpers::has_value(tree, name);
            if present {
                match param.process(tree.get_mut(name).unwrap()) {
                    Ok(result) => {
                        match result {
                            Some(new_value) => { tree.insert(name.clone(), new_value); },
                            None => ()
                        }
                    },
                    Err(err) => {
                        errors.insert(name.to_string(), err.to_json());
                    }
                }
            }
        }

        let mut i = 0us;
        for validator in self.validators.iter() {
            match validator.validate(tree) {
                Ok(()) => (),
                Err(err) => {
                    errors.insert(format!("$${}", i.to_string()), err.to_json());
                    i = i + 1;
                }
            };
        }

        if errors.len() == 0 {
            // second pass we need to validate without default values in optionals
            for param in self.optional.iter() {
                let ref name = param.name;
                let present = helpers::has_value(tree, name);
                if !present {
                    match param.default.as_ref() {
                        Some(val) => { tree.insert(name.clone(), val.clone()); },
                        None => ()
                    };
                }
            }

            Ok(())
        } else {
            Err(errors)
        }
    }
}

<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate hyper;

mod spaceapi;

use std::io::Write;
use std::net::Ipv4Addr;

use rustc_serialize::json;
use hyper::Server;
use hyper::server::Request;
use hyper::server::Response;
use hyper::net::Fresh;

fn build_response_json() -> String {

    let status = spaceapi::Status {
        api: "0.13".to_string(),
        space: "coredump".to_string(),
        logo: "https://www.coredump.ch/logo.png".to_string(),
        url: "https://www.coredump.ch/".to_string(),
        location: spaceapi::Location {
            address: "Spinnereistrasse 2, 8640 Rapperswil, Switzerland".to_string(),
            lat: 47.22936,
            lon: 8.82949,
        },
        spacefed: spaceapi::SpaceFED {
            spacenet: false,
            spacesaml: false,
            spacephone: false,
        },
        state: spaceapi::State {
            open: false,
            message: "Open every Monday from 20:00".to_string(),
        },
        contact: spaceapi::Contact {
            irc: "irc://freenode.net/#coredump".to_string(),
            twitter: "@coredump_ch".to_string(),
            foursquare: "525c20e5498e875d8231b1e5".to_string(),
            email: "danilo@coredump.ch".to_string(),
        },
        issue_report_channels: ["email", "twitter"],
        feeds: spaceapi::Feeds {
            blog: spaceapi::Feed {
                _type: "rss".to_string(),
                url: "https://www.coredump.ch/feed/".to_string(),
            },
        },
        projects: [
            "https://www.coredump.ch/projekte/",
            "https://discourse.coredump.ch/c/projects",
            "https://github.com/coredump-ch/"
        ]
    };
    json::encode(&status).unwrap()
}

fn status_endpoint(_: Request, res: Response<Fresh>) {
    let mut res = res.start().unwrap();
    let response_body = build_response_json();
    res.write_all(response_body.as_bytes()).unwrap();
    res.end().unwrap();
}

fn main() {
    let ip = Ipv4Addr::new(127, 0, 0, 1);
    let port = 3000;

    println!("Starting HTTP server on {}:{}...", ip, port);
    Server::http(status_endpoint).listen((ip, port)).unwrap();
}
<commit_msg>Read port from PORT env var<commit_after>extern crate rustc_serialize;
extern crate hyper;

mod spaceapi;

use std::io::Write;
use std::net::Ipv4Addr;
use std::env;

use rustc_serialize::json;
use hyper::Server;
use hyper::server::Request;
use hyper::server::Response;
use hyper::net::Fresh;

fn build_response_json() -> String {

    let status = spaceapi::Status {
        api: "0.13".to_string(),
        space: "coredump".to_string(),
        logo: "https://www.coredump.ch/logo.png".to_string(),
        url: "https://www.coredump.ch/".to_string(),
        location: spaceapi::Location {
            address: "Spinnereistrasse 2, 8640 Rapperswil, Switzerland".to_string(),
            lat: 47.22936,
            lon: 8.82949,
        },
        spacefed: spaceapi::SpaceFED {
            spacenet: false,
            spacesaml: false,
            spacephone: false,
        },
        state: spaceapi::State {
            open: false,
            message: "Open every Monday from 20:00".to_string(),
        },
        contact: spaceapi::Contact {
            irc: "irc://freenode.net/#coredump".to_string(),
            twitter: "@coredump_ch".to_string(),
            foursquare: "525c20e5498e875d8231b1e5".to_string(),
            email: "danilo@coredump.ch".to_string(),
        },
        issue_report_channels: ["email", "twitter"],
        feeds: spaceapi::Feeds {
            blog: spaceapi::Feed {
                _type: "rss".to_string(),
                url: "https://www.coredump.ch/feed/".to_string(),
            },
        },
        projects: [
            "https://www.coredump.ch/projekte/",
            "https://discourse.coredump.ch/c/projects",
            "https://github.com/coredump-ch/"
        ]
    };
    json::encode(&status).unwrap()
}

fn status_endpoint(_: Request, res: Response<Fresh>) {
    let mut res = res.start().unwrap();
    let response_body = build_response_json();
    res.write_all(response_body.as_bytes()).unwrap();
    res.end().unwrap();
}

fn main() {
    let ip = Ipv4Addr::new(127, 0, 0, 1);
    let port : u16 = match env::var("PORT") {
        Ok(val) => match val.parse::<u16>() {
            Ok(val) => val,
            Err(_) => 3000
        },
        Err(_) => 3000
    };

    println!("Starting HTTP server on {}:{}...", ip, port);
    Server::http(status_endpoint).listen((ip, port)).unwrap();
}
<|endoftext|>


<commit_before>use clap::{App, Arg, ArgMatches, SubCommand};

use tools::TEMPLATE_SUBCMD;

pub const NAME: &'static str = "gff-to-refflat";

pub fn build_cli<'a, 'b>() -> App<'a, 'b> {
    SubCommand::with_name(NAME)
        .about("Converts from the GTF or GFF3 format to refFlat")
        .template(TEMPLATE_SUBCMD)
        .arg(Arg::with_name("input")
                .value_name("input")
                .help("Path to input annotation file or '-' for stdin")
                .takes_value(true)
                .required(true))
        .arg(Arg::with_name("output")
                .value_name("output")
                .help("Path to output annotation file or '-' for stdout")
                .takes_value(true)
                .required(true))
}

pub fn run(args: &ArgMatches) -> ::Result<()> {
    unimplemented!()
}
<commit_msg>Implement gff-to-refflat subcommand<commit_after>use std::io::{self, Write};

use clap::{App, Arg, ArgMatches, SubCommand};
use gte::{GffReader, RefFlatWriter};

use tools::TEMPLATE_SUBCMD;
use utils;

pub const NAME: &'static str = "gff-to-refflat";

pub fn build_cli<'a, 'b>() -> App<'a, 'b> {
    SubCommand::with_name(NAME)
        .about("Converts from the GTF or GFF3 format to refFlat")
        .template(TEMPLATE_SUBCMD)
        .arg(Arg::with_name("input")
                .required(true)
                .takes_value(true)
                .help("Path to input annotation file or '-' for stdin"))
        .arg(Arg::with_name("output")
                .required(true)
                .takes_value(true)
                .help("Path to output annotation file or '-' for stdout"))
        .arg(Arg::with_name("gff_type")
                .short("-t")
                .long("--gff-type")
                .required(true)
                .takes_value(true)
                .value_name("TYPE")
                .possible_values(&["gff3", "gtf"])
                .display_order(1)
                .help("Input GFF variant"))
        .arg(Arg::with_name("seq_prefix")
                .long("--seq-prefix")
                .value_name("VALUE")
                .takes_value(true)
                .display_order(2)
                .help("String to prepend to all sequence names"))
        .arg(Arg::with_name("seq_lstrip")
                .long("--seq-lstrip")
                .value_name("VALUE")
                .takes_value(true)
                .display_order(3)
                .help("Left-most string to remove from all sequence names"))
        .arg(Arg::with_name("gene_id_attr")
                .long("--gid")
                .value_name("KEY")
                .default_value("gene_id")
                .takes_value(true)
                .display_order(4)
                .help("Key of GFF record attribute to use as gene identifier"))
        .arg(Arg::with_name("transcript_id_attr")
                .long("--tid")
                .value_name("KEY")
                .default_value("transcript_id")
                .display_order(5)
                .takes_value(true)
                .help("Key of GFF record attribute to use as transcript identifier"))
        .arg(Arg::with_name("loose_codons")
                .long("--loose-codons")
                .display_order(6)
                .takes_value(false)
                .long_help(
                    "If not specified, only GFF transcripts with start and stop codons will be \
                     created. If specified, GFF transcripts without start and/or stop codons \
                     will be created using the min/max coordinates of all their CDS."))
}

pub fn run(args: &ArgMatches) -> ::Result<()> {

    let gff_type = utils::resolve_gff_type(args.value_of("gff_type").unwrap())?;

    let mut reader = utils::resolve_reader(args.value_of("input").unwrap())
        .map(|r| GffReader::from_reader(r, gff_type))?;

    let mut writer = utils::resolve_writer(args.value_of("output").unwrap())
        .map(|w| RefFlatWriter::from_writer(w))?;

    let rtrxs = reader.transcripts(
        args.value_of("gene_id_attr"), args.value_of("transcript_id_attr"),
        args.value_of("seq_prefix"), args.value_of("seq_lstrip"),
        args.is_present("loose_codons"))?;

    for result in rtrxs {
        let wresult = result
            .and_then(|ref trx| writer.write_transcript(trx));
        if let Err(e) = wresult {
            let _ = writeln!(io::stderr(), "error: {}", e);
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>//! Trait definitions and type aliases.

use image::{Rgb, Rgba, Luma, Pixel, ImageBuffer};
use std::{u8, u16, i16};

/// An `ImageBuffer` containing Pixels of type P with storage `Vec<P::Subpixel>`.
/// Most operations in this library only support inputs of type `Image`, rather
/// than arbitrary `image::GenericImage`s. This is obviously less flexible, but
/// has the advantage of allowing many functions to be more performant. We may want
/// to add more flexibility later, but this should not be at the expense of performance.
/// When specialisation lands we should be able to do this by defining traits for images
/// with contiguous storage.
// TODO: This produces a compiler warning about trait bounds
// TODO: not being enforced in type definitions. In this case
// TODO: they are. Can we get rid of the warning?
pub type Image<P: Pixel> = ImageBuffer<P, Vec<<P as Pixel>::Subpixel>>;

/// Pixels which have a named Black value.
pub trait HasBlack {
    /// Returns a black pixel of this type.
    fn black() -> Self;
}

/// Pixels which have a named White value.
pub trait HasWhite {
    /// Returns a white pixel of this type.
    fn white() -> Self;
}

macro_rules! impl_black_white {
    ($for_:ty, $min:expr, $max:expr) => (
        impl HasBlack for $for_ {
            fn black() -> Self {
                $min
            }
        }

        impl HasWhite for $for_ {
            fn white() -> Self {
                $max
            }
        }
    )
}

impl_black_white!(Luma<u8>, Luma([u8::MIN]), Luma([u8::MAX]));
impl_black_white!(Luma<u16>, Luma([u16::MIN]), Luma([u16::MAX]));
impl_black_white!(Rgb<u8>, Rgb([u8::MIN; 3]), Rgb([u8::MAX; 3]));
impl_black_white!(Rgb<u16>, Rgb([u16::MIN; 3]), Rgb([u16::MAX; 3]));
impl_black_white!(Rgba<u8>, Rgba([u8::MIN, u8::MIN, u8::MIN, u8::MAX]), Rgba([u8::MAX, u8::MAX, u8::MAX, u8::MAX]));
impl_black_white!(Rgba<u16>, Rgba([u16::MIN, u16::MIN, u16::MIN, u16::MAX]), Rgba([u16::MAX, u16::MAX, u16::MAX, u16::MAX]));

/// Something with a 2d position.
pub trait Position {
    /// x-coordinate.
    fn x(&self) -> u32;
    /// y-coordinate.
    fn y(&self) -> u32;
}

/// Something with a score.
pub trait Score {
    /// Score of this item.
    fn score(&self) -> f32;
}

/// A type to which we can clamp a value of type T.
/// Implementations are not required to handle `NaN`s gracefully.
pub trait Clamp<T> {
    /// Clamp `x` to a valid value for this type.
    fn clamp(x: T) -> Self;
}

/// Creates an implementation of Clamp<From> for type To.
macro_rules! implement_clamp {
    ($from:ty, $to:ty, $min:expr, $max:expr, $min_from:expr, $max_from:expr) => (
        impl Clamp<$from> for $to {
            fn clamp(x: $from) -> $to {
                if x < $max_from as $from {
                    if x > $min_from as $from {
                        x as $to
                    } else {
                        $min
                    }
                } else {
                    $max
                }
            }
        }
    )
}

implement_clamp!(f32, u8, u8::MIN, u8::MAX, u8::MIN as f32, u8::MAX as f32);
implement_clamp!(f32, u16, u16::MIN, u16::MAX, u16::MIN as f32, u16::MAX as f32);
implement_clamp!(f64, u8, u8::MIN, u8::MAX, u8::MIN as f64, u8::MAX as f64);
implement_clamp!(f64, u16, u16::MIN, u16::MAX, u16::MIN as f64, u16::MAX as f64);
implement_clamp!(i32, u8, u8::MIN, u8::MAX, u8::MIN as i32, u8::MAX as i32);
implement_clamp!(u32, u8, u8::MIN, u8::MAX, u8::MIN as u32, u8::MAX as u32);
implement_clamp!(i32, u16, u16::MIN, u16::MAX, u16::MIN as i32, u16::MAX as i32);
implement_clamp!(i32, i16, i16::MIN, i16::MAX, i16::MIN as i32, i16::MAX as i32);
implement_clamp!(u16, u8, u8::MIN, u8::MAX, u8::MIN as u16, u8::MAX as u16);

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

    #[test]
    fn test_clamp_f32_u8() {
        let t: u8 = Clamp::clamp(255f32);
        assert_eq!(t, 255u8);
        let u: u8 = Clamp::clamp(300f32);
        assert_eq!(u, 255u8);
        let v: u8 = Clamp::clamp(0f32);
        assert_eq!(v, 0u8);
        let w: u8 = Clamp::clamp(-5f32);
        assert_eq!(w, 0u8);
    }

    #[test]
    fn test_clamp_f32_u16() {
        let t: u16 = Clamp::clamp(65535f32);
        assert_eq!(t, 65535u16);
        let u: u16 = Clamp::clamp(300000f32);
        assert_eq!(u, 65535u16);
        let v: u16 = Clamp::clamp(0f32);
        assert_eq!(v, 0u16);
        let w: u16 = Clamp::clamp(-5f32);
        assert_eq!(w, 0u16);
    }
}
<commit_msg>Fix compiler warning (#275)<commit_after>//! Trait definitions and type aliases.

use image::{Rgb, Rgba, Luma, Pixel, ImageBuffer};
use std::{u8, u16, i16};

/// An `ImageBuffer` containing Pixels of type P with storage `Vec<P::Subpixel>`.
/// Most operations in this library only support inputs of type `Image`, rather
/// than arbitrary `image::GenericImage`s. This is obviously less flexible, but
/// has the advantage of allowing many functions to be more performant. We may want
/// to add more flexibility later, but this should not be at the expense of performance.
/// When specialisation lands we should be able to do this by defining traits for images
/// with contiguous storage.
pub type Image<P> = ImageBuffer<P, Vec<<P as Pixel>::Subpixel>>;

/// Pixels which have a named Black value.
pub trait HasBlack {
    /// Returns a black pixel of this type.
    fn black() -> Self;
}

/// Pixels which have a named White value.
pub trait HasWhite {
    /// Returns a white pixel of this type.
    fn white() -> Self;
}

macro_rules! impl_black_white {
    ($for_:ty, $min:expr, $max:expr) => (
        impl HasBlack for $for_ {
            fn black() -> Self {
                $min
            }
        }

        impl HasWhite for $for_ {
            fn white() -> Self {
                $max
            }
        }
    )
}

impl_black_white!(Luma<u8>, Luma([u8::MIN]), Luma([u8::MAX]));
impl_black_white!(Luma<u16>, Luma([u16::MIN]), Luma([u16::MAX]));
impl_black_white!(Rgb<u8>, Rgb([u8::MIN; 3]), Rgb([u8::MAX; 3]));
impl_black_white!(Rgb<u16>, Rgb([u16::MIN; 3]), Rgb([u16::MAX; 3]));
impl_black_white!(Rgba<u8>, Rgba([u8::MIN, u8::MIN, u8::MIN, u8::MAX]), Rgba([u8::MAX, u8::MAX, u8::MAX, u8::MAX]));
impl_black_white!(Rgba<u16>, Rgba([u16::MIN, u16::MIN, u16::MIN, u16::MAX]), Rgba([u16::MAX, u16::MAX, u16::MAX, u16::MAX]));

/// Something with a 2d position.
pub trait Position {
    /// x-coordinate.
    fn x(&self) -> u32;
    /// y-coordinate.
    fn y(&self) -> u32;
}

/// Something with a score.
pub trait Score {
    /// Score of this item.
    fn score(&self) -> f32;
}

/// A type to which we can clamp a value of type T.
/// Implementations are not required to handle `NaN`s gracefully.
pub trait Clamp<T> {
    /// Clamp `x` to a valid value for this type.
    fn clamp(x: T) -> Self;
}

/// Creates an implementation of Clamp<From> for type To.
macro_rules! implement_clamp {
    ($from:ty, $to:ty, $min:expr, $max:expr, $min_from:expr, $max_from:expr) => (
        impl Clamp<$from> for $to {
            fn clamp(x: $from) -> $to {
                if x < $max_from as $from {
                    if x > $min_from as $from {
                        x as $to
                    } else {
                        $min
                    }
                } else {
                    $max
                }
            }
        }
    )
}

implement_clamp!(f32, u8, u8::MIN, u8::MAX, u8::MIN as f32, u8::MAX as f32);
implement_clamp!(f32, u16, u16::MIN, u16::MAX, u16::MIN as f32, u16::MAX as f32);
implement_clamp!(f64, u8, u8::MIN, u8::MAX, u8::MIN as f64, u8::MAX as f64);
implement_clamp!(f64, u16, u16::MIN, u16::MAX, u16::MIN as f64, u16::MAX as f64);
implement_clamp!(i32, u8, u8::MIN, u8::MAX, u8::MIN as i32, u8::MAX as i32);
implement_clamp!(u32, u8, u8::MIN, u8::MAX, u8::MIN as u32, u8::MAX as u32);
implement_clamp!(i32, u16, u16::MIN, u16::MAX, u16::MIN as i32, u16::MAX as i32);
implement_clamp!(i32, i16, i16::MIN, i16::MAX, i16::MIN as i32, i16::MAX as i32);
implement_clamp!(u16, u8, u8::MIN, u8::MAX, u8::MIN as u16, u8::MAX as u16);

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

    #[test]
    fn test_clamp_f32_u8() {
        let t: u8 = Clamp::clamp(255f32);
        assert_eq!(t, 255u8);
        let u: u8 = Clamp::clamp(300f32);
        assert_eq!(u, 255u8);
        let v: u8 = Clamp::clamp(0f32);
        assert_eq!(v, 0u8);
        let w: u8 = Clamp::clamp(-5f32);
        assert_eq!(w, 0u8);
    }

    #[test]
    fn test_clamp_f32_u16() {
        let t: u16 = Clamp::clamp(65535f32);
        assert_eq!(t, 65535u16);
        let u: u16 = Clamp::clamp(300000f32);
        assert_eq!(u, 65535u16);
        let v: u16 = Clamp::clamp(0f32);
        assert_eq!(v, 0u16);
        let w: u16 = Clamp::clamp(-5f32);
        assert_eq!(w, 0u16);
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::fmt;

use log::trace;

use rustc_span::DUMMY_SP;

use crate::*;

/// Details of premature program termination.
pub enum TerminationInfo {
    Exit(i64),
    Abort(Option<String>),
    UnsupportedInIsolation(String),
    ExperimentalUb { msg: String, url: String },
    Deadlock,
}

impl fmt::Debug for TerminationInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use TerminationInfo::*;
        match self {
            Exit(code) =>
                write!(f, "the evaluated program completed with exit code {}", code),
            Abort(None) =>
                write!(f, "the evaluated program aborted execution"),
            Abort(Some(msg)) =>
                write!(f, "the evaluated program aborted execution: {}", msg),
            UnsupportedInIsolation(msg) =>
                write!(f, "{}", msg),
            ExperimentalUb { msg, .. } =>
                write!(f, "{}", msg),
            Deadlock =>
                write!(f, "the evaluated program deadlocked"),
        }
    }
}

impl MachineStopType for TerminationInfo {}

/// Miri specific diagnostics
pub enum NonHaltingDiagnostic {
    PoppedTrackedPointerTag(Item),
    CreatedAlloc(AllocId),
}

/// Emit a custom diagnostic without going through the miri-engine machinery
pub fn report_error<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
    mut e: InterpErrorInfo<'tcx>,
) -> Option<i64> {
    use InterpError::*;

    let (title, helps) = match &e.kind {
        MachineStop(info) => {
            let info = info.downcast_ref::<TerminationInfo>().expect("invalid MachineStop payload");
            use TerminationInfo::*;
            let title = match info {
                Exit(code) => return Some(*code),
                Abort(_) =>
                    "abnormal termination",
                UnsupportedInIsolation(_) =>
                    "unsupported operation",
                ExperimentalUb { .. } =>
                    "Undefined Behavior",
                Deadlock => "deadlock",
            };
            let helps = match info {
                UnsupportedInIsolation(_) =>
                    vec![format!("pass the flag `-Zmiri-disable-isolation` to disable isolation")],
                ExperimentalUb { url, .. } =>
                    vec![
                        format!("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental"),
                        format!("see {} for further information", url),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
        _ => {
            let title = match e.kind {
                Unsupported(_) =>
                    "unsupported operation",
                UndefinedBehavior(_) =>
                    "Undefined Behavior",
                ResourceExhaustion(_) =>
                    "resource exhaustion",
                _ =>
                    bug!("This error should be impossible in Miri: {}", e),
            };
            let helps = match e.kind {
                Unsupported(UnsupportedOpInfo::NoMirFor(..)) =>
                    vec![format!("make sure to use a Miri sysroot, which you can prepare with `cargo miri setup`")],
                Unsupported(_) =>
                    vec![format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support")],
                UndefinedBehavior(_) =>
                    vec![
                        format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
                        format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
    };

    e.print_backtrace();
    let msg = e.to_string();
    report_msg(ecx, &format!("{}: {}", title, msg), msg, helps, true)
}

/// Report an error or note (depending on the `error` argument) at the current frame's current statement.
/// Also emits a full stacktrace of the interpreter stack.
fn report_msg<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
    title: &str,
    span_msg: String,
    mut helps: Vec<String>,
    error: bool,
) -> Option<i64> {
    let span = if let Some(frame) = ecx.stack().last() {
        frame.current_source_info().unwrap().span
    } else {
        DUMMY_SP
    };
    let mut err = if error {
        ecx.tcx.sess.struct_span_err(span, title)
    } else {
        ecx.tcx.sess.diagnostic().span_note_diag(span, title)
    };
    err.span_label(span, span_msg);
    if !helps.is_empty() {
        // Add visual separator before backtrace.
        helps.last_mut().unwrap().push_str("\n");
        for help in helps {
            err.help(&help);
        }
    }
    // Add backtrace
    let frames = ecx.generate_stacktrace();
    for (idx, frame_info) in frames.iter().enumerate() {
        let is_local = frame_info.instance.def_id().is_local();
        // No span for non-local frames and the first frame (which is the error site).
        if is_local && idx > 0 {
            err.span_note(frame_info.span, &frame_info.to_string());
        } else {
            err.note(&frame_info.to_string());
        }
    }

    err.emit();

    for (i, frame) in ecx.stack().iter().enumerate() {
        trace!("-------------------");
        trace!("Frame {}", i);
        trace!("    return: {:?}", frame.return_place.map(|p| *p));
        for (i, local) in frame.locals.iter().enumerate() {
            trace!("    local {}: {:?}", i, local.value);
        }
    }
    // Let the reported error determine the return code.
    return None;
}

thread_local! {
    static DIAGNOSTICS: RefCell<Vec<NonHaltingDiagnostic>> = RefCell::new(Vec::new());
}

/// Schedule a diagnostic for emitting. This function works even if you have no `InterpCx` available.
/// The diagnostic will be emitted after the current interpreter step is finished.
pub fn register_diagnostic(e: NonHaltingDiagnostic) {
    DIAGNOSTICS.with(|diagnostics| diagnostics.borrow_mut().push(e));
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Emit all diagnostics that were registed with `register_diagnostics`
    fn process_diagnostics(&self) {
        let this = self.eval_context_ref();
        DIAGNOSTICS.with(|diagnostics| {
            for e in diagnostics.borrow_mut().drain(..) {
                use NonHaltingDiagnostic::*;
                let msg = match e {
                    PoppedTrackedPointerTag(item) =>
                        format!("popped tracked tag for item {:?}", item),
                    CreatedAlloc(AllocId(id)) =>
                        format!("created allocation with id {}", id),
                };
                report_msg(this, "tracking was triggered", msg, vec![], false);
            }
        });
    }
}
<commit_msg>Auto merge of #1328 - RalfJung:align-false-pos, r=RalfJung<commit_after>use std::cell::RefCell;
use std::fmt;

use log::trace;

use rustc_span::DUMMY_SP;

use crate::*;

/// Details of premature program termination.
pub enum TerminationInfo {
    Exit(i64),
    Abort(Option<String>),
    UnsupportedInIsolation(String),
    ExperimentalUb { msg: String, url: String },
    Deadlock,
}

impl fmt::Debug for TerminationInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use TerminationInfo::*;
        match self {
            Exit(code) =>
                write!(f, "the evaluated program completed with exit code {}", code),
            Abort(None) =>
                write!(f, "the evaluated program aborted execution"),
            Abort(Some(msg)) =>
                write!(f, "the evaluated program aborted execution: {}", msg),
            UnsupportedInIsolation(msg) =>
                write!(f, "{}", msg),
            ExperimentalUb { msg, .. } =>
                write!(f, "{}", msg),
            Deadlock =>
                write!(f, "the evaluated program deadlocked"),
        }
    }
}

impl MachineStopType for TerminationInfo {}

/// Miri specific diagnostics
pub enum NonHaltingDiagnostic {
    PoppedTrackedPointerTag(Item),
    CreatedAlloc(AllocId),
}

/// Emit a custom diagnostic without going through the miri-engine machinery
pub fn report_error<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
    mut e: InterpErrorInfo<'tcx>,
) -> Option<i64> {
    use InterpError::*;

    let (title, helps) = match &e.kind {
        MachineStop(info) => {
            let info = info.downcast_ref::<TerminationInfo>().expect("invalid MachineStop payload");
            use TerminationInfo::*;
            let title = match info {
                Exit(code) => return Some(*code),
                Abort(_) =>
                    "abnormal termination",
                UnsupportedInIsolation(_) =>
                    "unsupported operation",
                ExperimentalUb { .. } =>
                    "Undefined Behavior",
                Deadlock => "deadlock",
            };
            let helps = match info {
                UnsupportedInIsolation(_) =>
                    vec![format!("pass the flag `-Zmiri-disable-isolation` to disable isolation")],
                ExperimentalUb { url, .. } =>
                    vec![
                        format!("this indicates a potential bug in the program: it performed an invalid operation, but the rules it violated are still experimental"),
                        format!("see {} for further information", url),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
        _ => {
            let title = match e.kind {
                Unsupported(_) =>
                    "unsupported operation",
                UndefinedBehavior(_) =>
                    "Undefined Behavior",
                ResourceExhaustion(_) =>
                    "resource exhaustion",
                _ =>
                    bug!("This error should be impossible in Miri: {}", e),
            };
            let helps = match e.kind {
                Unsupported(UnsupportedOpInfo::NoMirFor(..)) =>
                    vec![format!("make sure to use a Miri sysroot, which you can prepare with `cargo miri setup`")],
                Unsupported(_) =>
                    vec![format!("this is likely not a bug in the program; it indicates that the program performed an operation that the interpreter does not support")],
                UndefinedBehavior(UndefinedBehaviorInfo::AlignmentCheckFailed { .. }) =>
                    vec![
                        format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior"),
                        format!("but alignment errors can also be false positives, see https://github.com/rust-lang/miri/issues/1074"),
                    ],
                UndefinedBehavior(_) =>
                    vec![
                        format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior"),
                        format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information"),
                    ],
                _ => vec![],
            };
            (title, helps)
        }
    };

    e.print_backtrace();
    let msg = e.to_string();
    report_msg(ecx, &format!("{}: {}", title, msg), msg, helps, true)
}

/// Report an error or note (depending on the `error` argument) at the current frame's current statement.
/// Also emits a full stacktrace of the interpreter stack.
fn report_msg<'tcx, 'mir>(
    ecx: &InterpCx<'mir, 'tcx, Evaluator<'tcx>>,
    title: &str,
    span_msg: String,
    mut helps: Vec<String>,
    error: bool,
) -> Option<i64> {
    let span = if let Some(frame) = ecx.stack().last() {
        frame.current_source_info().unwrap().span
    } else {
        DUMMY_SP
    };
    let mut err = if error {
        ecx.tcx.sess.struct_span_err(span, title)
    } else {
        ecx.tcx.sess.diagnostic().span_note_diag(span, title)
    };
    err.span_label(span, span_msg);
    if !helps.is_empty() {
        // Add visual separator before backtrace.
        helps.last_mut().unwrap().push_str("\n");
        for help in helps {
            err.help(&help);
        }
    }
    // Add backtrace
    let frames = ecx.generate_stacktrace();
    for (idx, frame_info) in frames.iter().enumerate() {
        let is_local = frame_info.instance.def_id().is_local();
        // No span for non-local frames and the first frame (which is the error site).
        if is_local && idx > 0 {
            err.span_note(frame_info.span, &frame_info.to_string());
        } else {
            err.note(&frame_info.to_string());
        }
    }

    err.emit();

    for (i, frame) in ecx.stack().iter().enumerate() {
        trace!("-------------------");
        trace!("Frame {}", i);
        trace!("    return: {:?}", frame.return_place.map(|p| *p));
        for (i, local) in frame.locals.iter().enumerate() {
            trace!("    local {}: {:?}", i, local.value);
        }
    }
    // Let the reported error determine the return code.
    return None;
}

thread_local! {
    static DIAGNOSTICS: RefCell<Vec<NonHaltingDiagnostic>> = RefCell::new(Vec::new());
}

/// Schedule a diagnostic for emitting. This function works even if you have no `InterpCx` available.
/// The diagnostic will be emitted after the current interpreter step is finished.
pub fn register_diagnostic(e: NonHaltingDiagnostic) {
    DIAGNOSTICS.with(|diagnostics| diagnostics.borrow_mut().push(e));
}

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}
pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Emit all diagnostics that were registed with `register_diagnostics`
    fn process_diagnostics(&self) {
        let this = self.eval_context_ref();
        DIAGNOSTICS.with(|diagnostics| {
            for e in diagnostics.borrow_mut().drain(..) {
                use NonHaltingDiagnostic::*;
                let msg = match e {
                    PoppedTrackedPointerTag(item) =>
                        format!("popped tracked tag for item {:?}", item),
                    CreatedAlloc(AllocId(id)) =>
                        format!("created allocation with id {}", id),
                };
                report_msg(this, "tracking was triggered", msg, vec![], false);
            }
        });
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017 Sreejith Krishnan R
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

use std::f32;

use super::{Drawable, MeasureMode, BoundingBox, AbsoluteLayout, AbsoluteLayoutParams, Glyph, GlyphIndex};
use ::platform::Context;
use ::paint::{Point, Canvas, GlyphConstructionDirection, MathRuler, GlyphAssembly};
use ::props::{Color, Directionality};
use ::elements::Element;

type SymbolReader<T> = fn(&T) -> u32;
type SymmetricReader<T> = fn(&T) -> bool;
type SizeReader<T> = fn(&T) -> f32;
type DirReader<T> = fn(&T) -> &Directionality;
type ColorReader<T> = fn(&T) -> &Color;

pub struct Symbol<'a, T: Element + 'a> {
    props: &'a T,
    symbol_reader: SymbolReader<T>,
    symmetric_reader: SymmetricReader<T>,
    base_size_reader: SizeReader<T>,
    max_size_reader: SizeReader<T>,
    min_size_reader: SizeReader<T>,
    dir_reader: DirReader<T>,
    color_reader: ColorReader<T>,

    bounding_box: BoundingBox,
    layout: AbsoluteLayout<'a>,
}

impl<'a, T: Element + 'a> Drawable for Symbol<'a, T> {
    fn draw(&self, canvas: &Canvas, pen_pos: &Point) {
        self.layout.draw(canvas, pen_pos);
    }

    fn calculate(&mut self, context: &Context, width: f32, width_mode: &MeasureMode, height: f32,
                 height_mode: &MeasureMode) {
        let base_size = (self.base_size_reader)(self.props);
        let symbol = (self.symbol_reader)(self.props);
        let ruler = context.platform().get_math_ruler(self.props, base_size);

        if *height_mode == MeasureMode::UpTo {
            let stretch_dir = GlyphConstructionDirection::Vertical;

            if self.try_stretch_symbol(context,symbol, ruler, height, &stretch_dir) {
                return;
            }
        }

        if *width_mode == MeasureMode::UpTo {
            let stretch_dir = GlyphConstructionDirection::Horizontal;

            if self.try_stretch_symbol(context,symbol, ruler, width, &stretch_dir) {
                return;
            }
        }

        self.set_single_glyph(context,GlyphIndex::Char(symbol));
    }

    fn bounding_box(&self) -> &BoundingBox {
        &self.bounding_box
    }
}

impl<'a, T: Element + 'a> Symbol<'a, T> {
    pub fn new(props: &'a T, symbol_reader: SymbolReader<T>, symmetric_reader: SymmetricReader<T>,
               base_size_reader: SizeReader<T>, max_size_reader: SizeReader<T>,
               min_size_reader: SizeReader<T>, dir_reader: DirReader<T>,
               color_reader: ColorReader<T>) -> Symbol<'a, T> {
        Symbol {
            props,
            symbol_reader,
            symmetric_reader,
            base_size_reader,
            max_size_reader,
            min_size_reader,
            dir_reader,
            color_reader,
            bounding_box: BoundingBox::default(),
            layout: AbsoluteLayout::new(),
        }
    }

    fn set_single_glyph(&mut self, context: &Context, glyph: GlyphIndex) {
        let glyph = Glyph::new(
            self.props,
            glyph,
            self.base_size_reader,
            self.color_reader,
            self.dir_reader
        );

        self.layout.clear();
        self.layout.add_child(Box::new(glyph),
                              AbsoluteLayoutParams::new(Point::new(0., 0.)));

        self.layout.calculate(context, -1., &MeasureMode::Wrap, -1., &MeasureMode::Wrap);

        self.bounding_box = self.layout.bounding_box().clone();
    }

    fn try_stretch_symbol(&mut self, context: &Context, symbol: u32, ruler: &MathRuler,
                          stretched_size: f32, stretch_dir: &GlyphConstructionDirection) -> bool {
        let variants = ruler.glyph_variants(symbol, stretch_dir);

        for variant in variants {
            if variant.advance() >= stretched_size {
                self.set_single_glyph(context, GlyphIndex::Index(variant.glyph_index()));
                return true;
            }
        }

        let assembly = ruler.glyph_assembly(symbol, stretch_dir);
        if assembly.parts().len() >= 2 {
            self.set_glyph_assembly(context, assembly, &stretch_dir, stretched_size, ruler);
            return true;
        }

        return false;
    }

    fn set_glyph_assembly(&mut self, context: &Context, assembly: GlyphAssembly,
                          stretch_dir: &GlyphConstructionDirection,
                          stretched_size: f32, ruler: &MathRuler) {
        let min_connector_overlap = ruler.minimum_connector_overlap(stretch_dir);

        let mut num_extenders = 0;
        let mut total_extender_advance = 0f32;

        let mut num_non_extenders = 0;
        let mut total_non_extender_advance = 0f32;

        let mut max_connector_overlap = 0f32;

        for (index, part) in assembly.parts().iter().enumerate() {
            if part.is_extender() {
                num_extenders += 1;
                total_extender_advance += part.full_advance();
            } else {
                num_non_extenders += 1;
                total_non_extender_advance += part.full_advance();
            }

            if index != 0 {
                max_connector_overlap = max_connector_overlap.min(part.start_connector_length());
            }

            max_connector_overlap = max_connector_overlap.min(part.full_advance());

            if index != assembly.parts().len()-1 {
                max_connector_overlap = max_connector_overlap.min(part.end_connector_length());
            }

            max_connector_overlap = max_connector_overlap
                .min(part.start_connector_length())
                .min(part.end_connector_length())
                .min(part.full_advance());
        }

        let num_extenders = num_extenders as f32;
        let num_non_extenders = num_non_extenders as f32;

        let extender_multiplier = ((stretched_size + (min_connector_overlap * (num_non_extenders + 1.))
            - total_non_extender_advance) /
            (total_extender_advance + (min_connector_overlap * num_extenders))).ceil();

        let required_overlap = (total_non_extender_advance + (extender_multiplier * total_extender_advance)
            - stretched_size) /
            (num_non_extenders + (extender_multiplier * num_extenders) - 1.);

        let overlap = required_overlap.min(max_connector_overlap);

        self.layout.clear();

        let mut pen_pos = 0f32;
        for part in assembly.parts().iter() {
            self.layout.add_child(
                Box::new(Glyph::new(
                    self.props,
                    GlyphIndex::Index(part.glyph_index()),
                    self.base_size_reader,
                    self.color_reader,
                    self.dir_reader)
                ),
                AbsoluteLayoutParams::new(match *stretch_dir {
                    GlyphConstructionDirection::Horizontal => Point::new(pen_pos, 0.),
                    GlyphConstructionDirection::Vertical => Point::new(0., pen_pos)
                })
            );

            pen_pos += part.full_advance()-overlap;
        }

        self.layout.calculate(context, -1., &MeasureMode::Wrap, -1., &MeasureMode::Wrap);

        self.bounding_box = self.layout.bounding_box().clone();
    }
}<commit_msg>Stretch between max and min size specified<commit_after>/*
 * Copyright 2017 Sreejith Krishnan R
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

use std::f32;

use super::{Drawable, MeasureMode, BoundingBox, AbsoluteLayout, AbsoluteLayoutParams, Glyph, GlyphIndex};
use ::platform::Context;
use ::paint::{Point, Canvas, GlyphConstructionDirection, MathRuler, GlyphAssembly};
use ::props::{Color, Directionality};
use ::elements::Element;

type SymbolReader<T> = fn(&T) -> u32;
type SymmetricReader<T> = fn(&T) -> bool;
type SizeReader<T> = fn(&T) -> f32;
type DirReader<T> = fn(&T) -> &Directionality;
type ColorReader<T> = fn(&T) -> &Color;

pub struct Symbol<'a, T: Element + 'a> {
    props: &'a T,
    symbol_reader: SymbolReader<T>,
    symmetric_reader: SymmetricReader<T>,
    base_size_reader: SizeReader<T>,
    max_size_reader: SizeReader<T>,
    min_size_reader: SizeReader<T>,
    dir_reader: DirReader<T>,
    color_reader: ColorReader<T>,

    bounding_box: BoundingBox,
    layout: AbsoluteLayout<'a>,
}

impl<'a, T: Element + 'a> Drawable for Symbol<'a, T> {
    fn draw(&self, canvas: &Canvas, pen_pos: &Point) {
        self.layout.draw(canvas, pen_pos);
    }

    fn calculate(&mut self, context: &Context, width: f32, width_mode: &MeasureMode, height: f32,
                 height_mode: &MeasureMode) {
        let base_size = (self.base_size_reader)(self.props);
        let symbol = (self.symbol_reader)(self.props);
        let ruler = context.platform().get_math_ruler(self.props, base_size);

        if *height_mode == MeasureMode::UpTo {
            let stretch_dir = GlyphConstructionDirection::Vertical;
            let stretched_size = base_size
                .max((self.min_size_reader)(self.props))
                .min((self.max_size_reader)(self.props))
                .min(height);

            if self.try_stretch_symbol(context,symbol, ruler, stretched_size, &stretch_dir) {
                return;
            }
        }

        if *width_mode == MeasureMode::UpTo {
            let stretch_dir = GlyphConstructionDirection::Horizontal;
            let stretched_size = base_size
                .max((self.min_size_reader)(self.props))
                .min((self.max_size_reader)(self.props))
                .min(width);

            if self.try_stretch_symbol(context,symbol, ruler, stretched_size, &stretch_dir) {
                return;
            }
        }

        self.set_single_glyph(context,GlyphIndex::Char(symbol));
    }

    fn bounding_box(&self) -> &BoundingBox {
        &self.bounding_box
    }
}

impl<'a, T: Element + 'a> Symbol<'a, T> {
    pub fn new(props: &'a T, symbol_reader: SymbolReader<T>, symmetric_reader: SymmetricReader<T>,
               base_size_reader: SizeReader<T>, max_size_reader: SizeReader<T>,
               min_size_reader: SizeReader<T>, dir_reader: DirReader<T>,
               color_reader: ColorReader<T>) -> Symbol<'a, T> {
        Symbol {
            props,
            symbol_reader,
            symmetric_reader,
            base_size_reader,
            max_size_reader,
            min_size_reader,
            dir_reader,
            color_reader,
            bounding_box: BoundingBox::default(),
            layout: AbsoluteLayout::new(),
        }
    }

    fn set_single_glyph(&mut self, context: &Context, glyph: GlyphIndex) {
        let glyph = Glyph::new(
            self.props,
            glyph,
            self.base_size_reader,
            self.color_reader,
            self.dir_reader
        );

        self.layout.clear();
        self.layout.add_child(Box::new(glyph),
                              AbsoluteLayoutParams::new(Point::new(0., 0.)));

        self.layout.calculate(context, -1., &MeasureMode::Wrap, -1., &MeasureMode::Wrap);

        self.bounding_box = self.layout.bounding_box().clone();
    }

    fn try_stretch_symbol(&mut self, context: &Context, symbol: u32, ruler: &MathRuler,
                          stretched_size: f32, stretch_dir: &GlyphConstructionDirection) -> bool {
        let variants = ruler.glyph_variants(symbol, stretch_dir);

        for variant in variants {
            if variant.advance() >= stretched_size {
                self.set_single_glyph(context, GlyphIndex::Index(variant.glyph_index()));
                return true;
            }
        }

        let assembly = ruler.glyph_assembly(symbol, stretch_dir);
        if assembly.parts().len() >= 2 {
            self.set_glyph_assembly(context, assembly, &stretch_dir, stretched_size, ruler);
            return true;
        }

        return false;
    }

    fn set_glyph_assembly(&mut self, context: &Context, assembly: GlyphAssembly,
                          stretch_dir: &GlyphConstructionDirection,
                          stretched_size: f32, ruler: &MathRuler) {
        let min_connector_overlap = ruler.minimum_connector_overlap(stretch_dir);

        let mut num_extenders = 0;
        let mut total_extender_advance = 0f32;

        let mut num_non_extenders = 0;
        let mut total_non_extender_advance = 0f32;

        let mut max_connector_overlap = 0f32;

        for (index, part) in assembly.parts().iter().enumerate() {
            if part.is_extender() {
                num_extenders += 1;
                total_extender_advance += part.full_advance();
            } else {
                num_non_extenders += 1;
                total_non_extender_advance += part.full_advance();
            }

            if index != 0 {
                max_connector_overlap = max_connector_overlap.min(part.start_connector_length());
            }

            max_connector_overlap = max_connector_overlap.min(part.full_advance());

            if index != assembly.parts().len()-1 {
                max_connector_overlap = max_connector_overlap.min(part.end_connector_length());
            }

            max_connector_overlap = max_connector_overlap
                .min(part.start_connector_length())
                .min(part.end_connector_length())
                .min(part.full_advance());
        }

        let num_extenders = num_extenders as f32;
        let num_non_extenders = num_non_extenders as f32;

        let extender_multiplier = ((stretched_size + (min_connector_overlap * (num_non_extenders + 1.))
            - total_non_extender_advance) /
            (total_extender_advance + (min_connector_overlap * num_extenders))).ceil();

        let required_overlap = (total_non_extender_advance + (extender_multiplier * total_extender_advance)
            - stretched_size) /
            (num_non_extenders + (extender_multiplier * num_extenders) - 1.);

        let overlap = required_overlap.min(max_connector_overlap);

        self.layout.clear();

        let mut pen_pos = 0f32;
        for part in assembly.parts().iter() {
            self.layout.add_child(
                Box::new(Glyph::new(
                    self.props,
                    GlyphIndex::Index(part.glyph_index()),
                    self.base_size_reader,
                    self.color_reader,
                    self.dir_reader)
                ),
                AbsoluteLayoutParams::new(match *stretch_dir {
                    GlyphConstructionDirection::Horizontal => Point::new(pen_pos, 0.),
                    GlyphConstructionDirection::Vertical => Point::new(0., pen_pos)
                })
            );

            pen_pos += part.full_advance()-overlap;
        }

        self.layout.calculate(context, -1., &MeasureMode::Wrap, -1., &MeasureMode::Wrap);

        self.bounding_box = self.layout.bounding_box().clone();
    }
}<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// corresponds to lauxlib.h
use libc::{c_int, c_long, c_char, c_void, size_t};
use ffi::lua;
use ffi::lua::{lua_State, lua_CFunction, lua_Integer, lua_Number};
use ffi::luaconf::LUAL_BUFFERSIZE;
use std::ptr;

pub use super::glue::LUAL_NUMSIZES;

// extra error code for 'luaL_load'
pub const LUA_ERRFILE: c_int = lua::LUA_ERRERR + 1;

#[repr(C)]
pub struct luaL_Reg {
  pub name: *const c_char,
  pub func: lua_CFunction,
}

#[inline(always)]
pub unsafe fn luaL_checkversion(L: *mut lua_State) {
  luaL_checkversion_(L, lua::LUA_VERSION_NUM as lua_Number, LUAL_NUMSIZES as size_t)
}

extern {
  pub fn luaL_checkversion_(L: *mut lua_State, ver: lua_Number, sz: size_t);

  pub fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
  pub fn luaL_callmeta(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
  pub fn luaL_tolstring(L: *mut lua_State, idx: c_int, len: *mut size_t) -> *const c_char;
  pub fn luaL_argerror(L: *mut lua_State, arg: c_int, l: *const c_char) -> c_int;
  pub fn luaL_checklstring(L: *mut lua_State, arg: c_int, l: *mut size_t) -> *const c_char;
  pub fn luaL_optlstring(L: *mut lua_State, arg: c_int, def: *const c_char, l: *mut size_t) -> *const c_char;
  pub fn luaL_checknumber(L: *mut lua_State, arg: c_int) -> lua_Number;
  pub fn luaL_optnumber(L: *mut lua_State, arg: c_int, def: lua_Number) -> lua_Number;
  pub fn luaL_checkinteger(L: *mut lua_State, arg: c_int) -> lua_Integer;
  pub fn luaL_optinteger(L: *mut lua_State, arg: c_int, def: lua_Integer) -> lua_Integer;

  pub fn luaL_checkstack(L: *mut lua_State, sz: c_int, msg: *const c_char);
  pub fn luaL_checktype(L: *mut lua_State, arg: c_int, t: c_int);
  pub fn luaL_checkany(L: *mut lua_State, arg: c_int);

  pub fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int;
  pub fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char);
  pub fn luaL_testudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;
  pub fn luaL_checkudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;

  pub fn luaL_where(L: *mut lua_State, lvl: c_int);
  pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> c_int;

  // TODO: test this
  pub fn luaL_checkoption(L: *mut lua_State, arg: c_int, def: *const c_char, lst: [*const c_char]) -> c_int;

  pub fn luaL_fileresult(L: *mut lua_State, stat: c_int, fname: *const c_char) -> c_int;
  pub fn luaL_execresult(L: *mut lua_State, stat: c_int) -> c_int;
}

// pre-defined references
pub const LUA_NOREF: c_int = -2;
pub const LUA_REFNIL: c_int = -1;

extern {
  pub fn luaL_ref(L: *mut lua_State, t: c_int) -> c_int;
  pub fn luaL_unref(L: *mut lua_State, t: c_int, r: c_int);

  pub fn luaL_loadfilex(L: *mut lua_State, filename: *const c_char, mode: *const c_char) -> c_int;
}

#[inline(always)]
pub unsafe fn luaL_loadfile(L: *mut lua_State, f: *const c_char) -> c_int {
  luaL_loadfilex(L, f, ptr::null())
}

extern {
  pub fn luaL_loadbufferx(L: *mut lua_State, buff: *const c_char, sz: size_t, name: *const c_char, mode: *const c_char) -> c_int;
  pub fn luaL_loadstring(L: *mut lua_State, s: *const c_char) -> c_int;

  pub fn luaL_newstate() -> *mut lua_State;

  pub fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer;

  pub fn luaL_gsub(L: *mut lua_State, s: *const c_char, p: *const c_char, r: *const c_char) -> *const c_char;

  pub fn luaL_setfuncs(L: *mut lua_State, l: *const luaL_Reg, nup: c_int);

  pub fn luaL_getsubtable(L: *mut lua_State, idx: c_int, fname: *const c_char) -> c_int;

  pub fn luaL_traceback(L: *mut lua_State, L1: *mut lua_State, msg: *const c_char, level: c_int);

  pub fn luaL_requiref(L: *mut lua_State, modname: *const c_char, openf: lua_CFunction, glb: c_int);
}

#[inline(always)]
#[allow(unused_variables)]
pub unsafe fn luaL_newlibtable(L: *mut lua_State, l: *const luaL_Reg) {
  // TODO: figure out how to pass an appropriate hint for the second param
  // this involves correcting the second parameter's type; in C this is
  // sizeof(l)/sizeof(l[0])
  lua::lua_createtable(L, 0, 0)
}

#[inline(always)]
pub unsafe fn luaL_newlib(L: *mut lua_State, l: *const luaL_Reg) {
  luaL_checkversion(L);
  luaL_newlibtable(L, l);
  luaL_setfuncs(L, l, 0)
}

#[inline(always)]
pub unsafe fn luaL_argcheck(L: *mut lua_State, cond: c_int, arg: c_int, extramsg: *const c_char) {
  if cond == 0 {
    luaL_argerror(L, arg, extramsg);
  }
}

#[inline(always)]
pub unsafe fn luaL_checkstring(L: *mut lua_State, n: c_int) -> *const c_char {
  luaL_checklstring(L, n, ptr::null_mut())
}

#[inline(always)]
pub unsafe fn luaL_optstring(L: *mut lua_State, n: c_int, d: *const c_char) -> *const c_char {
  luaL_optlstring(L, n, d, ptr::null_mut())
}

// From 5.3 user manual:
// Macros to project non-default integer types (luaL_checkint, luaL_optint,
// luaL_checklong, luaL_optlong) were deprecated. Use their equivalent over
// lua_Integer with a type cast (or, when possible, use lua_Integer in your
// code).
#[inline(always)]
#[deprecated]
pub unsafe fn luaL_checkint(L: *mut lua_State, n: c_int) -> c_int {
  luaL_checkinteger(L, n) as c_int
}

#[inline(always)]
#[deprecated]
pub unsafe fn luaL_optint(L: *mut lua_State, n: c_int, d: c_int) -> c_int {
  luaL_optinteger(L, n, d as lua_Integer) as c_int
}

#[inline(always)]
#[deprecated]
pub unsafe fn luaL_checklong(L: *mut lua_State, n: c_int) -> c_long {
  luaL_checkinteger(L, n) as c_int
}

#[inline(always)]
#[deprecated]
pub unsafe fn luaL_optlong(L: *mut lua_State, n: c_int, d: c_long) -> c_long {
  luaL_optinteger(L, n, d as lua_Integer) as c_int
}

#[inline(always)]
pub unsafe fn luaL_typename(L: *mut lua_State, i: c_int) -> *const c_char {
  lua::lua_typename(L, lua::lua_type(L, i))
}

#[inline(always)]
pub unsafe fn luaL_dofile(L: *mut lua_State, filename: *const c_char) -> c_int {
  let status = luaL_loadfile(L, filename);
  if status == 0 {
    lua::lua_pcall(L, 0, lua::LUA_MULTRET, 0)
  } else {
    status
  }
}

#[inline(always)]
pub unsafe fn luaL_dostring(L: *mut lua_State, s: *const c_char) -> c_int {
  let status = luaL_loadstring(L, s);
  if status == 0 {
    lua::lua_pcall(L, 0, lua::LUA_MULTRET, 0)
  } else {
    status
  }
}

#[inline(always)]
pub unsafe fn luaL_getmetatable(L: *mut lua_State, n: *const c_char) {
  lua::lua_getfield(L, lua::LUA_REGISTRYINDEX, n);
}

// luaL_opt would be implemented here but it is undocumented, so it's omitted

#[inline(always)]
pub unsafe fn luaL_loadbuffer(L: *mut lua_State, s: *const c_char, sz: size_t, n: *const c_char) -> c_int {
  luaL_loadbufferx(L, s, sz, n, ptr::null())
}

#[repr(C)]
pub struct luaL_Buffer {
  b: *mut c_char,
  size: size_t,
  n: size_t,
  L: *mut lua_State,
  initb: [c_char, ..LUAL_BUFFERSIZE as uint]
}

// TODO: Test this thoroughly
#[inline(always)]
pub unsafe fn luaL_addchar(B: *mut luaL_Buffer, c: c_char) {
  // (B)->n < (B) -> size || luaL_prepbuffsize((B), 1)
  if (*B).n < (*B).size {
    luaL_prepbuffsize(B, 1);
  }
  // (B)->b[(B)->n++] = (c)
  let offset = (*B).b.offset((*B).n as int);
  ptr::write(offset, c);
  (*B).n += 1;
}

#[inline(always)]
pub unsafe fn luaL_addsize(B: *mut luaL_Buffer, s: size_t) {
  (*B).n += s;
}

extern {
  pub fn luaL_buffinit(L: *mut lua_State, B: *mut luaL_Buffer);
  pub fn luaL_prepbuffsize(B: *mut luaL_Buffer, sz: size_t) -> *mut c_char;
  pub fn luaL_addlstring(B: *mut luaL_Buffer, s: *const c_char, l: size_t);
  pub fn luaL_addstring(B: *mut luaL_Buffer, s: *const c_char);
  pub fn luaL_addvalue(B: *mut luaL_Buffer);
  pub fn luaL_pushresult(B: *mut luaL_Buffer);
  pub fn luaL_pushresultsize(B: *mut luaL_Buffer, sz: size_t);
  pub fn luaL_buffinitsize(L: *mut lua_State, B: *mut luaL_Buffer, sz: size_t) -> *mut c_char;
}

pub unsafe fn luaL_prepbuffer(B: *mut luaL_Buffer) -> *mut c_char {
  luaL_prepbuffsize(B, LUAL_BUFFERSIZE as size_t)
}

// omitted: LUA_FILEHANDLE

#[repr(C)]
pub struct luaL_Stream {
  f: *mut c_void,
  closef: lua_CFunction
}

// omitted: old module system compatibility
<commit_msg>Correct luaL_checkoption signature<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2014 J.C. Moyer
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

// corresponds to lauxlib.h
use libc::{c_int, c_long, c_char, c_void, size_t};
use ffi::lua;
use ffi::lua::{lua_State, lua_CFunction, lua_Integer, lua_Number};
use ffi::luaconf::LUAL_BUFFERSIZE;
use std::ptr;

pub use super::glue::LUAL_NUMSIZES;

// extra error code for 'luaL_load'
pub const LUA_ERRFILE: c_int = lua::LUA_ERRERR + 1;

#[repr(C)]
pub struct luaL_Reg {
  pub name: *const c_char,
  pub func: lua_CFunction,
}

#[inline(always)]
pub unsafe fn luaL_checkversion(L: *mut lua_State) {
  luaL_checkversion_(L, lua::LUA_VERSION_NUM as lua_Number, LUAL_NUMSIZES as size_t)
}

extern {
  pub fn luaL_checkversion_(L: *mut lua_State, ver: lua_Number, sz: size_t);

  pub fn luaL_getmetafield(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
  pub fn luaL_callmeta(L: *mut lua_State, obj: c_int, e: *const c_char) -> c_int;
  pub fn luaL_tolstring(L: *mut lua_State, idx: c_int, len: *mut size_t) -> *const c_char;
  pub fn luaL_argerror(L: *mut lua_State, arg: c_int, l: *const c_char) -> c_int;
  pub fn luaL_checklstring(L: *mut lua_State, arg: c_int, l: *mut size_t) -> *const c_char;
  pub fn luaL_optlstring(L: *mut lua_State, arg: c_int, def: *const c_char, l: *mut size_t) -> *const c_char;
  pub fn luaL_checknumber(L: *mut lua_State, arg: c_int) -> lua_Number;
  pub fn luaL_optnumber(L: *mut lua_State, arg: c_int, def: lua_Number) -> lua_Number;
  pub fn luaL_checkinteger(L: *mut lua_State, arg: c_int) -> lua_Integer;
  pub fn luaL_optinteger(L: *mut lua_State, arg: c_int, def: lua_Integer) -> lua_Integer;

  pub fn luaL_checkstack(L: *mut lua_State, sz: c_int, msg: *const c_char);
  pub fn luaL_checktype(L: *mut lua_State, arg: c_int, t: c_int);
  pub fn luaL_checkany(L: *mut lua_State, arg: c_int);

  pub fn luaL_newmetatable(L: *mut lua_State, tname: *const c_char) -> c_int;
  pub fn luaL_setmetatable(L: *mut lua_State, tname: *const c_char);
  pub fn luaL_testudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;
  pub fn luaL_checkudata(L: *mut lua_State, ud: c_int, tname: *const c_char) -> *mut c_void;

  pub fn luaL_where(L: *mut lua_State, lvl: c_int);
  pub fn luaL_error(L: *mut lua_State, fmt: *const c_char, ...) -> c_int;

  // TODO: test this
  pub fn luaL_checkoption(L: *mut lua_State, arg: c_int, def: *const c_char, lst: *const *const c_char) -> c_int;

  pub fn luaL_fileresult(L: *mut lua_State, stat: c_int, fname: *const c_char) -> c_int;
  pub fn luaL_execresult(L: *mut lua_State, stat: c_int) -> c_int;
}

// pre-defined references
pub const LUA_NOREF: c_int = -2;
pub const LUA_REFNIL: c_int = -1;

extern {
  pub fn luaL_ref(L: *mut lua_State, t: c_int) -> c_int;
  pub fn luaL_unref(L: *mut lua_State, t: c_int, r: c_int);

  pub fn luaL_loadfilex(L: *mut lua_State, filename: *const c_char, mode: *const c_char) -> c_int;
}

#[inline(always)]
pub unsafe fn luaL_loadfile(L: *mut lua_State, f: *const c_char) -> c_int {
  luaL_loadfilex(L, f, ptr::null())
}

extern {
  pub fn luaL_loadbufferx(L: *mut lua_State, buff: *const c_char, sz: size_t, name: *const c_char, mode: *const c_char) -> c_int;
  pub fn luaL_loadstring(L: *mut lua_State, s: *const c_char) -> c_int;

  pub fn luaL_newstate() -> *mut lua_State;

  pub fn luaL_len(L: *mut lua_State, idx: c_int) -> lua_Integer;

  pub fn luaL_gsub(L: *mut lua_State, s: *const c_char, p: *const c_char, r: *const c_char) -> *const c_char;

  pub fn luaL_setfuncs(L: *mut lua_State, l: *const luaL_Reg, nup: c_int);

  pub fn luaL_getsubtable(L: *mut lua_State, idx: c_int, fname: *const c_char) -> c_int;

  pub fn luaL_traceback(L: *mut lua_State, L1: *mut lua_State, msg: *const c_char, level: c_int);

  pub fn luaL_requiref(L: *mut lua_State, modname: *const c_char, openf: lua_CFunction, glb: c_int);
}

#[inline(always)]
#[allow(unused_variables)]
pub unsafe fn luaL_newlibtable(L: *mut lua_State, l: *const luaL_Reg) {
  // TODO: figure out how to pass an appropriate hint for the second param
  // this involves correcting the second parameter's type; in C this is
  // sizeof(l)/sizeof(l[0])
  lua::lua_createtable(L, 0, 0)
}

#[inline(always)]
pub unsafe fn luaL_newlib(L: *mut lua_State, l: *const luaL_Reg) {
  luaL_checkversion(L);
  luaL_newlibtable(L, l);
  luaL_setfuncs(L, l, 0)
}

#[inline(always)]
pub unsafe fn luaL_argcheck(L: *mut lua_State, cond: c_int, arg: c_int, extramsg: *const c_char) {
  if cond == 0 {
    luaL_argerror(L, arg, extramsg);
  }
}

#[inline(always)]
pub unsafe fn luaL_checkstring(L: *mut lua_State, n: c_int) -> *const c_char {
  luaL_checklstring(L, n, ptr::null_mut())
}

#[inline(always)]
pub unsafe fn luaL_optstring(L: *mut lua_State, n: c_int, d: *const c_char) -> *const c_char {
  luaL_optlstring(L, n, d, ptr::null_mut())
}

// From 5.3 user manual:
// Macros to project non-default integer types (luaL_checkint, luaL_optint,
// luaL_checklong, luaL_optlong) were deprecated. Use their equivalent over
// lua_Integer with a type cast (or, when possible, use lua_Integer in your
// code).
#[inline(always)]
#[deprecated]
pub unsafe fn luaL_checkint(L: *mut lua_State, n: c_int) -> c_int {
  luaL_checkinteger(L, n) as c_int
}

#[inline(always)]
#[deprecated]
pub unsafe fn luaL_optint(L: *mut lua_State, n: c_int, d: c_int) -> c_int {
  luaL_optinteger(L, n, d as lua_Integer) as c_int
}

#[inline(always)]
#[deprecated]
pub unsafe fn luaL_checklong(L: *mut lua_State, n: c_int) -> c_long {
  luaL_checkinteger(L, n) as c_int
}

#[inline(always)]
#[deprecated]
pub unsafe fn luaL_optlong(L: *mut lua_State, n: c_int, d: c_long) -> c_long {
  luaL_optinteger(L, n, d as lua_Integer) as c_int
}

#[inline(always)]
pub unsafe fn luaL_typename(L: *mut lua_State, i: c_int) -> *const c_char {
  lua::lua_typename(L, lua::lua_type(L, i))
}

#[inline(always)]
pub unsafe fn luaL_dofile(L: *mut lua_State, filename: *const c_char) -> c_int {
  let status = luaL_loadfile(L, filename);
  if status == 0 {
    lua::lua_pcall(L, 0, lua::LUA_MULTRET, 0)
  } else {
    status
  }
}

#[inline(always)]
pub unsafe fn luaL_dostring(L: *mut lua_State, s: *const c_char) -> c_int {
  let status = luaL_loadstring(L, s);
  if status == 0 {
    lua::lua_pcall(L, 0, lua::LUA_MULTRET, 0)
  } else {
    status
  }
}

#[inline(always)]
pub unsafe fn luaL_getmetatable(L: *mut lua_State, n: *const c_char) {
  lua::lua_getfield(L, lua::LUA_REGISTRYINDEX, n);
}

// luaL_opt would be implemented here but it is undocumented, so it's omitted

#[inline(always)]
pub unsafe fn luaL_loadbuffer(L: *mut lua_State, s: *const c_char, sz: size_t, n: *const c_char) -> c_int {
  luaL_loadbufferx(L, s, sz, n, ptr::null())
}

#[repr(C)]
pub struct luaL_Buffer {
  b: *mut c_char,
  size: size_t,
  n: size_t,
  L: *mut lua_State,
  initb: [c_char, ..LUAL_BUFFERSIZE as uint]
}

// TODO: Test this thoroughly
#[inline(always)]
pub unsafe fn luaL_addchar(B: *mut luaL_Buffer, c: c_char) {
  // (B)->n < (B) -> size || luaL_prepbuffsize((B), 1)
  if (*B).n < (*B).size {
    luaL_prepbuffsize(B, 1);
  }
  // (B)->b[(B)->n++] = (c)
  let offset = (*B).b.offset((*B).n as int);
  ptr::write(offset, c);
  (*B).n += 1;
}

#[inline(always)]
pub unsafe fn luaL_addsize(B: *mut luaL_Buffer, s: size_t) {
  (*B).n += s;
}

extern {
  pub fn luaL_buffinit(L: *mut lua_State, B: *mut luaL_Buffer);
  pub fn luaL_prepbuffsize(B: *mut luaL_Buffer, sz: size_t) -> *mut c_char;
  pub fn luaL_addlstring(B: *mut luaL_Buffer, s: *const c_char, l: size_t);
  pub fn luaL_addstring(B: *mut luaL_Buffer, s: *const c_char);
  pub fn luaL_addvalue(B: *mut luaL_Buffer);
  pub fn luaL_pushresult(B: *mut luaL_Buffer);
  pub fn luaL_pushresultsize(B: *mut luaL_Buffer, sz: size_t);
  pub fn luaL_buffinitsize(L: *mut lua_State, B: *mut luaL_Buffer, sz: size_t) -> *mut c_char;
}

pub unsafe fn luaL_prepbuffer(B: *mut luaL_Buffer) -> *mut c_char {
  luaL_prepbuffsize(B, LUAL_BUFFERSIZE as size_t)
}

// omitted: LUA_FILEHANDLE

#[repr(C)]
pub struct luaL_Stream {
  f: *mut c_void,
  closef: lua_CFunction
}

// omitted: old module system compatibility
<|endoftext|>


<commit_before>use gui::{Color, Colors};
use util::units::{AsTuple, Point, Size};

use tcod;
use tcod::Console as TCODConsole;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Key {
    Up,
    Down,
    Left,
    Right,
    Escape,
    Enter,
}

pub struct Console {
    console: tcod::RootConsole,
    size: Size,
}

impl Console {

    pub fn new(size: Size) -> Console {
        tcod::system::set_fps(60);

        let (width, height) = size.as_tuple();
        let console = tcod::RootConsole::initializer()
                        .size(width, height)
                        .title("rslike")
                        .font("assets/fonts/terminal12x12_gs_ro.png", tcod::FontLayout::AsciiInRow)
                        .font_type(tcod::FontType::Greyscale)
                        .init();

        Console {
            console: console,
            size: size,
        }
    }

}

impl Console {

    pub fn put_plain(&mut self, pos: Point, c: char) {
        self.console.put_char(pos.x, pos.y, c, tcod::BackgroundFlag::None);
    }

    pub fn put(&mut self, pos: Point, c: char, f_color: Color, b_color: Color) {
        self.console.put_char_ex(pos.x, pos.y, c, f_color, b_color);
    }

    pub fn print_plain(&mut self, pos: Point, text: &str) {
        self.console.print_ex(pos.x, pos.y, tcod::BackgroundFlag::None, tcod::TextAlignment::Left, text);
    }

    pub fn print(&mut self, pos: Point, text: &str, f_color: Color, b_color: Color) {
        self.console.set_default_background(b_color);
        self.console.set_default_foreground(f_color);
        self.console.print_ex(pos.x, pos.y, tcod::BackgroundFlag::None, tcod::TextAlignment::Left, text);
        self.console.set_default_background(Colors::BLACK);
        self.console.set_default_foreground(Colors::WHITE);
    }

    pub fn print_align(&mut self, pos: Point, text: &str, alignment: tcod::TextAlignment) {
        self.console.print_ex(pos.x, pos.y, tcod::BackgroundFlag::None, alignment, text);
    }

    pub fn clear(&mut self) {
        self.console.clear();
    }

    pub fn flush(&mut self) {
        self.console.flush();
    }

    pub fn check_for_keypress(&mut self) -> Option<Key> {
        let check_key = self.console.check_for_keypress(tcod::input::KEY_PRESSED);

        match check_key {
            Some(keypress) => {
                match keypress.key {
                    tcod::input::Key::Special(tcod::input::KeyCode::Up) => Some(Key::Up),
                    tcod::input::Key::Special(tcod::input::KeyCode::Down) => Some(Key::Down),
                    tcod::input::Key::Special(tcod::input::KeyCode::Left) => Some(Key::Left),
                    tcod::input::Key::Special(tcod::input::KeyCode::Right) => Some(Key::Right),
                    tcod::input::Key::Special(tcod::input::KeyCode::Escape) => Some(Key::Escape),
                    tcod::input::Key::Special(tcod::input::KeyCode::Enter) => Some(Key::Enter),
                    _ => None
                }
            }
            _ => None
        }
    }

    pub fn size(&self) -> Size {
        self.size
    }

    pub fn window_closed(&self) -> bool {
        self.console.window_closed()
    }

}
<commit_msg>Fixed passing Path to the new tcod-rs Root builder API<commit_after>use gui::{Color, Colors};
use util::units::{AsTuple, Point, Size};

use tcod;
use tcod::Console as TCODConsole;

use std::path::Path;

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Key {
    Up,
    Down,
    Left,
    Right,
    Escape,
    Enter,
}

pub struct Console {
    console: tcod::RootConsole,
    size: Size,
}

impl Console {

    pub fn new(size: Size) -> Console {
        tcod::system::set_fps(60);

        let (width, height) = size.as_tuple();
        let console = tcod::RootConsole::initializer()
                        .size(width, height)
                        .title("rslike")
                        .font(Path::new("assets/fonts/terminal12x12_gs_ro.png"), tcod::FontLayout::AsciiInRow)
                        .font_type(tcod::FontType::Greyscale)
                        .init();

        Console {
            console: console,
            size: size,
        }
    }

}

impl Console {

    pub fn put_plain(&mut self, pos: Point, c: char) {
        self.console.put_char(pos.x, pos.y, c, tcod::BackgroundFlag::None);
    }

    pub fn put(&mut self, pos: Point, c: char, f_color: Color, b_color: Color) {
        self.console.put_char_ex(pos.x, pos.y, c, f_color, b_color);
    }

    pub fn print_plain(&mut self, pos: Point, text: &str) {
        self.console.print_ex(pos.x, pos.y, tcod::BackgroundFlag::None, tcod::TextAlignment::Left, text);
    }

    pub fn print(&mut self, pos: Point, text: &str, f_color: Color, b_color: Color) {
        self.console.set_default_background(b_color);
        self.console.set_default_foreground(f_color);
        self.console.print_ex(pos.x, pos.y, tcod::BackgroundFlag::None, tcod::TextAlignment::Left, text);
        self.console.set_default_background(Colors::BLACK);
        self.console.set_default_foreground(Colors::WHITE);
    }

    pub fn print_align(&mut self, pos: Point, text: &str, alignment: tcod::TextAlignment) {
        self.console.print_ex(pos.x, pos.y, tcod::BackgroundFlag::None, alignment, text);
    }

    pub fn clear(&mut self) {
        self.console.clear();
    }

    pub fn flush(&mut self) {
        self.console.flush();
    }

    pub fn check_for_keypress(&mut self) -> Option<Key> {
        let check_key = self.console.check_for_keypress(tcod::input::KEY_PRESSED);

        match check_key {
            Some(keypress) => {
                match keypress.key {
                    tcod::input::Key::Special(tcod::input::KeyCode::Up) => Some(Key::Up),
                    tcod::input::Key::Special(tcod::input::KeyCode::Down) => Some(Key::Down),
                    tcod::input::Key::Special(tcod::input::KeyCode::Left) => Some(Key::Left),
                    tcod::input::Key::Special(tcod::input::KeyCode::Right) => Some(Key::Right),
                    tcod::input::Key::Special(tcod::input::KeyCode::Escape) => Some(Key::Escape),
                    tcod::input::Key::Special(tcod::input::KeyCode::Enter) => Some(Key::Enter),
                    _ => None
                }
            }
            _ => None
        }
    }

    pub fn size(&self) -> Size {
        self.size
    }

    pub fn window_closed(&self) -> bool {
        self.console.window_closed()
    }

}
<|endoftext|>