<commit_before>use std::collections::BTreeSet;

use value::{Value, Field, Tuple};
use relation::{Relation, SingleSelect, Reference, MultiSelect};
use primitive::Primitive;

#[derive(Clone, Debug)]
pub struct Table {
    pub insert: Option<SingleSelect>,
    pub remove: Option<SingleSelect>,
}

#[derive(Clone, Debug)]
pub struct Union {
    pub selects: Vec<SingleSelect>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ConstraintOp {
    EQ,
    NEQ,
    LT,
    GT,
    LTE,
    GTE,
}

#[derive(Clone, Debug)]
pub struct Constraint {
    pub left: Reference,
    pub op: ConstraintOp,
    pub right: Reference,
}

impl Constraint {
    fn is_satisfied_by(&self, tuples: &[Tuple]) -> bool {
        let left = self.left.resolve(tuples);
        let right = self.right.resolve(tuples);
        match self.op {
            ConstraintOp::EQ => left == right,
            ConstraintOp::NEQ => left != right,
            ConstraintOp::LT => left < right,
            ConstraintOp::GT => left > right,
            ConstraintOp::LTE => left <= right,
            ConstraintOp::GTE => left >= right,
        }
    }
}

#[derive(Clone, Debug)]
pub enum JoinSource {
    Relation{
        input: usize
    },
    Primitive{
        primitive: Primitive,
        arguments: Vec<Reference>,
        fields: Vec<Field>,
        // TODO `fields` is here just to hack a Tuple in - will go away when we stop using Tuple
    },
}

#[derive(Clone, Debug)]
pub struct Join {
    pub sources: Vec<JoinSource>,
    pub constraints: Vec<Vec<Constraint>>,
    pub select: MultiSelect,
}

#[derive(Clone, Debug)]
pub struct Reducer {
    pub primitive: Primitive,
    pub arguments: Vec<Reference>,
    pub fields: Vec<Field>,
    // TODO `fields` is here just to hack a Tuple in - will go away when we stop using Tuple
}

#[derive(Clone, Debug)]
pub struct Aggregate {
    pub outer: SingleSelect,
    pub inner: SingleSelect,
    pub limit_from: Option<Reference>,
    pub limit_to: Option<Reference>,
    pub reducers: Vec<Reducer>,
    pub selects_inner: bool,
    pub select: MultiSelect,
}

#[derive(Clone, Debug)]
pub enum View {
    Table(Table),
    Union(Union),
    Join(Join),
    Aggregate(Aggregate),
}

fn join_step<'a>(join: &'a Join, inputs: &[&'a Relation], tuples: &mut Vec<Tuple<'a>>, index: &mut BTreeSet<Vec<Value>>) {
    let ix = tuples.len();
    if ix == join.sources.len() {
        index.insert(join.select.select(&tuples[..]));
    } else {
        match join.sources[ix] {
            JoinSource::Relation{input} => {
                for tuple in inputs[input].iter() {
                    tuples.push(tuple);
                    if join.constraints[ix].iter().all(|constraint| constraint.is_satisfied_by(&tuples[..])) {
                        join_step(join, inputs, tuples, index)
                    }
                    tuples.pop();
                }
            }
            JoinSource::Primitive{ref primitive, ref arguments, ref fields} => {
                for values in primitive.eval_from_join(&arguments[..], &tuples[..]).into_iter() {
                    let tuple = Tuple{fields: &fields[..], names: &fields[..], values: &values[..]};
                    // promise the borrow checker that we will pop `tuple` before leaving this scope
                    let tuple = unsafe{ ::std::mem::transmute::<Tuple, Tuple<'a>>(tuple) };
                    tuples.push(tuple);
                    if join.constraints[ix].iter().all(|constraint| constraint.is_satisfied_by(&tuples[..])) {
                        join_step(join, inputs, tuples, index)
                    }
                    tuples.pop();
                }
            }
        }
    }
}

fn aggregate_step<'a>(aggregate: &Aggregate, input_fields: &[&[Field]], input_sets: &'a [&[Vec<Value>]], tuples: &mut Vec<Tuple<'a>>, index: &mut BTreeSet<Vec<Value>>) {
    if input_fields.len() == 0 {
        aggregate.select.select(&tuples[..]);
    } else {
        for values in input_sets[0].iter() {
            let tuple = Tuple{fields: input_fields[0], names: input_fields[0], values: &values[..]};
            // promise the borrow checker that we will pop `tuple` before leaving this scope
            let tuple = unsafe{ ::std::mem::transmute::<Tuple, Tuple<'a>>(tuple) };
            tuples.push(tuple);
            aggregate_step(aggregate, &input_fields[1..], &input_sets[1..], tuples, index);
            tuples.pop();
        }
    }
}

impl View {
    pub fn run(&self, old_output: &Relation, inputs: &[&Relation]) -> Option<Relation> {
        match *self {
            View::Table(_) => None,
            View::Union(ref union) => {
                assert_eq!(union.selects.len(), inputs.len());
                let mut output = Relation::with_fields(old_output.fields.clone(), old_output.names.clone());
                for select in union.selects.iter() {
                    for values in select.select(&inputs[..]) {
                        output.index.insert(values);
                    }
                }
                Some(output)
            }
            View::Join(ref join) => {
                let mut output = Relation::with_fields(old_output.fields.clone(), old_output.names.clone());
                let mut tuples = Vec::with_capacity(join.sources.len());
                join_step(join, inputs, &mut tuples, &mut output.index);
                Some(output)
            }
            View::Aggregate(ref aggregate) => {
                let mut output = Relation::with_fields(old_output.fields.clone(), old_output.names.clone());
                let mut outer = aggregate.outer.select(&inputs[..]);
                let mut inner = aggregate.inner.select(&inputs[..]);
                outer.sort();
                outer.dedup();
                inner.sort();
                let mut group_start = 0;
                for outer_values in outer.into_iter() {
                    let mut group_end = group_start;
                    while (group_end < inner.len())
                    && (inner[group_end][0..outer_values.len()] == outer_values[..]) {
                        group_end += 1;
                    }
                    let (group, output_values) = {
                        let outer_tuple = Tuple{
                            fields: &aggregate.outer.fields[..],
                            names: &aggregate.outer.fields[..],
                            values: &outer_values[..]
                        };
                        let limit_inputs = &[outer_tuple.clone()];
                        let limit_from = match aggregate.limit_from {
                            None => group_start,
                            Some(ref reference) => group_start + reference.resolve(limit_inputs).as_usize(),
                        };
                        let limit_to = match aggregate.limit_to {
                            None => group_end,
                            Some(ref reference) => group_start + reference.resolve(limit_inputs).as_usize(),
                        };
                        let limit_from = ::std::cmp::min(::std::cmp::max(limit_from, group_start), group_end);
                        let limit_to = ::std::cmp::min(::std::cmp::max(limit_to, limit_from), group_end);
                        let group = &inner[limit_from..limit_to];
                        let output_values = aggregate.reducers.iter().map(|reducer| {
                            reducer.primitive.eval_from_aggregate(&reducer.arguments[..], &outer_tuple, &aggregate.inner.fields[..], group)
                        }).collect::<Vec<_>>();
                        (group, output_values)
                    };
                    let outer_items = vec![outer_values];
                    let mut output_fields = aggregate.reducers.iter().map(|reducer|
                        &reducer.fields[..]
                        ).collect::<Vec<_>>();
                    let mut output_sets = output_values.iter().map(|values|
                        &values[..]
                        ).collect::<Vec<_>>();
                    output_fields.push(&aggregate.outer.fields[..]);
                    output_sets.push(&outer_items[..]);
                    if aggregate.selects_inner {
                        output_fields.push(&aggregate.inner.fields[..]);
                        output_sets.push(group);
                    }
                    let mut tuples = Vec::with_capacity(output_fields.len());
                    aggregate_step(aggregate, &output_fields[..], &output_sets[..], &mut tuples, &mut output.index);
                    group_start = group_end;
                }
                Some(output)
            }
        }
    }
}<commit_msg>Yeah, you have to actually insert the results<commit_after>use std::collections::BTreeSet;

use value::{Value, Field, Tuple};
use relation::{Relation, SingleSelect, Reference, MultiSelect};
use primitive::Primitive;

#[derive(Clone, Debug)]
pub struct Table {
    pub insert: Option<SingleSelect>,
    pub remove: Option<SingleSelect>,
}

#[derive(Clone, Debug)]
pub struct Union {
    pub selects: Vec<SingleSelect>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ConstraintOp {
    EQ,
    NEQ,
    LT,
    GT,
    LTE,
    GTE,
}

#[derive(Clone, Debug)]
pub struct Constraint {
    pub left: Reference,
    pub op: ConstraintOp,
    pub right: Reference,
}

impl Constraint {
    fn is_satisfied_by(&self, tuples: &[Tuple]) -> bool {
        let left = self.left.resolve(tuples);
        let right = self.right.resolve(tuples);
        match self.op {
            ConstraintOp::EQ => left == right,
            ConstraintOp::NEQ => left != right,
            ConstraintOp::LT => left < right,
            ConstraintOp::GT => left > right,
            ConstraintOp::LTE => left <= right,
            ConstraintOp::GTE => left >= right,
        }
    }
}

#[derive(Clone, Debug)]
pub enum JoinSource {
    Relation{
        input: usize
    },
    Primitive{
        primitive: Primitive,
        arguments: Vec<Reference>,
        fields: Vec<Field>,
        // TODO `fields` is here just to hack a Tuple in - will go away when we stop using Tuple
    },
}

#[derive(Clone, Debug)]
pub struct Join {
    pub sources: Vec<JoinSource>,
    pub constraints: Vec<Vec<Constraint>>,
    pub select: MultiSelect,
}

#[derive(Clone, Debug)]
pub struct Reducer {
    pub primitive: Primitive,
    pub arguments: Vec<Reference>,
    pub fields: Vec<Field>,
    // TODO `fields` is here just to hack a Tuple in - will go away when we stop using Tuple
}

#[derive(Clone, Debug)]
pub struct Aggregate {
    pub outer: SingleSelect,
    pub inner: SingleSelect,
    pub limit_from: Option<Reference>,
    pub limit_to: Option<Reference>,
    pub reducers: Vec<Reducer>,
    pub selects_inner: bool,
    pub select: MultiSelect,
}

#[derive(Clone, Debug)]
pub enum View {
    Table(Table),
    Union(Union),
    Join(Join),
    Aggregate(Aggregate),
}

fn join_step<'a>(join: &'a Join, inputs: &[&'a Relation], tuples: &mut Vec<Tuple<'a>>, index: &mut BTreeSet<Vec<Value>>) {
    let ix = tuples.len();
    if ix == join.sources.len() {
        index.insert(join.select.select(&tuples[..]));
    } else {
        match join.sources[ix] {
            JoinSource::Relation{input} => {
                for tuple in inputs[input].iter() {
                    tuples.push(tuple);
                    if join.constraints[ix].iter().all(|constraint| constraint.is_satisfied_by(&tuples[..])) {
                        join_step(join, inputs, tuples, index)
                    }
                    tuples.pop();
                }
            }
            JoinSource::Primitive{ref primitive, ref arguments, ref fields} => {
                for values in primitive.eval_from_join(&arguments[..], &tuples[..]).into_iter() {
                    let tuple = Tuple{fields: &fields[..], names: &fields[..], values: &values[..]};
                    // promise the borrow checker that we will pop `tuple` before leaving this scope
                    let tuple = unsafe{ ::std::mem::transmute::<Tuple, Tuple<'a>>(tuple) };
                    tuples.push(tuple);
                    if join.constraints[ix].iter().all(|constraint| constraint.is_satisfied_by(&tuples[..])) {
                        join_step(join, inputs, tuples, index)
                    }
                    tuples.pop();
                }
            }
        }
    }
}

fn aggregate_step<'a>(aggregate: &Aggregate, input_fields: &[&[Field]], input_sets: &'a [&[Vec<Value>]], tuples: &mut Vec<Tuple<'a>>, index: &mut BTreeSet<Vec<Value>>) {
    if input_fields.len() == 0 {
        index.insert(aggregate.select.select(&tuples[..]));
    } else {
        for values in input_sets[0].iter() {
            let tuple = Tuple{fields: input_fields[0], names: input_fields[0], values: &values[..]};
            // promise the borrow checker that we will pop `tuple` before leaving this scope
            let tuple = unsafe{ ::std::mem::transmute::<Tuple, Tuple<'a>>(tuple) };
            tuples.push(tuple);
            aggregate_step(aggregate, &input_fields[1..], &input_sets[1..], tuples, index);
            tuples.pop();
        }
    }
}

impl View {
    pub fn run(&self, old_output: &Relation, inputs: &[&Relation]) -> Option<Relation> {
        match *self {
            View::Table(_) => None,
            View::Union(ref union) => {
                assert_eq!(union.selects.len(), inputs.len());
                let mut output = Relation::with_fields(old_output.fields.clone(), old_output.names.clone());
                for select in union.selects.iter() {
                    for values in select.select(&inputs[..]) {
                        output.index.insert(values);
                    }
                }
                Some(output)
            }
            View::Join(ref join) => {
                let mut output = Relation::with_fields(old_output.fields.clone(), old_output.names.clone());
                let mut tuples = Vec::with_capacity(join.sources.len());
                join_step(join, inputs, &mut tuples, &mut output.index);
                Some(output)
            }
            View::Aggregate(ref aggregate) => {
                let mut output = Relation::with_fields(old_output.fields.clone(), old_output.names.clone());
                let mut outer = aggregate.outer.select(&inputs[..]);
                let mut inner = aggregate.inner.select(&inputs[..]);
                outer.sort();
                outer.dedup();
                inner.sort();
                let mut group_start = 0;
                for outer_values in outer.into_iter() {
                    let mut group_end = group_start;
                    while (group_end < inner.len())
                    && (inner[group_end][0..outer_values.len()] == outer_values[..]) {
                        group_end += 1;
                    }
                    let (group, output_values) = {
                        let outer_tuple = Tuple{
                            fields: &aggregate.outer.fields[..],
                            names: &aggregate.outer.fields[..],
                            values: &outer_values[..]
                        };
                        let limit_inputs = &[outer_tuple.clone()];
                        let limit_from = match aggregate.limit_from {
                            None => group_start,
                            Some(ref reference) => group_start + reference.resolve(limit_inputs).as_usize(),
                        };
                        let limit_to = match aggregate.limit_to {
                            None => group_end,
                            Some(ref reference) => group_start + reference.resolve(limit_inputs).as_usize(),
                        };
                        let limit_from = ::std::cmp::min(::std::cmp::max(limit_from, group_start), group_end);
                        let limit_to = ::std::cmp::min(::std::cmp::max(limit_to, limit_from), group_end);
                        let group = &inner[limit_from..limit_to];
                        let output_values = aggregate.reducers.iter().map(|reducer| {
                            reducer.primitive.eval_from_aggregate(&reducer.arguments[..], &outer_tuple, &aggregate.inner.fields[..], group)
                        }).collect::<Vec<_>>();
                        (group, output_values)
                    };
                    let outer_items = vec![outer_values];
                    let mut output_fields = aggregate.reducers.iter().map(|reducer|
                        &reducer.fields[..]
                        ).collect::<Vec<_>>();
                    let mut output_sets = output_values.iter().map(|values|
                        &values[..]
                        ).collect::<Vec<_>>();
                    output_fields.push(&aggregate.outer.fields[..]);
                    output_sets.push(&outer_items[..]);
                    if aggregate.selects_inner {
                        output_fields.push(&aggregate.inner.fields[..]);
                        output_sets.push(group);
                    }
                    let mut tuples = Vec::with_capacity(output_fields.len());
                    aggregate_step(aggregate, &output_fields[..], &output_sets[..], &mut tuples, &mut output.index);
                    group_start = group_end;
                }
                Some(output)
            }
        }
    }
}<|endoftext|>


<commit_before>use consts::{
    CODE_ALPHABET, ENCODING_BASE, LATITUDE_MAX, LONGITUDE_MAX, PAIR_CODE_LENGTH, GRID_ROWS,
    GRID_COLUMNS,
};

use interface::encode;

use geo::Point;

pub fn code_value(chr: char) -> usize {
    // We assume this function is only called by other functions that have
    // already ensured that the characters in the passed-in code are all valid
    // and have all been "treated" (upper-cased, padding and '+' stripped)
    CODE_ALPHABET.iter().position(|&x| x == char).unwrap()
}

pub fn normalize_longitude(value: f64) -> f64 {
    let mut result: f64 = value;
    while result >= LONGITUDE_MAX {
        result -= LONGITUDE_MAX * 2f64;
    }
    while result < -LONGITUDE_MAX{
        result += LONGITUDE_MAX * 2f64;
    }
    result
}

pub fn clip_latitude(latitude_degrees: f64) -> f64 {
    latitude_degrees.min(LATITUDE_MAX).max(-LATITUDE_MAX)
}

pub fn compute_latitude_precision(code_length: usize) -> f64 {
    if code_length <= PAIR_CODE_LENGTH {
        return ENCODING_BASE.powf((code_length as f64 / -2f64 + 2f64).floor())
    }
    ENCODING_BASE.powi(-3f64) / GRID_ROWS.powf(code_length as f64 - PAIR_CODE_LENGTH as f64)
}

pub fn prefix_by_reference(pt: Point<f64>, code_length: usize) -> String {
    let precision = compute_latitude_precision(code_length);
    let mut code = encode(
        Point::new(
            (pt.lng() / precision).floor() * precision,
            (pt.lat() / precision).floor() * precision
        ),
        PAIR_CODE_LENGTH
    );
    code.drain(code_length..);
    code
}

pub fn near(value: f64) -> bool {
    // Detects real values that are "very near" the next integer value
    // returning true when this is the case.
    //
    // I'm not particularly happy with this function, but I am at a loss
    // for another (better?) way to achieve the required behaviour.
    value.trunc() != (value + 0.0000000001f64).trunc()
}

pub fn narrow_region(digit: usize, lat: &mut f64, lng: &mut f64) {
    if digit == 0 {
        *lat /= ENCODING_BASE;
        *lng /= ENCODING_BASE;
    } else if digit < PAIR_CODE_LENGTH {
        *lat *= ENCODING_BASE;
        *lng *= ENCODING_BASE;
    } else {
        *lat *= GRID_ROWS;
        *lng *= GRID_COLUMNS
    }
    if near(*lat) {
        *lat = lat.round();
    }
    if near(*lng) {
        *lng = lng.round();
    }
}
<commit_msg>Update private.rs<commit_after>use consts::{
    CODE_ALPHABET, ENCODING_BASE, LATITUDE_MAX, LONGITUDE_MAX, PAIR_CODE_LENGTH, GRID_ROWS,
    GRID_COLUMNS,
};

use interface::encode;

use geo::Point;

pub fn code_value(chr: char) -> usize {
    // We assume this function is only called by other functions that have
    // already ensured that the characters in the passed-in code are all valid
    // and have all been "treated" (upper-cased, padding and '+' stripped)
    CODE_ALPHABET.iter().position(|&x| x == char).unwrap()
}

pub fn normalize_longitude(value: f64) -> f64 {
    let mut result: f64 = value;
    while result >= LONGITUDE_MAX {
        result -= LONGITUDE_MAX * 2f64;
    }
    while result < -LONGITUDE_MAX{
        result += LONGITUDE_MAX * 2f64;
    }
    result
}

pub fn clip_latitude(latitude_degrees: f64) -> f64 {
    latitude_degrees.min(LATITUDE_MAX).max(-LATITUDE_MAX)
}

pub fn compute_latitude_precision(code_length: usize) -> f64 {
    if code_length <= PAIR_CODE_LENGTH {
        return ENCODING_BASE.powf((code_length as f64 / -2f64 + 2f64).floor())
    }
    ENCODING_BASE.powi(-3i32) / GRID_ROWS.powf(code_length as f64 - PAIR_CODE_LENGTH as f64)
}

pub fn prefix_by_reference(pt: Point<f64>, code_length: usize) -> String {
    let precision = compute_latitude_precision(code_length);
    let mut code = encode(
        Point::new(
            (pt.lng() / precision).floor() * precision,
            (pt.lat() / precision).floor() * precision
        ),
        PAIR_CODE_LENGTH
    );
    code.drain(code_length..);
    code
}

pub fn near(value: f64) -> bool {
    // Detects real values that are "very near" the next integer value
    // returning true when this is the case.
    //
    // I'm not particularly happy with this function, but I am at a loss
    // for another (better?) way to achieve the required behaviour.
    value.trunc() != (value + 0.0000000001f64).trunc()
}

pub fn narrow_region(digit: usize, lat: &mut f64, lng: &mut f64) {
    if digit == 0 {
        *lat /= ENCODING_BASE;
        *lng /= ENCODING_BASE;
    } else if digit < PAIR_CODE_LENGTH {
        *lat *= ENCODING_BASE;
        *lng *= ENCODING_BASE;
    } else {
        *lat *= GRID_ROWS;
        *lng *= GRID_COLUMNS
    }
    if near(*lat) {
        *lat = lat.round();
    }
    if near(*lng) {
        *lng = lng.round();
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

extern crate csv;
extern crate hex;
extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate image;
extern crate piston_window;

mod cpu;
mod gpu;
mod system;

use piston_window::*;
use image::ImageBuffer;
use image::{RgbaImage, Rgba};
use opengl_graphics::Texture;
use piston::event_loop::*;
use piston::input::*;
use opengl_graphics::{ GlGraphics, OpenGL };
use std::fs::File;
use std::io::prelude::*;
use std::env;
use cpu::cpu::*;
use gpu::gpu::*;
use gpu::gpu_registers::*;
use system::*;
use self::hex::FromHex;

static MAX_SPRITE: u8 = 40;

fn main()
 {
    //Initialize Emulator
    let args: Vec<String> = env::args().collect();
    let emulator_type: String = String::from("CLASSIC");
    let file_name: &String = &args[1];
    let mut system_data : SystemData = get_system_data(&emulator_type);
    system_data.mem_map = read_gb_file(file_name);
    let mut registers: Registers = Registers::new();
    let mut gpu_registers: GPU_Registers = GPU_Registers::new();

    //Initialize Screen
    let opengl = OpenGL::V3_2;
    let mut window: PistonWindow = WindowSettings::new("RustBoy", [system_data.width as u32, system_data.height as u32]).opengl(opengl).exit_on_esc(true).build().unwrap();
    //window.set_max_fps(60);
    let mut app = App
    {
        gl: GlGraphics::new(opengl),
    };
    let mut events = Events::new(EventSettings::new().max_fps(60));
    //events.set_max_fps(60);
    let mut background_tile_map: TileMap = TileMap::new();
    let mut window_tile_map: TileMap = TileMap::new();

    //Operation loop
    let mut emulator_loop = true;

    while let Some(e) = events.next(&mut window)
    {

        if let Some(r) = e.render_args(){
            gpu_registers.v_blank_draw_flag = false;
            background_tile_map.populate_tile_map(&mut system_data, gpu_registers.lcdc_register.tile_data, gpu_registers.lcdc_register.background_display_select);
            window_tile_map.populate_tile_map(&mut system_data, gpu_registers.lcdc_register.tile_data, gpu_registers.lcdc_register.window_display_select);
            let background_image: RgbaImage = create_background_img(&background_tile_map);
            app.render(&background_image, &r);
            // break;
        }

        if let Some(r) = e.update_args()
        {
            while !gpu_registers.v_blank_draw_flag
            {
                let opcode = system_data.mem_map[registers.program_counter as usize];
                let address = registers.program_counter;
                cpu_continue(&mut system_data, &mut registers);
                update_gpu(&mut system_data, &mut registers, &mut gpu_registers);
            }
        }
    }
        // if system_data.cycles == 0  //|| registers.program_counter == 0x6d
        // {
        //     emulator_loop = false;
        //     println!("Location: {:04X}\tOpcode: 0x{:02X}  {:08b}", address, opcode, opcode);
        // }
    //Cleanup?
}

pub struct App
{
    gl: GlGraphics
}

impl App
{
    fn render(&mut self, img: &RgbaImage, args: &RenderArgs)
    {
            use graphics::*;
            let BLANK: types::Color = color::hex("9CBD0F");
            let square = rectangle::square(0.0, 0.0, 50.0);

            let tile = Texture::from_image(img, &TextureSettings::new());

            self.gl.draw(args.viewport(), |c, gl|
            {
                clear(BLANK, gl);
                let transform = c.transform.trans(0.0,0.0);
                image(&tile, transform, gl);
            });
    }
}

fn read_gb_file(file_name: &str) -> Vec<u8>
{
    let mut buffer : Vec<u8> = vec![0; 0x10000];
    let file = File::open(file_name);
    if file.is_ok()
    {
        if file.unwrap().read(&mut buffer).is_ok()
        {
            return buffer;
        }
    }
    return vec![0;0];
}

fn create_tile_img(tile_data: &TileData) -> RgbaImage
{
    let mut buffer = ImageBuffer::new(8,8);
    for pixel_y in 0..8
    {
        for pixel_x in 0..8
        {
            let pixel_data = tile_data.data[(pixel_y * 8) + pixel_x];
            let mut pixel : Rgba<u8>;
            pixel = pixel_color_map(pixel_data);
            buffer.put_pixel(pixel_x as u32, pixel_y as u32, pixel);
        }
    }
    return buffer;
}

fn create_background_img(background_tile_map: &TileMap) -> RgbaImage
{
    let mut buffer = ImageBuffer::new(256, 256);
    for tile_y in 0..32
    {
        for tile_x in 0..32
        {
            for pixel_y in 0..8
            {
                for pixel_x in 0..8
                {
                    let tile = background_tile_map.map[(tile_y * 32) + tile_x];
                    let pixel_data = background_tile_map.tiles[tile as usize].data[(pixel_y * 8) + pixel_x];
                    let pixel = pixel_color_map(pixel_data);
                    buffer.put_pixel(((tile_x *32 ) + pixel_x) as u32, ((tile_y) + pixel_y) as u32, pixel);
                }
            }
        }
    }
    return buffer;
}

fn pixel_color_map(pixel_data: u8) -> Rgba<u8>
{
    match pixel_data
    {
        0 => return Rgba([156,189,15, 0xFF]),
        1 => return Rgba([140,173,15, 0xFF]),
        2 => return Rgba([48,98,48, 0xFF]),
        3 => return Rgba([15, 56, 15, 0xFF]),
        _ => return Rgba([0, 0, 0, 0xFF]),
    }
}

fn output_mem_selection(mem_map: &Vec<u8>, start: u16, end:u16)
{
    for index in start .. end
    {
        print!("{}-{:x}\t", index, mem_map[index as usize]);
    }
    print!("\n");
}

#[cfg(test)]
mod main_tests
{
    use read_gb_file;

    #[test]
    fn passing_bad_filename_to_read_gb_file_return_empty_vec()
    {
        let return_vector : Vec<u8> = read_gb_file("");
        assert_eq!(return_vector, vec![0;0]);
    }
}
<commit_msg>Fixed frame creation settings<commit_after>#![allow(dead_code)]

extern crate csv;
extern crate hex;
extern crate piston;
extern crate graphics;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate image;
extern crate piston_window;

mod cpu;
mod gpu;
mod system;

use piston_window::*;
use image::ImageBuffer;
use image::{RgbaImage, Rgba};
use opengl_graphics::Texture;
use piston::event_loop::*;
use piston::input::*;
use opengl_graphics::{ GlGraphics, OpenGL };
use std::fs::File;
use std::io::prelude::*;
use std::env;
use cpu::cpu::*;
use gpu::gpu::*;
use gpu::gpu_registers::*;
use system::*;
use self::hex::FromHex;

static MAX_SPRITE: u8 = 40;

fn main()
 {
    //Initialize Emulator
    let args: Vec<String> = env::args().collect();
    let emulator_type: String = String::from("CLASSIC");
    let file_name: &String = &args[1];
    let mut system_data : SystemData = get_system_data(&emulator_type);
    system_data.mem_map = read_gb_file(file_name);
    let mut registers: Registers = Registers::new();
    let mut gpu_registers: GPU_Registers = GPU_Registers::new();

    //Initialize Screen
    let opengl = OpenGL::V3_2;
    let mut window: PistonWindow = WindowSettings::new("RustBoy", [system_data.width as u32, system_data.height as u32])
                                        .opengl(opengl)
                                        .exit_on_esc(true)
                                        .build()
                                        .unwrap();
    //window.set_max_fps(60);
    let mut app = App
    {
        gl: GlGraphics::new(opengl),
    };
    let mut events = Events::new(EventSettings::new().max_fps(60));
    //events.set_max_fps(60);
    let mut background_tile_map: TileMap = TileMap::new();
    let mut window_tile_map: TileMap = TileMap::new();

    //Operation loop
    let mut emulator_loop = true;

    while let Some(e) = events.next(&mut window)
    {
        if let Some(r) = e.update_args()
        {
            while !gpu_registers.v_blank_draw_flag
            {
                let opcode = system_data.mem_map[registers.program_counter as usize];
                let address = registers.program_counter;
                cpu_continue(&mut system_data, &mut registers);
                update_gpu(&mut system_data, &mut registers, &mut gpu_registers);
            }
        }

        if let Some(r) = e.render_args(){
            gpu_registers.v_blank_draw_flag = false;
            background_tile_map.populate_tile_map(&mut system_data, gpu_registers.lcdc_register.tile_data, gpu_registers.lcdc_register.background_display_select);
            window_tile_map.populate_tile_map(&mut system_data, gpu_registers.lcdc_register.tile_data, gpu_registers.lcdc_register.window_display_select);
            //let background_image: RgbaImage = create_background_img(&background_tile_map);
            let background_image: RgbaImage = create_background_img(&window_tile_map);
            app.render(&background_image, &r);
            // break;
        }
    }
        // if system_data.cycles == 0  //|| registers.program_counter == 0x6d
        // {
        //     emulator_loop = false;
        //     println!("Location: {:04X}\tOpcode: 0x{:02X}  {:08b}", address, opcode, opcode);
        // }
    //Cleanup?
}

pub struct App
{
    gl: GlGraphics
}

impl App
{
    fn render(&mut self, img: &RgbaImage, args: &RenderArgs)
    {
            use graphics::*;
            let BLANK: types::Color = color::hex("9CBD0F");
            let tile = Texture::from_image(&img, &TextureSettings::new());

            self.gl.draw(args.viewport(), |c, gl|
            {
                clear(color::BLACK, gl);
                let transform = c.transform.trans(0.0,0.0);
                image(&tile, transform, gl);
            });
    }
}

fn read_gb_file(file_name: &str) -> Vec<u8>
{
    let mut buffer : Vec<u8> = vec![0; 0x10000];
    let file = File::open(file_name);
    if file.is_ok()
    {
        if file.unwrap().read(&mut buffer).is_ok()
        {
            return buffer;
        }
    }
    return vec![0;0];
}

fn create_background_img(background_tile_map: &TileMap) -> RgbaImage
{

    let mut buffer = ImageBuffer::new(256, 256);
    for tile_y in 0..32
    {
        for tile_x in 0..32
        {
            for pixel_y in 0..8
            {
                for pixel_x in 0..8
                {
                    let tile = background_tile_map.map[(tile_y * 32) + tile_x];
                    let pixel_data = background_tile_map.tiles[tile as usize].data[(pixel_y * 8) + pixel_x];
                    let pixel = pixel_color_map(pixel_data);
                    buffer.put_pixel(((tile_x * 8) + pixel_x) as u32, ((tile_y * 8) + pixel_y) as u32, pixel);
                }
            }
        }
    }
    return buffer;
}

fn pixel_color_map(pixel_data: u8) -> Rgba<u8>
{
    match pixel_data
    {
        0 => return Rgba([156,189,15, 0xFF]),
        1 => return Rgba([140,173,15, 0xFF]),
        2 => return Rgba([48,98,48, 0xFF]),
        3 => return Rgba([15, 56, 15, 0xFF]),
        _ => return Rgba([0, 0, 0, 0xFF]),
    }
}

fn output_mem_selection(mem_map: &Vec<u8>, start: u16, end:u16)
{
    for index in start .. end
    {
        print!("{}-{:x}\t", index, mem_map[index as usize]);
    }
    print!("\n");
}

#[cfg(test)]
mod main_tests
{
    use read_gb_file;

    #[test]
    fn passing_bad_filename_to_read_gb_file_return_empty_vec()
    {
        let return_vector : Vec<u8> = read_gb_file("");
        assert_eq!(return_vector, vec![0;0]);
    }
}
<|endoftext|>


<commit_before>// spell-checker:ignore udev pcent
use crate::common::util::*;

#[test]
fn test_df_compatible_no_size_arg() {
    new_ucmd!().arg("-a").succeeds();
}

#[test]
fn test_df_shortened_long_argument() {
    new_ucmd!().arg("--a").succeeds();
}

#[test]
fn test_df_compatible() {
    new_ucmd!().arg("-ah").succeeds();
}

#[test]
fn test_df_compatible_type() {
    new_ucmd!().arg("-aT").succeeds();
}

#[test]
fn test_df_compatible_si() {
    new_ucmd!().arg("-aH").succeeds();
}

#[test]
fn test_df_output() {
    // TODO These should fail because `-total` should have two dashes,
    // not just one. But they don't fail.
    if cfg!(target_os = "macos") {
        new_ucmd!().arg("-H").arg("-total").succeeds().
        stdout_only("Filesystem               Size         Used    Available     Capacity  Use% Mounted on       \n");
    } else {
        new_ucmd!().arg("-H").arg("-total").succeeds().stdout_only(
            "Filesystem               Size         Used    Available  Use% Mounted on       \n",
        );
    }
}

/// Test that the order of rows in the table does not change across executions.
#[test]
fn test_order_same() {
    let output1 = new_ucmd!()
        .arg("--output=source")
        .succeeds()
        .stdout_move_str();
    let output2 = new_ucmd!()
        .arg("--output=source")
        .succeeds()
        .stdout_move_str();
    assert_eq!(output1, output2);
}

/// Test of mount point begin repeated
#[cfg(unix)]
#[test]
fn test_output_mp_repeat() {
    let output1 = new_ucmd!().arg("/").arg("/").succeeds().stdout_move_str();
    let output1: Vec<String> = output1
        .lines()
        .map(|l| String::from(l.split_once(' ').unwrap().0))
        .collect();
    assert_eq!(3, output1.len());
    assert_eq!(output1[1], output1[2]);
}
#[test]
fn test_output_conflict_options() {
    for option in ["-i", "-T", "-P"] {
        new_ucmd!().arg("--output=source").arg(option).fails();
    }
}

#[test]
fn test_output_option() {
    new_ucmd!().arg("--output").succeeds();
    new_ucmd!().arg("--output=source,target").succeeds();
    new_ucmd!().arg("--output=invalid_option").fails();
}

#[test]
fn test_output_option_without_equals_sign() {
    new_ucmd!().arg("--output").arg(".").succeeds();
}

#[test]
fn test_type_option() {
    new_ucmd!().args(&["-t", "ext4", "-t", "ext3"]).succeeds();
}

#[test]
fn test_exclude_type_option() {
    new_ucmd!().args(&["-x", "ext4", "-x", "ext3"]).succeeds();
}

#[test]
fn test_include_exclude_same_type() {
    new_ucmd!()
        .args(&["-t", "ext4", "-x", "ext4"])
        .fails()
        .stderr_is("df: file system type 'ext4' both selected and excluded");
    new_ucmd!()
        .args(&["-t", "ext4", "-x", "ext4", "-t", "ext3", "-x", "ext3"])
        .fails()
        .stderr_is(
            "df: file system type 'ext4' both selected and excluded\n\
             df: file system type 'ext3' both selected and excluded",
        );
}

#[test]
fn test_total() {
    // Example output:
    //
    //     Filesystem            1K-blocks     Used Available Use% Mounted on
    //     udev                    3858016        0   3858016   0% /dev
    //     ...
    //     /dev/loop14               63488    63488         0 100% /snap/core20/1361
    //     total                 258775268 98099712 148220200  40% -
    let output = new_ucmd!().arg("--total").succeeds().stdout_move_str();

    // Skip the header line.
    let lines: Vec<&str> = output.lines().skip(1).collect();

    // Parse the values from the last row.
    let last_line = lines.last().unwrap();
    let mut iter = last_line.split_whitespace();
    assert_eq!(iter.next().unwrap(), "total");
    let reported_total_size = iter.next().unwrap().parse().unwrap();
    let reported_total_used = iter.next().unwrap().parse().unwrap();
    let reported_total_avail = iter.next().unwrap().parse().unwrap();

    // Loop over each row except the last, computing the sum of each column.
    let mut computed_total_size = 0;
    let mut computed_total_used = 0;
    let mut computed_total_avail = 0;
    let n = lines.len();
    for line in &lines[..n - 1] {
        let mut iter = line.split_whitespace();
        iter.next().unwrap();
        computed_total_size += iter.next().unwrap().parse::<u64>().unwrap();
        computed_total_used += iter.next().unwrap().parse::<u64>().unwrap();
        computed_total_avail += iter.next().unwrap().parse::<u64>().unwrap();
    }

    // Check that the sum of each column matches the reported value in
    // the last row.
    assert_eq!(computed_total_size, reported_total_size);
    assert_eq!(computed_total_used, reported_total_used);
    assert_eq!(computed_total_avail, reported_total_avail);
}

#[test]
fn test_use_percentage() {
    let output = new_ucmd!()
        .args(&["--total", "--output=used,avail,pcent"])
        .succeeds()
        .stdout_move_str();

    // Skip the header line.
    let lines: Vec<&str> = output.lines().skip(1).collect();

    for line in lines {
        let mut iter = line.split_whitespace();
        let reported_used = iter.next().unwrap().parse::<f64>().unwrap();
        let reported_avail = iter.next().unwrap().parse::<f64>().unwrap();
        let reported_percentage = iter.next().unwrap();
        let reported_percentage = reported_percentage[..reported_percentage.len() - 1]
            .parse::<u8>()
            .unwrap();
        let computed_percentage =
            (100.0 * (reported_used / (reported_used + reported_avail))).ceil() as u8;

        assert_eq!(computed_percentage, reported_percentage);
    }
}

#[test]
fn test_block_size_1024() {
    fn get_header(block_size: u64) -> String {
        // TODO When #3057 is resolved, we should just use
        //
        //     new_ucmd!().arg("--output=size").succeeds().stdout_move_str();
        //
        // instead of parsing the entire `df` table as a string.
        let output = new_ucmd!()
            .args(&["-B", &format!("{}", block_size)])
            .succeeds()
            .stdout_move_str();
        let first_line = output.lines().next().unwrap();
        let mut column_labels = first_line.split_whitespace();
        let size_column_label = column_labels.nth(1).unwrap();
        size_column_label.into()
    }

    assert_eq!(get_header(1024), "1K-blocks");
    assert_eq!(get_header(2048), "2K-blocks");
    assert_eq!(get_header(4096), "4K-blocks");
    assert_eq!(get_header(1024 * 1024), "1M-blocks");
    assert_eq!(get_header(2 * 1024 * 1024), "2M-blocks");
    assert_eq!(get_header(1024 * 1024 * 1024), "1G-blocks");
    assert_eq!(get_header(34 * 1024 * 1024 * 1024), "34G-blocks");
}

// TODO The spacing does not match GNU df. Also we need to remove
// trailing spaces from the heading row.
#[test]
fn test_output_selects_columns() {
    let output = new_ucmd!()
        .args(&["--output=source"])
        .succeeds()
        .stdout_move_str();
    assert_eq!(output.lines().next().unwrap(), "Filesystem       ");

    let output = new_ucmd!()
        .args(&["--output=source,target"])
        .succeeds()
        .stdout_move_str();
    assert_eq!(
        output.lines().next().unwrap(),
        "Filesystem       Mounted on       "
    );

    let output = new_ucmd!()
        .args(&["--output=source,target,used"])
        .succeeds()
        .stdout_move_str();
    assert_eq!(
        output.lines().next().unwrap(),
        "Filesystem       Mounted on               Used "
    );
}

#[test]
fn test_output_multiple_occurrences() {
    let output = new_ucmd!()
        .args(&["--output=source", "--output=target"])
        .succeeds()
        .stdout_move_str();
    assert_eq!(
        output.lines().next().unwrap(),
        "Filesystem       Mounted on       "
    );
}

// TODO Fix the spacing.
#[test]
fn test_output_file_all_filesystems() {
    // When run with no positional arguments, `df` lets "-" represent
    // the "File" entry for each row.
    let output = new_ucmd!()
        .arg("--output=file")
        .succeeds()
        .stdout_move_str();
    let mut lines = output.lines();
    assert_eq!(lines.next().unwrap(), "File            ");
    for line in lines {
        assert_eq!(line, "-               ");
    }
}

// TODO Fix the spacing.
#[test]
fn test_output_file_specific_files() {
    // Create three files.
    let (at, mut ucmd) = at_and_ucmd!();
    at.touch("a");
    at.touch("b");
    at.touch("c");

    // When run with positional arguments, the filesystems should
    // appear in the "File" column.
    let output = ucmd
        .args(&["--output=file", "a", "b", "c"])
        .succeeds()
        .stdout_move_str();
    let actual: Vec<&str> = output.lines().collect();
    assert_eq!(
        actual,
        vec![
            "File            ",
            "a               ",
            "b               ",
            "c               "
        ]
    );
}

#[test]
fn test_output_field_no_more_than_once() {
    new_ucmd!()
        .arg("--output=target,source,target")
        .fails()
        .usage_error("option --output: field 'target' used more than once");
}
<commit_msg>df: correct --total argument used in unit test<commit_after>// spell-checker:ignore udev pcent
use crate::common::util::*;

#[test]
fn test_df_compatible_no_size_arg() {
    new_ucmd!().arg("-a").succeeds();
}

#[test]
fn test_df_shortened_long_argument() {
    new_ucmd!().arg("--a").succeeds();
}

#[test]
fn test_df_compatible() {
    new_ucmd!().arg("-ah").succeeds();
}

#[test]
fn test_df_compatible_type() {
    new_ucmd!().arg("-aT").succeeds();
}

#[test]
fn test_df_compatible_si() {
    new_ucmd!().arg("-aH").succeeds();
}

#[test]
fn test_df_output() {
    let expected = if cfg!(target_os = "macos") {
        "Filesystem               Size         Used    Available     Capacity  Use% Mounted on       "
    } else {
        "Filesystem               Size         Used    Available  Use% Mounted on       "
    };
    let output = new_ucmd!()
        .arg("-H")
        .arg("--total")
        .succeeds()
        .stdout_move_str();
    let actual = output.lines().take(1).collect::<Vec<&str>>()[0];
    assert_eq!(actual, expected);
}

/// Test that the order of rows in the table does not change across executions.
#[test]
fn test_order_same() {
    let output1 = new_ucmd!()
        .arg("--output=source")
        .succeeds()
        .stdout_move_str();
    let output2 = new_ucmd!()
        .arg("--output=source")
        .succeeds()
        .stdout_move_str();
    assert_eq!(output1, output2);
}

/// Test of mount point begin repeated
#[cfg(unix)]
#[test]
fn test_output_mp_repeat() {
    let output1 = new_ucmd!().arg("/").arg("/").succeeds().stdout_move_str();
    let output1: Vec<String> = output1
        .lines()
        .map(|l| String::from(l.split_once(' ').unwrap().0))
        .collect();
    assert_eq!(3, output1.len());
    assert_eq!(output1[1], output1[2]);
}
#[test]
fn test_output_conflict_options() {
    for option in ["-i", "-T", "-P"] {
        new_ucmd!().arg("--output=source").arg(option).fails();
    }
}

#[test]
fn test_output_option() {
    new_ucmd!().arg("--output").succeeds();
    new_ucmd!().arg("--output=source,target").succeeds();
    new_ucmd!().arg("--output=invalid_option").fails();
}

#[test]
fn test_output_option_without_equals_sign() {
    new_ucmd!().arg("--output").arg(".").succeeds();
}

#[test]
fn test_type_option() {
    new_ucmd!().args(&["-t", "ext4", "-t", "ext3"]).succeeds();
}

#[test]
fn test_exclude_type_option() {
    new_ucmd!().args(&["-x", "ext4", "-x", "ext3"]).succeeds();
}

#[test]
fn test_include_exclude_same_type() {
    new_ucmd!()
        .args(&["-t", "ext4", "-x", "ext4"])
        .fails()
        .stderr_is("df: file system type 'ext4' both selected and excluded");
    new_ucmd!()
        .args(&["-t", "ext4", "-x", "ext4", "-t", "ext3", "-x", "ext3"])
        .fails()
        .stderr_is(
            "df: file system type 'ext4' both selected and excluded\n\
             df: file system type 'ext3' both selected and excluded",
        );
}

#[test]
fn test_total() {
    // Example output:
    //
    //     Filesystem            1K-blocks     Used Available Use% Mounted on
    //     udev                    3858016        0   3858016   0% /dev
    //     ...
    //     /dev/loop14               63488    63488         0 100% /snap/core20/1361
    //     total                 258775268 98099712 148220200  40% -
    let output = new_ucmd!().arg("--total").succeeds().stdout_move_str();

    // Skip the header line.
    let lines: Vec<&str> = output.lines().skip(1).collect();

    // Parse the values from the last row.
    let last_line = lines.last().unwrap();
    let mut iter = last_line.split_whitespace();
    assert_eq!(iter.next().unwrap(), "total");
    let reported_total_size = iter.next().unwrap().parse().unwrap();
    let reported_total_used = iter.next().unwrap().parse().unwrap();
    let reported_total_avail = iter.next().unwrap().parse().unwrap();

    // Loop over each row except the last, computing the sum of each column.
    let mut computed_total_size = 0;
    let mut computed_total_used = 0;
    let mut computed_total_avail = 0;
    let n = lines.len();
    for line in &lines[..n - 1] {
        let mut iter = line.split_whitespace();
        iter.next().unwrap();
        computed_total_size += iter.next().unwrap().parse::<u64>().unwrap();
        computed_total_used += iter.next().unwrap().parse::<u64>().unwrap();
        computed_total_avail += iter.next().unwrap().parse::<u64>().unwrap();
    }

    // Check that the sum of each column matches the reported value in
    // the last row.
    assert_eq!(computed_total_size, reported_total_size);
    assert_eq!(computed_total_used, reported_total_used);
    assert_eq!(computed_total_avail, reported_total_avail);
}

#[test]
fn test_use_percentage() {
    let output = new_ucmd!()
        .args(&["--total", "--output=used,avail,pcent"])
        .succeeds()
        .stdout_move_str();

    // Skip the header line.
    let lines: Vec<&str> = output.lines().skip(1).collect();

    for line in lines {
        let mut iter = line.split_whitespace();
        let reported_used = iter.next().unwrap().parse::<f64>().unwrap();
        let reported_avail = iter.next().unwrap().parse::<f64>().unwrap();
        let reported_percentage = iter.next().unwrap();
        let reported_percentage = reported_percentage[..reported_percentage.len() - 1]
            .parse::<u8>()
            .unwrap();
        let computed_percentage =
            (100.0 * (reported_used / (reported_used + reported_avail))).ceil() as u8;

        assert_eq!(computed_percentage, reported_percentage);
    }
}

#[test]
fn test_block_size_1024() {
    fn get_header(block_size: u64) -> String {
        // TODO When #3057 is resolved, we should just use
        //
        //     new_ucmd!().arg("--output=size").succeeds().stdout_move_str();
        //
        // instead of parsing the entire `df` table as a string.
        let output = new_ucmd!()
            .args(&["-B", &format!("{}", block_size)])
            .succeeds()
            .stdout_move_str();
        let first_line = output.lines().next().unwrap();
        let mut column_labels = first_line.split_whitespace();
        let size_column_label = column_labels.nth(1).unwrap();
        size_column_label.into()
    }

    assert_eq!(get_header(1024), "1K-blocks");
    assert_eq!(get_header(2048), "2K-blocks");
    assert_eq!(get_header(4096), "4K-blocks");
    assert_eq!(get_header(1024 * 1024), "1M-blocks");
    assert_eq!(get_header(2 * 1024 * 1024), "2M-blocks");
    assert_eq!(get_header(1024 * 1024 * 1024), "1G-blocks");
    assert_eq!(get_header(34 * 1024 * 1024 * 1024), "34G-blocks");
}

// TODO The spacing does not match GNU df. Also we need to remove
// trailing spaces from the heading row.
#[test]
fn test_output_selects_columns() {
    let output = new_ucmd!()
        .args(&["--output=source"])
        .succeeds()
        .stdout_move_str();
    assert_eq!(output.lines().next().unwrap(), "Filesystem       ");

    let output = new_ucmd!()
        .args(&["--output=source,target"])
        .succeeds()
        .stdout_move_str();
    assert_eq!(
        output.lines().next().unwrap(),
        "Filesystem       Mounted on       "
    );

    let output = new_ucmd!()
        .args(&["--output=source,target,used"])
        .succeeds()
        .stdout_move_str();
    assert_eq!(
        output.lines().next().unwrap(),
        "Filesystem       Mounted on               Used "
    );
}

#[test]
fn test_output_multiple_occurrences() {
    let output = new_ucmd!()
        .args(&["--output=source", "--output=target"])
        .succeeds()
        .stdout_move_str();
    assert_eq!(
        output.lines().next().unwrap(),
        "Filesystem       Mounted on       "
    );
}

// TODO Fix the spacing.
#[test]
fn test_output_file_all_filesystems() {
    // When run with no positional arguments, `df` lets "-" represent
    // the "File" entry for each row.
    let output = new_ucmd!()
        .arg("--output=file")
        .succeeds()
        .stdout_move_str();
    let mut lines = output.lines();
    assert_eq!(lines.next().unwrap(), "File            ");
    for line in lines {
        assert_eq!(line, "-               ");
    }
}

// TODO Fix the spacing.
#[test]
fn test_output_file_specific_files() {
    // Create three files.
    let (at, mut ucmd) = at_and_ucmd!();
    at.touch("a");
    at.touch("b");
    at.touch("c");

    // When run with positional arguments, the filesystems should
    // appear in the "File" column.
    let output = ucmd
        .args(&["--output=file", "a", "b", "c"])
        .succeeds()
        .stdout_move_str();
    let actual: Vec<&str> = output.lines().collect();
    assert_eq!(
        actual,
        vec![
            "File            ",
            "a               ",
            "b               ",
            "c               "
        ]
    );
}

#[test]
fn test_output_field_no_more_than_once() {
    new_ucmd!()
        .arg("--output=target,source,target")
        .fails()
        .usage_error("option --output: field 'target' used more than once");
}
<|endoftext|>


<commit_before>//! The `parser` module contains a lot of useful functionality
//! to parse tokens from the lexer and create an parse-tree
//! its an predictiv parser for a LL(1) grammar

/*

----------------------------------------
Grammatik:

LL(1)
----------------------------------------|
S -> Passage S2                         |
S2 -> S                                 |
S2 -> ɛ                                 |
Passage -> PassageName PassageContent   |
PassageContent -> TextPassage B         |
PassageContent -> Formatting B          |
PassageContent -> Newline B             |
B -> PassageContent                     |
B -> ɛ                                  |
----------------------------------------|

Hello World im LL(1)-Parser:
token: [TokPassageName("Start"), TokText("Hello World\n")]

input                   | stack                         | output                              |
------------------------+-------------------------------+-------------------------------------+---------------------------------------------------
PassageName TextPassage | S                             | S->Passage S'                       | passage and s' as child of S
        --||--          | Passage S2                    | Passage->PassageName PassageContent | passageName and passagecontent as child of passage
        --||--          | PassageName PassageContent S2 |                                     | gehe bei den token 1 weiter
TextPassage             | PassageContent S2             | PassageContent->TextPassage B       | textpassage and b as child of PassageContent
        --||--          | TextPassage B S'              |                                     | gehe bei den token 1 weiter
empty                   | B S'                          | B->ɛ                                |
empty                   | S'                            | S' -> ɛ                             |
empty                   | empty                         | ACCEPT                              |
------------------------+-------------------------------+-------------------------------------|---------------------------------------------------

*/

pub use frontend::lexer::Token;
pub use frontend::ast;

pub fn parse_tokens(tokens: Vec<Token>) -> ParseTree {
    let mut parser: Parser = Parser::new(tokens);
    parser.parsing();
    parser.tree
}

//==============================
// grammar

#[derive(Debug, Copy, Clone)]
pub enum NonTerminalType {
    S,
    S2,
    Passage,
    PassageContent,
    B
}

//==============================
// parser

struct Parser {
    tree: ParseTree,
    stack: Stack,
    tokens: Vec<Token>,
    lookahead: usize
}

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Parser {
        Parser {
            tree: ParseTree::new(),
            stack: Stack::new(),
            tokens: tokens,
            lookahead: 0
        }
    }

    /// the predictive stack ll(1) parsing routine
    pub fn parsing(&mut self) {
        self.stack.push_start();

        while let Some(top) = self.stack.pop() {
            if self.tree.root.is_terminal(top.to_vec()) {
                self.next_token();
            } else {
                self.apply_grammar(top.to_vec());
            }
        }

        debug!("Parse Tree: ");
        self.tree.print();
    }

    /// apply the ll(1) grammar
    /// the match-statement simulates the parsing-table behavior
    ///
    fn apply_grammar(&mut self, top_path: Vec<usize>) {
        //let current_token: &Token;
        if let Some(token) = self.tokens.get_mut(self.lookahead) {
            //current_token = token;

            let to_add_path: Vec<usize> = top_path.to_vec();

            // the frst item in the tuple is the current state and
            // the snd is the current lookup-token
            let state_first: (NonTerminalType, &Token) = (self.tree.root.get_non_terminal(top_path).clone(), token);

            let mut new_nodes = Vec::new();
            match state_first {
                (NonTerminalType::S, &Token::TokPassageName(_)) => {
                    new_nodes.push(PNode::new_non_terminal(NonTerminalType::Passage));
                    new_nodes.push(PNode::new_non_terminal(NonTerminalType::S2));
                },
                (NonTerminalType::S2, &Token::TokPassageName(_)) => {
                    new_nodes.push(PNode::new_non_terminal(NonTerminalType::S));
                },
                (NonTerminalType::Passage, &Token::TokPassageName(ref name)) => {
                    let new_token: Token = Token::TokPassageName(name.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(NonTerminalType::PassageContent));
                },
                (NonTerminalType::PassageContent, &Token::TokText(ref text)) => {
                    let new_token: Token = Token::TokText(text.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(NonTerminalType::B));
                },
                (NonTerminalType::B, _) => {
                    // not implemented
                },
                _ => {

                }
            }

            // adds the new nodes to the tree
            // and adds the path in the tree to the stack
            let length = new_nodes.len().clone();
            self.tree.add_nodes(new_nodes, &to_add_path);
            self.stack.push_path(length as u8, to_add_path);

        } else {
            // no token left
            // only ɛ-productions could be here
            // these productions will be poped of the stack
        }
    }

    /// sets the lookahead to the next token
    fn next_token(&mut self) {
        self.lookahead = self.lookahead + 1;
    }
}

//==============================
// stack of the parser
struct Stack {
    data: Vec<Vec<usize>>
}

impl Stack {
    pub fn new() -> Stack {
        Stack { data: Vec::new() }
    }

    /// pushs the address of the first startsymbol to the stack
    fn push_start(&mut self) {
        self.data.push(vec![]);
    }

    /// save the path of the nodes in the tree to the stack
    /// the right part of the production
    /// should be on the stack in reverse order
    fn push_path(&mut self, count_elements: u8, to_add_path: Vec<usize>) {
        for i in 0..count_elements {
            let mut path: Vec<usize> = to_add_path.to_vec();
            path.push((count_elements-i-1) as usize);
            self.data.push(path);
        }
    }

    fn pop(&mut self) -> Option<Vec<usize>> {
        self.data.pop()
    }
}

//==============================
// parsetree

pub struct ParseTree {
    root: PNode
}

impl ParseTree {
    pub fn new() -> ParseTree {
        ParseTree {
            root: PNode::new_non_terminal(NonTerminalType::S)
        }
    }

    /// adds nodes to the tree
    pub fn add_nodes(&mut self, childs: Vec<PNode>, to_add_path: &Vec<usize>) {
        for child in childs {
            self.root.add_child_at(to_add_path, child);
        }
    }

    /// prints the tree
    pub fn print(&self) {
        self.root.print(0);
    }

    pub fn create_ast(&self, ast: &mut ast::AST) {
        self.root.create_ast(ast);
    }
}

//==============================
// node of the paretree

pub struct NodeNonTerminal {
    category: NonTerminalType,
    childs: Vec<PNode>
}

pub struct NodeTerminal {
    category: Token
}

//#[derive(Debug)]
pub enum PNode {
    NonTerminal (NodeNonTerminal),
    Terminal (NodeTerminal)
}

impl PNode {
    pub fn new_terminal(terminal: Token) -> PNode {
        PNode::Terminal(NodeTerminal  { category: terminal })
    }

    pub fn new_non_terminal(non_terminal: NonTerminalType) -> PNode {
        PNode::NonTerminal(NodeNonTerminal { category: non_terminal, childs: Vec::new() })
    }

    /// prints a node
    pub fn print(&self, indent: usize) {
        let mut spaces = "".to_string();
        for _ in 0..indent {
            spaces.push_str(" ");
        }

        match self {
            &PNode::NonTerminal(ref t) => {
                debug!("{}|- Node: {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            }
            &PNode::Terminal(ref t) => { debug!("{}|- Terminal: {:?}", spaces, t.category); }
        }
    }

    /// returns a non_terminal of the path
    pub fn get_non_terminal(&self, path: Vec<usize>) -> &NonTerminalType {
        match self {
            &PNode::NonTerminal(ref node) => {
                if let Some(index) = path.first() {
                    let mut new_path: Vec<usize> = path.to_vec();
                    new_path.remove(0);
                    return node.childs[*index].get_non_terminal(new_path);
                } else {
                    return &node.category;
                }
            },
            _ => panic!("error")
        }
    }

    /// adds a node to the childs in path
    pub fn add_child_at(&mut self, path: &[usize], child: PNode) {
        match self {
            &mut PNode::NonTerminal (ref mut node) => {
                if let Some(index) = path.first() {
                    let mut new_path: Vec<usize> = path.to_vec();
                    new_path.remove(0);
                    node.childs[*index].add_child_at(&new_path, child);
                } else {
                    node.childs.push(child);
                }
            },
            _ => panic!("error")
        }
    }

    /// checks if the node of the path is a terminal or not
    pub fn is_terminal(&self, path: Vec<usize>) -> bool {
        match self {
            &PNode::NonTerminal(ref node) => {
                if let Some(index) = path.first() {
                    let mut new_path: Vec<usize> = path.to_vec();
                    new_path.remove(0);
                    return node.childs[*index].is_terminal(new_path);
                }

                return false
            },
            &PNode::Terminal(_) => return true
        }

        false
    }

    pub fn create_ast(&self, ast: &mut ast::AST) {

        match self {
            &PNode::NonTerminal(ref node) => {
                /*match node.category {
                    NonTerminalType::S => {
                        println!("S");
                    },
                    _ => {
                        println!("_");
                    }
                }*/
                for child in &node.childs {
                    child.create_ast(ast);
                }

            },
            &PNode::Terminal(ref node) => {
                match node.category {
                    Token::TokPassageName(ref name) => {
                        let new_token: Token = Token::TokPassageName(name.clone());
                        ast.add_passage(new_token);
                    },
                    Token::TokText(ref text) => {
                        let new_token: Token = Token::TokText(text.clone());
                        ast.add_leaf(new_token);
                    },
                    _ => {
                        println!("_");
                    }
                }
            }
        }
    }
}

#[test]
fn it_works() {

}

<commit_msg>small changes<commit_after>//! The `parser` module contains a lot of useful functionality
//! to parse tokens from the lexer and create an parse-tree
//! its an predictiv parser for a LL(1) grammar

/*

----------------------------------------
Grammatik:

LL(1)
------------------------------------------------------------|
S -> Passage S2                                             |
S2 -> S                                                     |
S2 -> ɛ                                                     |
Passage -> PassageName PassageContent                       |
PassageContent -> TextPassage B                             |
PassageContent -> Formatting B                              |
PassageContent -> Newline B                                 |
B -> PassageContent                                         |
B -> ɛ                                                      |
Formating -> BoldFormatting                                 |
Formating -> ItalicFormatting                               |
BoldFormatting -> FormatBold PassageContent FormatBold      |
ItalicFormatting -> FormatItalic PassageContent FormatItalic|
------------------------------------------------------------|

Hello World im LL(1)-Parser:
token: [TokPassageName("Start"), TokText("Hello World\n")]

input                   | stack                         | output                              |
------------------------+-------------------------------+-------------------------------------+---------------------------------------------------
PassageName TextPassage | S                             | S->Passage S'                       | passage and s' as child of S
        --||--          | Passage S2                    | Passage->PassageName PassageContent | passageName and passagecontent as child of passage
        --||--          | PassageName PassageContent S2 |                                     | gehe bei den token 1 weiter
TextPassage             | PassageContent S2             | PassageContent->TextPassage B       | textpassage and b as child of PassageContent
        --||--          | TextPassage B S'              |                                     | gehe bei den token 1 weiter
empty                   | B S'                          | B->ɛ                                |
empty                   | S'                            | S' -> ɛ                             |
empty                   | empty                         | ACCEPT                              |
------------------------+-------------------------------+-------------------------------------|---------------------------------------------------

*/

pub use frontend::lexer::Token;
pub use frontend::ast;

pub fn parse_tokens(tokens: Vec<Token>) -> ParseTree {
    let mut parser: Parser = Parser::new(tokens);
    parser.parsing();
    parser.tree
}

//==============================
// grammar

#[derive(Debug, Copy, Clone)]
pub enum NonTerminalType {
    S,
    S2,
    Passage,
    PassageContent,
    B
}

//==============================
// parser

struct Parser {
    tree: ParseTree,
    stack: Stack,
    tokens: Vec<Token>,
    lookahead: usize
}

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Parser {
        Parser {
            tree: ParseTree::new(),
            stack: Stack::new(),
            tokens: tokens,
            lookahead: 0
        }
    }

    /// the predictive stack ll(1) parsing routine
    pub fn parsing(&mut self) {
        self.stack.push_start();

        while let Some(top) = self.stack.pop() {
            if self.tree.root.is_terminal(top.to_vec()) {
                self.next_token();
            } else {
                self.apply_grammar(top.to_vec());
            }
        }

        debug!("Parse Tree: ");
        self.tree.print();
    }

    /// apply the ll(1) grammar
    /// the match-statement simulates the parsing-table behavior
    ///
    fn apply_grammar(&mut self, top_path: Vec<usize>) {
        //let current_token: &Token;
        if let Some(token) = self.tokens.get_mut(self.lookahead) {
            //current_token = token;

            let to_add_path: Vec<usize> = top_path.to_vec();

            // the frst item in the tuple is the current state and
            // the snd is the current lookup-token
            let state_first: (NonTerminalType, &Token) = (self.tree.root.get_non_terminal(top_path).clone(), token);

            let mut new_nodes = Vec::new();
            match state_first {
                (NonTerminalType::S, &Token::TokPassageName(_)) => {
                    new_nodes.push(PNode::new_non_terminal(NonTerminalType::Passage));
                    new_nodes.push(PNode::new_non_terminal(NonTerminalType::S2));
                },
                (NonTerminalType::S2, &Token::TokPassageName(_)) => {
                    new_nodes.push(PNode::new_non_terminal(NonTerminalType::S));
                },
                (NonTerminalType::Passage, &Token::TokPassageName(ref name)) => {
                    let new_token: Token = Token::TokPassageName(name.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(NonTerminalType::PassageContent));
                },
                (NonTerminalType::PassageContent, &Token::TokText(ref text)) => {
                    let new_token: Token = Token::TokText(text.clone());
                    new_nodes.push(PNode::new_terminal(new_token));
                    new_nodes.push(PNode::new_non_terminal(NonTerminalType::B));
                },
                (NonTerminalType::B, _) => {
                    // not implemented
                },
                _ => {

                }
            }

            // adds the new nodes to the tree
            // and adds the path in the tree to the stack
            let length = new_nodes.len().clone();
            self.tree.add_nodes(new_nodes, &to_add_path);
            self.stack.push_path(length as u8, to_add_path);

        } else {
            // no token left
            // only ɛ-productions could be here
            // these productions will be poped of the stack
        }
    }

    /// sets the lookahead to the next token
    fn next_token(&mut self) {
        self.lookahead = self.lookahead + 1;
    }
}

//==============================
// stack of the parser
struct Stack {
    data: Vec<Vec<usize>>
}

impl Stack {
    pub fn new() -> Stack {
        Stack { data: Vec::new() }
    }

    /// pushs the address of the first startsymbol to the stack
    fn push_start(&mut self) {
        self.data.push(vec![]);
    }

    /// save the path of the nodes in the tree to the stack
    /// the right part of the production
    /// should be on the stack in reverse order
    fn push_path(&mut self, count_elements: u8, to_add_path: Vec<usize>) {
        for i in 0..count_elements {
            let mut path: Vec<usize> = to_add_path.to_vec();
            path.push((count_elements-i-1) as usize);
            self.data.push(path);
        }
    }

    fn pop(&mut self) -> Option<Vec<usize>> {
        self.data.pop()
    }
}

//==============================
// parsetree

pub struct ParseTree {
    root: PNode
}

impl ParseTree {
    pub fn new() -> ParseTree {
        ParseTree {
            root: PNode::new_non_terminal(NonTerminalType::S)
        }
    }

    /// adds nodes to the tree
    pub fn add_nodes(&mut self, childs: Vec<PNode>, to_add_path: &Vec<usize>) {
        for child in childs {
            self.root.add_child_at(to_add_path, child);
        }
    }

    /// prints the tree
    pub fn print(&self) {
        self.root.print(0);
    }

    pub fn create_ast(&self, ast: &mut ast::AST) {
        self.root.create_ast(ast);
    }
}

//==============================
// node of the paretree

pub struct NodeNonTerminal {
    category: NonTerminalType,
    childs: Vec<PNode>
}

pub struct NodeTerminal {
    category: Token
}

//#[derive(Debug)]
pub enum PNode {
    NonTerminal (NodeNonTerminal),
    Terminal (NodeTerminal)
}

impl PNode {
    pub fn new_terminal(terminal: Token) -> PNode {
        PNode::Terminal(NodeTerminal  { category: terminal })
    }

    pub fn new_non_terminal(non_terminal: NonTerminalType) -> PNode {
        PNode::NonTerminal(NodeNonTerminal { category: non_terminal, childs: Vec::new() })
    }

    /// prints a node
    pub fn print(&self, indent: usize) {
        let mut spaces = "".to_string();
        for _ in 0..indent {
            spaces.push_str(" ");
        }

        match self {
            &PNode::NonTerminal(ref t) => {
                debug!("{}|- Node: {:?}", spaces, t.category);
                for child in &t.childs {
                    child.print(indent+2);
                }
            }
            &PNode::Terminal(ref t) => { debug!("{}|- Terminal: {:?}", spaces, t.category); }
        }
    }

    /// returns a non_terminal of the path
    pub fn get_non_terminal(&self, path: Vec<usize>) -> &NonTerminalType {
        match self {
            &PNode::NonTerminal(ref node) => {
                if let Some(index) = path.first() {
                    let mut new_path: Vec<usize> = path.to_vec();
                    new_path.remove(0);
                    return node.childs[*index].get_non_terminal(new_path);
                } else {
                    return &node.category;
                }
            },
            _ => panic!("error")
        }
    }

    /// adds a node to the childs in path
    pub fn add_child_at(&mut self, path: &[usize], child: PNode) {
        match self {
            &mut PNode::NonTerminal (ref mut node) => {
                if let Some(index) = path.first() {
                    let mut new_path: Vec<usize> = path.to_vec();
                    new_path.remove(0);
                    node.childs[*index].add_child_at(&new_path, child);
                } else {
                    node.childs.push(child);
                }
            },
            _ => panic!("error")
        }
    }

    /// checks if the node of the path is a terminal or not
    pub fn is_terminal(&self, path: Vec<usize>) -> bool {
        match self {
            &PNode::NonTerminal(ref node) => {
                if let Some(index) = path.first() {
                    let mut new_path: Vec<usize> = path.to_vec();
                    new_path.remove(0);
                    return node.childs[*index].is_terminal(new_path);
                }

                return false
            },
            &PNode::Terminal(_) => return true
        }

        false
    }

    pub fn create_ast(&self, ast: &mut ast::AST) {

        match self {
            &PNode::NonTerminal(ref node) => {
                /*match node.category {
                    NonTerminalType::S => {
                        println!("S");
                    },
                    _ => {
                        println!("_");
                    }
                }*/
                for child in &node.childs {
                    child.create_ast(ast);
                }
            },
            &PNode::Terminal(ref node) => {
                match node.category {
                    Token::TokPassageName(ref name) => {
                        let new_token: Token = Token::TokPassageName(name.clone());
                        ast.add_passage(new_token);
                    },
                    Token::TokText(ref text) => {
                        let new_token: Token = Token::TokText(text.clone());
                        ast.add_leaf(new_token);
                    },
                    _ => {
                        println!("_");
                    }
                }
            }
        }
    }
}

#[test]
fn it_works() {

}

<|endoftext|>


<commit_before>// Build mcuboot as a library, based on the requested features.

extern crate cc;

use std::env;
use std::fs;
use std::io;
use std::path::Path;

fn main() {
    // Feature flags.
    let sig_rsa = env::var("CARGO_FEATURE_SIG_RSA").is_ok();
    let sig_ecdsa = env::var("CARGO_FEATURE_SIG_ECDSA").is_ok();
    let overwrite_only = env::var("CARGO_FEATURE_OVERWRITE_ONLY").is_ok();
    let validate_slot0 = env::var("CARGO_FEATURE_VALIDATE_SLOT0").is_ok();
    let enc_rsa = env::var("CARGO_FEATURE_ENC_RSA").is_ok();
    let enc_kw = env::var("CARGO_FEATURE_ENC_KW").is_ok();

    let mut conf = cc::Build::new();
    conf.define("__BOOTSIM__", None);
    conf.define("MCUBOOT_USE_FLASH_AREA_GET_SECTORS", None);
    conf.define("MCUBOOT_HAVE_ASSERT_H", None);
    conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("128"));

    if validate_slot0 {
        conf.define("MCUBOOT_VALIDATE_SLOT0", None);
    }

    // Currently, mbed TLS cannot build with both RSA and ECDSA.
    if sig_rsa && sig_ecdsa {
        panic!("mcuboot does not support RSA and ECDSA at the same time");
    }

    if sig_rsa {
        conf.define("MCUBOOT_SIGN_RSA", None);
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.include("mbedtls/include");
        conf.file("mbedtls/library/sha256.c");
        conf.file("csupport/keys.c");

        conf.file("mbedtls/library/rsa.c");
        conf.file("mbedtls/library/bignum.c");
        conf.file("mbedtls/library/platform.c");
        conf.file("mbedtls/library/platform_util.c");
        conf.file("mbedtls/library/asn1parse.c");
    } else if sig_ecdsa {
        conf.define("MCUBOOT_SIGN_EC256", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);

        conf.include("../../ext/mbedtls/include");
        conf.include("../../ext/tinycrypt/lib/include");

        conf.file("csupport/keys.c");

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");

        conf.file("../../ext/mbedtls/src/asn1parse.c");
    } else {
        // Neither signature type, only verify sha256. The default
        // configuration file bundled with mbedTLS is sufficient.
        conf.define("MCUBOOT_USE_MBED_TLS", None);
        conf.include("mbedtls/include");
        conf.file("mbedtls/library/sha256.c");
    }

    if overwrite_only {
        conf.define("MCUBOOT_OVERWRITE_ONLY", None);
        conf.define("MCUBOOT_OVERWRITE_ONLY_FAST", None);
    }

    if enc_rsa {
        conf.define("MCUBOOT_ENCRYPT_RSA", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("mbedtls/include");
        conf.file("mbedtls/library/sha256.c");

        conf.file("mbedtls/library/platform.c");
        conf.file("mbedtls/library/platform_util.c");
        conf.file("mbedtls/library/rsa.c");
        conf.file("mbedtls/library/rsa_internal.c");
        conf.file("mbedtls/library/md.c");
        conf.file("mbedtls/library/md_wrap.c");
        conf.file("mbedtls/library/aes.c");
        conf.file("mbedtls/library/bignum.c");
        conf.file("mbedtls/library/asn1parse.c");
    }

    if enc_kw {
        conf.define("MCUBOOT_ENCRYPT_KW", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("mbedtls/include");
        conf.file("mbedtls/library/sha256.c");

        conf.file("mbedtls/library/platform.c");
        conf.file("mbedtls/library/platform_util.c");
        conf.file("mbedtls/library/nist_kw.c");
        conf.file("mbedtls/library/cipher.c");
        conf.file("mbedtls/library/cipher_wrap.c");
        conf.file("mbedtls/library/aes.c");
    }

    if sig_rsa || enc_rsa {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa.h>"));
    } else if sig_ecdsa {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
    } else if enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-kw.h>"));
    }

    conf.file("../../boot/bootutil/src/image_validate.c");
    if sig_rsa {
        conf.file("../../boot/bootutil/src/image_rsa.c");
    } else if sig_ecdsa {
        conf.file("../../boot/bootutil/src/image_ec256.c");
    }
    conf.file("../../boot/bootutil/src/loader.c");
    conf.file("../../boot/bootutil/src/caps.c");
    conf.file("../../boot/bootutil/src/bootutil_misc.c");
    conf.file("csupport/run.c");
    conf.include("../../boot/bootutil/include");
    conf.include("csupport");
    conf.include("../../boot/zephyr/include");
    conf.debug(true);
    conf.flag("-Wall");
    conf.flag("-Werror");

    // FIXME: travis-ci still uses gcc 4.8.4 which defaults to std=gnu90.
    // It has incomplete std=c11 and std=c99 support but std=c99 was checked
    // to build correctly so leaving it here to updated in the future...
    conf.flag("-std=c99");

    conf.compile("libbootutil.a");

    walk_dir("../../boot").unwrap();
    walk_dir("../../ext/tinycrypt/lib/source").unwrap();
    walk_dir("../../ext/mbedtls").unwrap();
    walk_dir("csupport").unwrap();
    walk_dir("mbedtls/include").unwrap();
    walk_dir("mbedtls/library").unwrap();
}

// Output the names of all files within a directory so that Cargo knows when to rebuild.
fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
    for ent in fs::read_dir(path.as_ref())? {
        let ent = ent?;
        let p = ent.path();
        if p.is_dir() {
            walk_dir(p)?;
        } else {
            // Note that non-utf8 names will fail.
            let name = p.to_str().unwrap();
            if name.ends_with(".c") || name.ends_with(".h") {
                println!("cargo:rerun-if-changed={}", name);
            }
        }
    }

    Ok(())
}
<commit_msg>Enable bootutil logging in simulator<commit_after>// Build mcuboot as a library, based on the requested features.

extern crate cc;

use std::env;
use std::fs;
use std::io;
use std::path::Path;

fn main() {
    // Feature flags.
    let sig_rsa = env::var("CARGO_FEATURE_SIG_RSA").is_ok();
    let sig_ecdsa = env::var("CARGO_FEATURE_SIG_ECDSA").is_ok();
    let overwrite_only = env::var("CARGO_FEATURE_OVERWRITE_ONLY").is_ok();
    let validate_slot0 = env::var("CARGO_FEATURE_VALIDATE_SLOT0").is_ok();
    let enc_rsa = env::var("CARGO_FEATURE_ENC_RSA").is_ok();
    let enc_kw = env::var("CARGO_FEATURE_ENC_KW").is_ok();

    let mut conf = cc::Build::new();
    conf.define("__BOOTSIM__", None);
    conf.define("MCUBOOT_HAVE_LOGGING", None);
    conf.define("MCUBOOT_USE_FLASH_AREA_GET_SECTORS", None);
    conf.define("MCUBOOT_HAVE_ASSERT_H", None);
    conf.define("MCUBOOT_MAX_IMG_SECTORS", Some("128"));

    if validate_slot0 {
        conf.define("MCUBOOT_VALIDATE_SLOT0", None);
    }

    // Currently, mbed TLS cannot build with both RSA and ECDSA.
    if sig_rsa && sig_ecdsa {
        panic!("mcuboot does not support RSA and ECDSA at the same time");
    }

    if sig_rsa {
        conf.define("MCUBOOT_SIGN_RSA", None);
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.include("mbedtls/include");
        conf.file("mbedtls/library/sha256.c");
        conf.file("csupport/keys.c");

        conf.file("mbedtls/library/rsa.c");
        conf.file("mbedtls/library/bignum.c");
        conf.file("mbedtls/library/platform.c");
        conf.file("mbedtls/library/platform_util.c");
        conf.file("mbedtls/library/asn1parse.c");
    } else if sig_ecdsa {
        conf.define("MCUBOOT_SIGN_EC256", None);
        conf.define("MCUBOOT_USE_TINYCRYPT", None);

        conf.include("../../ext/mbedtls/include");
        conf.include("../../ext/tinycrypt/lib/include");

        conf.file("csupport/keys.c");

        conf.file("../../ext/tinycrypt/lib/source/utils.c");
        conf.file("../../ext/tinycrypt/lib/source/sha256.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_dsa.c");
        conf.file("../../ext/tinycrypt/lib/source/ecc_platform_specific.c");

        conf.file("../../ext/mbedtls/src/asn1parse.c");
    } else {
        // Neither signature type, only verify sha256. The default
        // configuration file bundled with mbedTLS is sufficient.
        conf.define("MCUBOOT_USE_MBED_TLS", None);
        conf.include("mbedtls/include");
        conf.file("mbedtls/library/sha256.c");
    }

    if overwrite_only {
        conf.define("MCUBOOT_OVERWRITE_ONLY", None);
        conf.define("MCUBOOT_OVERWRITE_ONLY_FAST", None);
    }

    if enc_rsa {
        conf.define("MCUBOOT_ENCRYPT_RSA", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("mbedtls/include");
        conf.file("mbedtls/library/sha256.c");

        conf.file("mbedtls/library/platform.c");
        conf.file("mbedtls/library/platform_util.c");
        conf.file("mbedtls/library/rsa.c");
        conf.file("mbedtls/library/rsa_internal.c");
        conf.file("mbedtls/library/md.c");
        conf.file("mbedtls/library/md_wrap.c");
        conf.file("mbedtls/library/aes.c");
        conf.file("mbedtls/library/bignum.c");
        conf.file("mbedtls/library/asn1parse.c");
    }

    if enc_kw {
        conf.define("MCUBOOT_ENCRYPT_KW", None);
        conf.define("MCUBOOT_ENC_IMAGES", None);
        conf.define("MCUBOOT_USE_MBED_TLS", None);

        conf.file("../../boot/bootutil/src/encrypted.c");
        conf.file("csupport/keys.c");

        conf.include("mbedtls/include");
        conf.file("mbedtls/library/sha256.c");

        conf.file("mbedtls/library/platform.c");
        conf.file("mbedtls/library/platform_util.c");
        conf.file("mbedtls/library/nist_kw.c");
        conf.file("mbedtls/library/cipher.c");
        conf.file("mbedtls/library/cipher_wrap.c");
        conf.file("mbedtls/library/aes.c");
    }

    if sig_rsa || enc_rsa {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-rsa.h>"));
    } else if sig_ecdsa {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-asn1.h>"));
    } else if enc_kw {
        conf.define("MBEDTLS_CONFIG_FILE", Some("<config-kw.h>"));
    }

    conf.file("../../boot/bootutil/src/image_validate.c");
    if sig_rsa {
        conf.file("../../boot/bootutil/src/image_rsa.c");
    } else if sig_ecdsa {
        conf.file("../../boot/bootutil/src/image_ec256.c");
    }
    conf.file("../../boot/bootutil/src/loader.c");
    conf.file("../../boot/bootutil/src/caps.c");
    conf.file("../../boot/bootutil/src/bootutil_misc.c");
    conf.file("csupport/run.c");
    conf.include("../../boot/bootutil/include");
    conf.include("csupport");
    conf.include("../../boot/zephyr/include");
    conf.debug(true);
    conf.flag("-Wall");
    conf.flag("-Werror");

    // FIXME: travis-ci still uses gcc 4.8.4 which defaults to std=gnu90.
    // It has incomplete std=c11 and std=c99 support but std=c99 was checked
    // to build correctly so leaving it here to updated in the future...
    conf.flag("-std=c99");

    conf.compile("libbootutil.a");

    walk_dir("../../boot").unwrap();
    walk_dir("../../ext/tinycrypt/lib/source").unwrap();
    walk_dir("../../ext/mbedtls").unwrap();
    walk_dir("csupport").unwrap();
    walk_dir("mbedtls/include").unwrap();
    walk_dir("mbedtls/library").unwrap();
}

// Output the names of all files within a directory so that Cargo knows when to rebuild.
fn walk_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
    for ent in fs::read_dir(path.as_ref())? {
        let ent = ent?;
        let p = ent.path();
        if p.is_dir() {
            walk_dir(p)?;
        } else {
            // Note that non-utf8 names will fail.
            let name = p.to_str().unwrap();
            if name.ends_with(".c") || name.ends_with(".h") {
                println!("cargo:rerun-if-changed={}", name);
            }
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright 2017 The xi-editor Authors.
//
// 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.

//! Very basic syntax detection.

use std::borrow::Borrow;
use std::collections::{BTreeMap, HashMap};
use std::path::Path;
use std::sync::Arc;

use crate::config::Table;

/// The canonical identifier for a particular `LanguageDefinition`.
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct LanguageId(Arc<String>);

/// Describes a `LanguageDefinition`. Although these are provided by plugins,
/// they are a fundamental concept in core, used to determine things like
/// plugin activations and active user config tables.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LanguageDefinition {
    pub name: LanguageId,
    pub extensions: Vec<String>,
    pub first_line_match: Option<String>,
    pub scope: String,
    #[serde(skip)]
    pub default_config: Option<Table>,
}

/// A repository of all loaded `LanguageDefinition`s.
#[derive(Debug, Default)]
pub struct Languages {
    // NOTE: BTreeMap is used for sorting the languages by name alphabetically
    named: BTreeMap<LanguageId, Arc<LanguageDefinition>>,
    extensions: HashMap<String, Arc<LanguageDefinition>>,
}

impl Languages {
    pub fn new(language_defs: &[LanguageDefinition]) -> Self {
        let mut named = BTreeMap::new();
        let mut extensions = HashMap::new();
        for lang in language_defs.iter() {
            let lang_arc = Arc::new(lang.clone());
            named.insert(lang.name.clone(), lang_arc.clone());
            for ext in &lang.extensions {
                extensions.insert(ext.clone(), lang_arc.clone());
            }
        }
        Languages { named, extensions }
    }

    pub fn language_for_path(&self, path: &Path) -> Option<Arc<LanguageDefinition>> {
        path.extension()
            .or_else(|| path.file_name())
            .and_then(|ext| self.extensions.get(ext.to_str().unwrap_or_default()))
            .map(Arc::clone)
    }

    pub fn language_for_name<S>(&self, name: S) -> Option<Arc<LanguageDefinition>>
    where
        S: AsRef<str>,
    {
        self.named.get(name.as_ref()).map(Arc::clone)
    }

    /// Returns a Vec of any `LanguageDefinition`s which exist
    /// in `self` but not `other`.
    pub fn difference(&self, other: &Languages) -> Vec<Arc<LanguageDefinition>> {
        self.named
            .iter()
            .filter(|(k, _)| !other.named.contains_key(*k))
            .map(|(_, v)| v.clone())
            .collect()
    }

    pub fn iter(&self) -> impl Iterator<Item = &Arc<LanguageDefinition>> {
        self.named.values()
    }
}

impl AsRef<str> for LanguageId {
    fn as_ref(&self) -> &str {
        self.0.as_ref()
    }
}

// let's us use &str to query a HashMap with `LanguageId` keys
impl Borrow<str> for LanguageId {
    fn borrow(&self) -> &str {
        &self.0.as_ref()
    }
}

impl<'a> From<&'a str> for LanguageId {
    fn from(src: &'a str) -> LanguageId {
        LanguageId(Arc::new(src.into()))
    }
}

// for testing
#[cfg(test)]
impl LanguageDefinition {
    pub(crate) fn simple(name: &str, exts: &[&str], scope: &str, config: Option<Table>) -> Self {
        LanguageDefinition {
            name: name.into(),
            extensions: exts.iter().map(|s| (*s).into()).collect(),
            first_line_match: None,
            scope: scope.into(),
            default_config: config,
        }
    }
}

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

    #[test]
    pub fn language_for_name() {}

    #[test]
    pub fn language_for_path() {
        let ld_rust = LanguageDefinition {
            name: LanguageId::from("Rust"),
            extensions: vec![String::from("rs")],
            scope: String::from("source.rust"),
            first_line_match: None,
            default_config: None,
        };
        let ld_commit_msg = LanguageDefinition {
            name: LanguageId::from("Git Commit"),
            extensions: vec![
                String::from("COMMIT_EDITMSG"),
                String::from("MERGE_MSG"),
                String::from("TAG_EDITMSG"),
            ],
            scope: String::from("text.git.commit"),
            first_line_match: None,
            default_config: None,
        };
        let languages = Languages::new(&[ld_rust.clone(), ld_commit_msg.clone()]);

        assert_eq!(
            ld_rust.name,
            languages.language_for_path(Path::new("/path/test.rs")).unwrap().name
        );
        assert_eq!(
            ld_commit_msg.name,
            languages.language_for_path(Path::new("/path/COMMIT_EDITMSG")).unwrap().name
        );
        assert_eq!(
            ld_commit_msg.name,
            languages.language_for_path(Path::new("/path/MERGE_MSG")).unwrap().name
        );
        assert_eq!(
            ld_commit_msg.name,
            languages.language_for_path(Path::new("/path/TAG_EDITMSG")).unwrap().name
        );
    }
}
<commit_msg>remove empty test<commit_after>// Copyright 2017 The xi-editor Authors.
//
// 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.

//! Very basic syntax detection.

use std::borrow::Borrow;
use std::collections::{BTreeMap, HashMap};
use std::path::Path;
use std::sync::Arc;

use crate::config::Table;

/// The canonical identifier for a particular `LanguageDefinition`.
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct LanguageId(Arc<String>);

/// Describes a `LanguageDefinition`. Although these are provided by plugins,
/// they are a fundamental concept in core, used to determine things like
/// plugin activations and active user config tables.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LanguageDefinition {
    pub name: LanguageId,
    pub extensions: Vec<String>,
    pub first_line_match: Option<String>,
    pub scope: String,
    #[serde(skip)]
    pub default_config: Option<Table>,
}

/// A repository of all loaded `LanguageDefinition`s.
#[derive(Debug, Default)]
pub struct Languages {
    // NOTE: BTreeMap is used for sorting the languages by name alphabetically
    named: BTreeMap<LanguageId, Arc<LanguageDefinition>>,
    extensions: HashMap<String, Arc<LanguageDefinition>>,
}

impl Languages {
    pub fn new(language_defs: &[LanguageDefinition]) -> Self {
        let mut named = BTreeMap::new();
        let mut extensions = HashMap::new();
        for lang in language_defs.iter() {
            let lang_arc = Arc::new(lang.clone());
            named.insert(lang.name.clone(), lang_arc.clone());
            for ext in &lang.extensions {
                extensions.insert(ext.clone(), lang_arc.clone());
            }
        }
        Languages { named, extensions }
    }

    pub fn language_for_path(&self, path: &Path) -> Option<Arc<LanguageDefinition>> {
        path.extension()
            .or_else(|| path.file_name())
            .and_then(|ext| self.extensions.get(ext.to_str().unwrap_or_default()))
            .map(Arc::clone)
    }

    pub fn language_for_name<S>(&self, name: S) -> Option<Arc<LanguageDefinition>>
    where
        S: AsRef<str>,
    {
        self.named.get(name.as_ref()).map(Arc::clone)
    }

    /// Returns a Vec of any `LanguageDefinition`s which exist
    /// in `self` but not `other`.
    pub fn difference(&self, other: &Languages) -> Vec<Arc<LanguageDefinition>> {
        self.named
            .iter()
            .filter(|(k, _)| !other.named.contains_key(*k))
            .map(|(_, v)| v.clone())
            .collect()
    }

    pub fn iter(&self) -> impl Iterator<Item = &Arc<LanguageDefinition>> {
        self.named.values()
    }
}

impl AsRef<str> for LanguageId {
    fn as_ref(&self) -> &str {
        self.0.as_ref()
    }
}

// let's us use &str to query a HashMap with `LanguageId` keys
impl Borrow<str> for LanguageId {
    fn borrow(&self) -> &str {
        &self.0.as_ref()
    }
}

impl<'a> From<&'a str> for LanguageId {
    fn from(src: &'a str) -> LanguageId {
        LanguageId(Arc::new(src.into()))
    }
}

// for testing
#[cfg(test)]
impl LanguageDefinition {
    pub(crate) fn simple(name: &str, exts: &[&str], scope: &str, config: Option<Table>) -> Self {
        LanguageDefinition {
            name: name.into(),
            extensions: exts.iter().map(|s| (*s).into()).collect(),
            first_line_match: None,
            scope: scope.into(),
            default_config: config,
        }
    }
}

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

    #[test]
    pub fn language_for_path() {
        let ld_rust = LanguageDefinition {
            name: LanguageId::from("Rust"),
            extensions: vec![String::from("rs")],
            scope: String::from("source.rust"),
            first_line_match: None,
            default_config: None,
        };
        let ld_commit_msg = LanguageDefinition {
            name: LanguageId::from("Git Commit"),
            extensions: vec![
                String::from("COMMIT_EDITMSG"),
                String::from("MERGE_MSG"),
                String::from("TAG_EDITMSG"),
            ],
            scope: String::from("text.git.commit"),
            first_line_match: None,
            default_config: None,
        };
        let languages = Languages::new(&[ld_rust.clone(), ld_commit_msg.clone()]);

        assert_eq!(
            ld_rust.name,
            languages.language_for_path(Path::new("/path/test.rs")).unwrap().name
        );
        assert_eq!(
            ld_commit_msg.name,
            languages.language_for_path(Path::new("/path/COMMIT_EDITMSG")).unwrap().name
        );
        assert_eq!(
            ld_commit_msg.name,
            languages.language_for_path(Path::new("/path/MERGE_MSG")).unwrap().name
        );
        assert_eq!(
            ld_commit_msg.name,
            languages.language_for_path(Path::new("/path/TAG_EDITMSG")).unwrap().name
        );
    }
}
<|endoftext|>