<commit_before>use std;
use std::collections::btree_map::Iter;
use std::collections::BTreeMap;
use std::collections::HashMap;
use std::collections::HashSet;

use common::Graph;
use disassembler::*;

#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
pub enum LinkType {
    Next,
    Branch,
    Call,
    SwitchCaseJump,
}

#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
pub struct Link {
    pub address: u64,
    pub target_address: u64,
    pub type_: LinkType,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ExtraData {
    pub function_address: u64,
    pub import_name: String,
    pub is_protected: bool,
}

#[derive(Serialize, Deserialize)]
pub struct InstructionGraph {
    disassembler: Disassembler,
    bytes: Vec<u8>,
    first_address: u64,
    first_address_after_code: u64,
    instructions: BTreeMap<u64, Insn>,
    extra_data: HashMap<u64, ExtraData>,
    instruction_links: HashMap<u64, Vec<Link>>,
    reverse_links: HashMap<u64, Vec<Link>>,
    is_reversed: bool,
    #[serde(skip, default = "empty_edge_predicate")]
    edge_predicate: Box<Fn(&Link) -> bool>,
}

fn empty_edge_predicate() -> Box<Fn(&Link) -> bool> {
    Box::new(|_e| true)
}

pub fn disassemble(bytes: Vec<u8>, pc: u64) -> Result<InstructionGraph, String> {
    trace!("InstructionGraph::disassemble: 0x{:x}, {} bytes", pc, bytes.len());
    let mut disassembler = Disassembler::new();

    let instructions = disassembler.disassemble(&bytes[..], pc, 0, bytes.len());
    let mut instruction_map = BTreeMap::new();

    for instr in instructions.into_iter() {
        instruction_map.insert(instr.address, instr);
    }
    let last_instruction = instruction_map.iter().next_back().unwrap().1;

    let graph = InstructionGraph {
        disassembler,
        bytes,
        first_address: pc,
        first_address_after_code: last_instruction.address + u64::from(last_instruction.length),
        instructions: instruction_map,
        extra_data: HashMap::new(),
        instruction_links: HashMap::new(),
        reverse_links: HashMap::new(),
        is_reversed: false,
        edge_predicate: empty_edge_predicate(),
    };

    trace!("InstructionGraph::disassemble: done");
    Ok(graph)
}

impl Graph<u64, Insn, Link> for InstructionGraph {
    fn set_subgraph(&mut self, _subgraph: Option<HashSet<u64>>) -> &mut Self {
        panic!("NOT SUPPORTED");
    }

    fn set_edge_filter(&mut self, filter: Box<Fn(&Link) -> bool>) -> &mut Self {
        self.edge_predicate = filter;
        self
    }

    fn reverse_edges(&mut self) -> &mut Self {
        self.is_reversed = !self.is_reversed;
        self
    }

    fn contains(&self, vid: &u64) -> bool {
        self.instructions.contains_key(vid)
    }

    fn get_vertex(&self, vid: &u64) -> &Insn {
        &self.instructions[vid]
    }

    fn get_adjacent(&self, vid: &u64) -> Vec<Result<(&u64, &Link), String>> {
        let mut result = vec![];
        let instruction_links = if self.is_reversed {
            &self.reverse_links
        } else {
            &self.instruction_links
        };
        match instruction_links.get(vid) {
            Some(links) => for link in links.iter().filter(|e| (*self.edge_predicate)(e)) {
                let address = if self.is_reversed {
                    &link.address
                } else {
                    &link.target_address
                };
                if self.in_bounds(*address) {
                    result.push(Result::Ok((address, link)));
                } else {
                    result.push(Result::Err(format!(
                        "DFS: Jump outside of code section: {}",
                        address
                    )));
                }
            },
            None => result.push(Result::Err(format!(
                "DFS: Couldn't find links for {}",
                &self.instructions[vid].assembly()
            ))),
        }
        result
    }
}

impl InstructionGraph {
    pub fn instructions_iter(&self) -> Iter<u64, Insn> {
        self.instructions.iter()
    }

    pub fn first_address_after_code(&self) -> u64 {
        self.first_address_after_code
    }

    pub fn contains_address(&self, address: u64) -> bool {
        self.instructions.contains_key(&address)
    }

    pub fn contains(&self, instr: &Insn) -> bool {
        self.instructions.contains_key(&instr.address)
    }

    pub fn in_bounds(&self, address: u64) -> bool {
        address >= self.first_address && address < self.first_address_after_code
    }

    pub fn get_next(&self, address: u64) -> u64 {
        match (address + 1..self.first_address_after_code)
            .find(|a| self.instructions.contains_key(a))
        {
            Some(address) => address,
            None => panic!("Failed to find the next address."),
        }
    }

    pub fn get_in_value(&self, address: u64) -> u32 {
        self.reverse_links[&address].len() as u32
    }

    pub fn get_out_value(&self, address: u64) -> u32 {
        self.instruction_links[&address].len() as u32
    }

    pub fn get_bytes(&self, address: u64, size: usize) -> &[u8] {
        let addr = self.to_byte_array_index(address);
        &self.bytes[addr..(addr + size)]
    }

    pub fn get_bytes_as_hex(&self, insn: &Insn) -> String {
        let mut hex = String::new();
        for byte in self.get_bytes(insn.address, insn.length as usize) {
            hex.push_str(&format!("{:02x}", byte));
        }
        hex
    }

    pub fn get_extra_data(&self, address: u64) -> Option<&ExtraData> {
        self.extra_data.get(&address)
    }

    pub fn get_extra_data_mut(&mut self, address: u64) -> &mut ExtraData {
        self.extra_data.entry(address).or_insert(ExtraData {
            function_address: 0,
            import_name: "".to_string(),
            is_protected: false,
        })
    }

    pub fn add_link(&mut self, offset: u64, target_offset: u64, type_: LinkType) -> () {
        let link = Link {
            address: offset,
            target_address: target_offset,
            type_,
        };

        let links = match self.instruction_links.get_mut(&offset) {
            Some(links) => links,
            None => {
                let links = Vec::new();
                self.instruction_links.insert(offset, links);
                self.instruction_links.get_mut(&offset).unwrap()
            }
        };
        links.push(link);

        let reverse_links = match self.reverse_links.get_mut(&target_offset) {
            Some(links) => links,
            None => {
                let links = Vec::new();
                self.reverse_links.insert(target_offset, links);
                self.reverse_links.get_mut(&target_offset).unwrap()
            }
        };
        reverse_links.push(link);
    }

    pub fn add_jump_table_entry(&mut self, address: u64) -> bool {
        let data = self.read_u32(address);
        if !self.in_bounds(u64::from(data)) {
            false
        } else {
            self.mark_data_bytes(address, 4, "TODO: TEXT".to_string());
            true
        }
    }

    pub fn add_jump_table_indirect_entries(&mut self, address: u64, count: u8) -> () {
        let display_text = "TODO: TEXT".to_string();
        self.mark_data_bytes(address, count, display_text);
    }

    pub fn mark_data_bytes(&mut self, address: u64, length: u8, data_display_text: String) -> () {
        // check if there is an instruction at address, otherwise split an existing one
        let mut size = match self.instructions.get(&address) {
            Some(instr) => instr.length,
            None => {
                let insn = self.split_instruction_at(address);
                insn.length - ((address - insn.address) as u8)
            }
        };
        self.instructions.insert(
            address,
            Insn {
                address,
                code: Mnemonic::Inone,
                length,
                // assembly: data_display_text,
                operands: vec![],
                prefix_segment: Reg::NONE,
                prefix_operand_size: false,
                prefix_address_size: false,
                prefix_lock: false,
                prefix_str: false,
                prefix_rep: false,
                prefix_repe: false,
                prefix_repne: false,
                br_far: false,
                opr_mode: 0,
            },
        );
        self.get_extra_data_mut(address).is_protected = true;
        // remove old instructions
        while size < length {
            let insn = self
                .instructions
                .remove(&(address + u64::from(size)))
                .unwrap();
            size += insn.length;
        }
        // if there are bytes left from the last removed instruction, re-disassemble them
        if size != length {
            let new_instructions = self.disassembler.disassemble(
                &self.bytes[..],
                address + u64::from(length),
                self.to_byte_array_index(address) + (length as usize),
                (size - length) as usize,
            );
            for new_insn in new_instructions {
                self.instructions.insert(new_insn.address, new_insn);
            }
        }
    }

    pub fn split_instruction_at(&mut self, address: u64) -> Insn {
        let mut insn_address = address - 1;
        while !self.instructions.contains_key(&insn_address) {
            insn_address -= 1;
        }
        let old_insn = &self.instructions[&insn_address].clone();
        // Split the old instruction and re-disassemble its first part
        let extra_length = (address - insn_address) as usize;
        let new_instructions = self.disassembler.disassemble(
            &self.bytes[..],
            insn_address,
            self.to_byte_array_index(insn_address),
            extra_length,
        );
        for new_insn in new_instructions {
            self.instructions.insert(new_insn.address, new_insn);
        }
        old_insn.clone()
    }

    pub fn read_u32(&self, address: u64) -> u32 {
        let addr = (address - self.first_address) as usize;
        let mut result = u32::from(self.bytes[addr]);
        result |= u32::from(self.bytes[addr + 1]) << 8;
        result |= u32::from(self.bytes[addr + 2]) << 16;
        result |= u32::from(self.bytes[addr + 3]) << 24;
        result
    }

    pub fn redisassemble(&mut self, address: u64) -> () {
        // This function will fix any instructions that were incorrectly disassembled because of the data block that was treated as code
        trace!("InstructionGraph::redisassemble: 0x{:x}", address);
        if !self.instructions.contains_key(&address) {
            self.split_instruction_at(address);
        }
        let max_disasm_length = 0x100;
        let mut disasm_length =
            std::cmp::min(max_disasm_length, self.first_address_after_code - address);
        disasm_length = (0..=disasm_length)
            .find(|len| {
                self.extra_data
                    .get(&(address + len))
                    .map_or(false, |d| d.is_protected)
            }).unwrap_or(disasm_length);
        let mut new_instructions = self.disassembler.disassemble(
            &self.bytes[..],
            address,
            self.to_byte_array_index(address),
            disasm_length as usize,
        );
        // Take 1 instruction less since it can be incorrectly disassembled (partial data)
        new_instructions.pop();
        let mut fixed_instructions = false;
        for new_insn in new_instructions {
            match self.instructions.get(&new_insn.address) {
                Some(old_insn) if old_insn.length == new_insn.length => {
                    if fixed_instructions {
                        trace!("InstructionGraph::redisassemble: done");
                        return;
                    }
                }
                _ => {
                    let length = u64::from(new_insn.length);
                    let addr = new_insn.address;
                    self.instructions.insert(new_insn.address, new_insn);
                    for j in 1..length {
                        self.instructions.remove(&(addr + j));
                    }
                    fixed_instructions = true;
                }
            }
        }
        error!("InstructionGraph::redisassemble: FIXME: Extra disassemble size was too small");
    }

    fn to_byte_array_index(&self, address: u64) -> usize {
        (address - self.first_address) as usize
    }
}
<commit_msg>Suppress a compilation warning<commit_after>use std;
use std::collections::btree_map::Iter;
use std::collections::BTreeMap;
use std::collections::HashMap;
use std::collections::HashSet;

use common::Graph;
use disassembler::*;

#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
pub enum LinkType {
    Next,
    Branch,
    Call,
    SwitchCaseJump,
}

#[derive(Serialize, Deserialize, Debug, Copy, Clone)]
pub struct Link {
    pub address: u64,
    pub target_address: u64,
    pub type_: LinkType,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct ExtraData {
    pub function_address: u64,
    pub import_name: String,
    pub is_protected: bool,
}

#[derive(Serialize, Deserialize)]
pub struct InstructionGraph {
    disassembler: Disassembler,
    bytes: Vec<u8>,
    first_address: u64,
    first_address_after_code: u64,
    instructions: BTreeMap<u64, Insn>,
    extra_data: HashMap<u64, ExtraData>,
    instruction_links: HashMap<u64, Vec<Link>>,
    reverse_links: HashMap<u64, Vec<Link>>,
    is_reversed: bool,
    #[serde(skip, default = "empty_edge_predicate")]
    edge_predicate: Box<Fn(&Link) -> bool>,
}

fn empty_edge_predicate() -> Box<Fn(&Link) -> bool> {
    Box::new(|_e| true)
}

pub fn disassemble(bytes: Vec<u8>, pc: u64) -> Result<InstructionGraph, String> {
    trace!("InstructionGraph::disassemble: 0x{:x}, {} bytes", pc, bytes.len());
    let mut disassembler = Disassembler::new();

    let instructions = disassembler.disassemble(&bytes[..], pc, 0, bytes.len());
    let mut instruction_map = BTreeMap::new();

    for instr in instructions.into_iter() {
        instruction_map.insert(instr.address, instr);
    }
    let last_instruction = instruction_map.iter().next_back().unwrap().1;

    let graph = InstructionGraph {
        disassembler,
        bytes,
        first_address: pc,
        first_address_after_code: last_instruction.address + u64::from(last_instruction.length),
        instructions: instruction_map,
        extra_data: HashMap::new(),
        instruction_links: HashMap::new(),
        reverse_links: HashMap::new(),
        is_reversed: false,
        edge_predicate: empty_edge_predicate(),
    };

    trace!("InstructionGraph::disassemble: done");
    Ok(graph)
}

impl Graph<u64, Insn, Link> for InstructionGraph {
    fn set_subgraph(&mut self, _subgraph: Option<HashSet<u64>>) -> &mut Self {
        panic!("NOT SUPPORTED");
    }

    fn set_edge_filter(&mut self, filter: Box<Fn(&Link) -> bool>) -> &mut Self {
        self.edge_predicate = filter;
        self
    }

    fn reverse_edges(&mut self) -> &mut Self {
        self.is_reversed = !self.is_reversed;
        self
    }

    fn contains(&self, vid: &u64) -> bool {
        self.instructions.contains_key(vid)
    }

    fn get_vertex(&self, vid: &u64) -> &Insn {
        &self.instructions[vid]
    }

    fn get_adjacent(&self, vid: &u64) -> Vec<Result<(&u64, &Link), String>> {
        let mut result = vec![];
        let instruction_links = if self.is_reversed {
            &self.reverse_links
        } else {
            &self.instruction_links
        };
        match instruction_links.get(vid) {
            Some(links) => for link in links.iter().filter(|e| (*self.edge_predicate)(e)) {
                let address = if self.is_reversed {
                    &link.address
                } else {
                    &link.target_address
                };
                if self.in_bounds(*address) {
                    result.push(Result::Ok((address, link)));
                } else {
                    result.push(Result::Err(format!(
                        "DFS: Jump outside of code section: {}",
                        address
                    )));
                }
            },
            None => result.push(Result::Err(format!(
                "DFS: Couldn't find links for {}",
                &self.instructions[vid].assembly()
            ))),
        }
        result
    }
}

impl InstructionGraph {
    pub fn instructions_iter(&self) -> Iter<u64, Insn> {
        self.instructions.iter()
    }

    pub fn first_address_after_code(&self) -> u64 {
        self.first_address_after_code
    }

    pub fn contains_address(&self, address: u64) -> bool {
        self.instructions.contains_key(&address)
    }

    pub fn contains(&self, instr: &Insn) -> bool {
        self.instructions.contains_key(&instr.address)
    }

    pub fn in_bounds(&self, address: u64) -> bool {
        address >= self.first_address && address < self.first_address_after_code
    }

    pub fn get_next(&self, address: u64) -> u64 {
        match (address + 1..self.first_address_after_code)
            .find(|a| self.instructions.contains_key(a))
        {
            Some(address) => address,
            None => panic!("Failed to find the next address."),
        }
    }

    pub fn get_in_value(&self, address: u64) -> u32 {
        self.reverse_links[&address].len() as u32
    }

    pub fn get_out_value(&self, address: u64) -> u32 {
        self.instruction_links[&address].len() as u32
    }

    pub fn get_bytes(&self, address: u64, size: usize) -> &[u8] {
        let addr = self.to_byte_array_index(address);
        &self.bytes[addr..(addr + size)]
    }

    pub fn get_bytes_as_hex(&self, insn: &Insn) -> String {
        let mut hex = String::new();
        for byte in self.get_bytes(insn.address, insn.length as usize) {
            hex.push_str(&format!("{:02x}", byte));
        }
        hex
    }

    pub fn get_extra_data(&self, address: u64) -> Option<&ExtraData> {
        self.extra_data.get(&address)
    }

    pub fn get_extra_data_mut(&mut self, address: u64) -> &mut ExtraData {
        self.extra_data.entry(address).or_insert(ExtraData {
            function_address: 0,
            import_name: "".to_string(),
            is_protected: false,
        })
    }

    pub fn add_link(&mut self, offset: u64, target_offset: u64, type_: LinkType) -> () {
        let link = Link {
            address: offset,
            target_address: target_offset,
            type_,
        };

        let links = match self.instruction_links.get_mut(&offset) {
            Some(links) => links,
            None => {
                let links = Vec::new();
                self.instruction_links.insert(offset, links);
                self.instruction_links.get_mut(&offset).unwrap()
            }
        };
        links.push(link);

        let reverse_links = match self.reverse_links.get_mut(&target_offset) {
            Some(links) => links,
            None => {
                let links = Vec::new();
                self.reverse_links.insert(target_offset, links);
                self.reverse_links.get_mut(&target_offset).unwrap()
            }
        };
        reverse_links.push(link);
    }

    pub fn add_jump_table_entry(&mut self, address: u64) -> bool {
        let data = self.read_u32(address);
        if !self.in_bounds(u64::from(data)) {
            false
        } else {
            self.mark_data_bytes(address, 4, "TODO: TEXT".to_string());
            true
        }
    }

    pub fn add_jump_table_indirect_entries(&mut self, address: u64, count: u8) -> () {
        let display_text = "TODO: TEXT".to_string();
        self.mark_data_bytes(address, count, display_text);
    }

    pub fn mark_data_bytes(&mut self, address: u64, length: u8, _data_display_text: String) -> () {
        // check if there is an instruction at address, otherwise split an existing one
        let mut size = match self.instructions.get(&address) {
            Some(instr) => instr.length,
            None => {
                let insn = self.split_instruction_at(address);
                insn.length - ((address - insn.address) as u8)
            }
        };
        self.instructions.insert(
            address,
            Insn {
                address,
                code: Mnemonic::Inone,
                length,
                // assembly: data_display_text,
                operands: vec![],
                prefix_segment: Reg::NONE,
                prefix_operand_size: false,
                prefix_address_size: false,
                prefix_lock: false,
                prefix_str: false,
                prefix_rep: false,
                prefix_repe: false,
                prefix_repne: false,
                br_far: false,
                opr_mode: 0,
            },
        );
        self.get_extra_data_mut(address).is_protected = true;
        // remove old instructions
        while size < length {
            let insn = self
                .instructions
                .remove(&(address + u64::from(size)))
                .unwrap();
            size += insn.length;
        }
        // if there are bytes left from the last removed instruction, re-disassemble them
        if size != length {
            let new_instructions = self.disassembler.disassemble(
                &self.bytes[..],
                address + u64::from(length),
                self.to_byte_array_index(address) + (length as usize),
                (size - length) as usize,
            );
            for new_insn in new_instructions {
                self.instructions.insert(new_insn.address, new_insn);
            }
        }
    }

    pub fn split_instruction_at(&mut self, address: u64) -> Insn {
        let mut insn_address = address - 1;
        while !self.instructions.contains_key(&insn_address) {
            insn_address -= 1;
        }
        let old_insn = &self.instructions[&insn_address].clone();
        // Split the old instruction and re-disassemble its first part
        let extra_length = (address - insn_address) as usize;
        let new_instructions = self.disassembler.disassemble(
            &self.bytes[..],
            insn_address,
            self.to_byte_array_index(insn_address),
            extra_length,
        );
        for new_insn in new_instructions {
            self.instructions.insert(new_insn.address, new_insn);
        }
        old_insn.clone()
    }

    pub fn read_u32(&self, address: u64) -> u32 {
        let addr = (address - self.first_address) as usize;
        let mut result = u32::from(self.bytes[addr]);
        result |= u32::from(self.bytes[addr + 1]) << 8;
        result |= u32::from(self.bytes[addr + 2]) << 16;
        result |= u32::from(self.bytes[addr + 3]) << 24;
        result
    }

    pub fn redisassemble(&mut self, address: u64) -> () {
        // This function will fix any instructions that were incorrectly disassembled because of the data block that was treated as code
        trace!("InstructionGraph::redisassemble: 0x{:x}", address);
        if !self.instructions.contains_key(&address) {
            self.split_instruction_at(address);
        }
        let max_disasm_length = 0x100;
        let mut disasm_length =
            std::cmp::min(max_disasm_length, self.first_address_after_code - address);
        disasm_length = (0..=disasm_length)
            .find(|len| {
                self.extra_data
                    .get(&(address + len))
                    .map_or(false, |d| d.is_protected)
            }).unwrap_or(disasm_length);
        let mut new_instructions = self.disassembler.disassemble(
            &self.bytes[..],
            address,
            self.to_byte_array_index(address),
            disasm_length as usize,
        );
        // Take 1 instruction less since it can be incorrectly disassembled (partial data)
        new_instructions.pop();
        let mut fixed_instructions = false;
        for new_insn in new_instructions {
            match self.instructions.get(&new_insn.address) {
                Some(old_insn) if old_insn.length == new_insn.length => {
                    if fixed_instructions {
                        trace!("InstructionGraph::redisassemble: done");
                        return;
                    }
                }
                _ => {
                    let length = u64::from(new_insn.length);
                    let addr = new_insn.address;
                    self.instructions.insert(new_insn.address, new_insn);
                    for j in 1..length {
                        self.instructions.remove(&(addr + j));
                    }
                    fixed_instructions = true;
                }
            }
        }
        error!("InstructionGraph::redisassemble: FIXME: Extra disassemble size was too small");
    }

    fn to_byte_array_index(&self, address: u64) -> usize {
        (address - self.first_address) as usize
    }
}
<|endoftext|>


<commit_before>extern crate num;

use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

use num::{BigInt, BigUint, Zero, One, FromPrimitive};

fn combinator(n: i32, k: i32) -> f64 {
    let mut num: f64 = 1.0;
    let mut n_aux = n;
    let mut d_aux = n - k;
    num = 1.0 / factorial(k) as f64;
    if k < d_aux {
        while n_aux > d_aux {
            num = num * n_aux as f64;
            // println!("{}", num);
            n_aux -= 1;
        }
        num
    } else {
        while n_aux > k {
            num = num * n_aux as f64;
            n_aux -= 1;
        }
        num
    }
}

fn factorial(n: i32) -> u64 {
    if n <= 1 {
        return 1;
    }
    // range(2, n + 1).product()
    let mut fact: u64 = 1;
    let mut x: u64 = 2;

    while x <= n as u64 {
        fact = fact * x;
        x += 1;
    }

    fact
}

fn binomial_distrib(n: i32, k: i32, p: f32) -> f64 {
    let q = 1.0 - p;
    // let fac_n = factorial(n) as f32;
    // let fac_k = factorial(k) as f32;
    // let fac_n_k = factorial(n - k) as f32;
    // fac_n * p.powf(k as f32) * q.powf((n - k) as f32) / fac_k / fac_n_k
    combinator(n, k) * (p.powf(k as f32) * q.powf((n - k) as f32)) as f64
}

fn do_calculation_a() {
    println!("Doing calculations");
    let val_a = binomial_distrib(40, 8, 0.35);
    let val_b = binomial_distrib(20, 12, 0.35);
    let val_c = binomial_distrib(30, 11, 0.35);
    let val_d = binomial_distrib(38, 9, 0.65);
    let val_e = binomial_distrib(51, 13, 0.65);

    println!("Writing to file");
    let mut file = File::create("EPuma_Practica04_A.txt").expect("Couldn't open write file");
    write!(file,
           "{}\n{}\n{}\n{}\n{}",
           val_a,
           val_b,
           val_c,
           val_d,
           val_e)
            .expect("Couldn't write in file");
    // write!(file, "{}", val_a).expect("Couldn't write in file");
}

fn process_file(p: &str, ctr: &mut [u32; 3]) {
    let path = Path::new(p);

    let mut file = File::open(&path).expect("Unable to open");
    let mut s = String::new();
    file.read_to_string(&mut s).expect("not able to read");

    ctr[2] = s.len() as u32;

    for c in s.chars() {
        match c {
            'A' => ctr[0] += 1,
            'G' => ctr[0] += 1,
            'C' => ctr[1] += 1,
            'T' => ctr[1] += 1,
            _ => println!("Not a valid letter"),
        }
    }
}

fn do_calculation_b() {
    let path = "practica_04_B.txt";
    let mut counter: [u32; 3] = [0; 3];
    process_file(path, &mut counter);

    let prob_pur = counter[0] as f32 / counter[2] as f32;
    let prob_pir = counter[1] as f32 / counter[2] as f32;

    println!("Pur: {}, Pir: {}, probs: {} & {}",
             counter[0],
             counter[1],
             prob_pur,
             prob_pir);

    let val_a = binomial_distrib(10, 5, prob_pur);
    let val_b = binomial_distrib(15, 7, prob_pur);
    let val_c = binomial_distrib(13, 6, prob_pir);
    let val_d = binomial_distrib(12, 3, prob_pir);

    println!("Writing to file");
    let mut file = File::create("EPuma_Practica04_B.txt").expect("Couldn't open write file");
    write!(file, "{}\n{}\n{}\n{}", val_a, val_b, val_c, val_d).expect("Couldn't write in file");
}

fn main() {
    // println!("Value: {}", binomial_distrib(20, 4, 0.3));
    do_calculation_a();
    do_calculation_b();
}
<commit_msg>deleted unused code<commit_after>extern crate num;

use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

use num::{BigInt, BigUint, Zero, One, FromPrimitive};

fn combinator(n: i32, k: i32) -> f64 {
    let mut num: f64 = 1.0;
    let mut n_aux = n;
    let mut d_aux = n - k;
    num = 1.0 / factorial(k) as f64;
    if k < d_aux {
        while n_aux > d_aux {
            num = num * n_aux as f64;
            n_aux -= 1;
        }
        num
    } else {
        while n_aux > k {
            num = num * n_aux as f64;
            n_aux -= 1;
        }
        num
    }
}

fn factorial(n: i32) -> u64 {
    if n <= 1 {
        return 1;
    }

    let mut fact: u64 = 1;
    let mut x: u64 = 2;

    while x <= n as u64 {
        fact = fact * x;
        x += 1;
    }

    fact
}

fn binomial_distrib(n: i32, k: i32, p: f32) -> f64 {
    let q = 1.0 - p;
    combinator(n, k) * (p.powf(k as f32) * q.powf((n - k) as f32)) as f64
}

fn do_calculation_a() {
    println!("Doing calculations");
    let val_a = binomial_distrib(40, 8, 0.35);
    let val_b = binomial_distrib(20, 12, 0.35);
    let val_c = binomial_distrib(30, 11, 0.35);
    let val_d = binomial_distrib(38, 9, 0.65);
    let val_e = binomial_distrib(51, 13, 0.65);

    println!("Writing to file");
    let mut file = File::create("EPuma_Practica04_A.txt").expect("Couldn't open write file");
    write!(file,
           "{}\n{}\n{}\n{}\n{}",
           val_a,
           val_b,
           val_c,
           val_d,
           val_e)
            .expect("Couldn't write in file");
}

fn process_file(p: &str, ctr: &mut [u32; 3]) {
    let path = Path::new(p);

    let mut file = File::open(&path).expect("Unable to open");
    let mut s = String::new();
    file.read_to_string(&mut s).expect("not able to read");

    ctr[2] = s.len() as u32;

    for c in s.chars() {
        match c {
            'A' => ctr[0] += 1,
            'G' => ctr[0] += 1,
            'C' => ctr[1] += 1,
            'T' => ctr[1] += 1,
            _ => println!("Not a valid letter"),
        }
    }
}

fn do_calculation_b() {
    let path = "practica_04_B.txt";
    let mut counter: [u32; 3] = [0; 3];
    process_file(path, &mut counter);

    let prob_pur = counter[0] as f32 / counter[2] as f32;
    let prob_pir = counter[1] as f32 / counter[2] as f32;

    println!("Pur: {}, Pir: {}, probs: {} & {}",
             counter[0],
             counter[1],
             prob_pur,
             prob_pir);

    let val_a = binomial_distrib(10, 5, prob_pur);
    let val_b = binomial_distrib(15, 7, prob_pur);
    let val_c = binomial_distrib(13, 6, prob_pir);
    let val_d = binomial_distrib(12, 3, prob_pir);

    println!("Writing to file");
    let mut file = File::create("EPuma_Practica04_B.txt").expect("Couldn't open write file");
    write!(file, "{}\n{}\n{}\n{}", val_a, val_b, val_c, val_d).expect("Couldn't write in file");
}

fn main() {
    do_calculation_a();
    do_calculation_b();
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Breaks rustdocs into sections according to their headers

use astsrv;
use attr_pass;
use doc::ItemUtils;
use doc;
use extract;
use fold::Fold;
use fold;

use core::str;
use core::vec;
use std::par;

pub fn mk_pass() -> Pass {
    {
        name: ~"sectionalize",
        f: run
    }
}

fn run(_srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
    let fold = Fold {
        fold_item: fold_item,
        fold_trait: fold_trait,
        fold_impl: fold_impl,
        .. fold::default_any_fold(())
    };
    (fold.fold_doc)(&fold, doc)
}

fn fold_item(fold: &fold::Fold<()>, +doc: doc::ItemDoc) -> doc::ItemDoc {
    let doc = fold::default_seq_fold_item(fold, doc);
    let (desc, sections) = sectionalize(doc.desc);

    {
        desc: desc,
        sections: sections,
        .. doc
    }
}

fn fold_trait(fold: &fold::Fold<()>, +doc: doc::TraitDoc) -> doc::TraitDoc {
    let doc = fold::default_seq_fold_trait(fold, doc);

    {
        methods: do par::map(doc.methods) |method| {
            let (desc, sections) = sectionalize(method.desc);

            {
                desc: desc,
                sections: sections,
                .. *method
            }
        },
        .. doc
    }
}

fn fold_impl(fold: &fold::Fold<()>, +doc: doc::ImplDoc) -> doc::ImplDoc {
    let doc = fold::default_seq_fold_impl(fold, doc);

    {
        methods: do par::map(doc.methods) |method| {
            let (desc, sections) = sectionalize(method.desc);

            {
                desc: desc,
                sections: sections,
                .. *method
            }
        },
        .. doc
    }
}

fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) {

    /*!
     * Take a description of the form
     *
     *     General text
     *
     *     # Section header
     *
     *     Section text
     *
     *     # Section header
     *
     *     Section text
     *
     * and remove each header and accompanying text into section records.
     */

    if desc.is_none() {
        return (None, ~[]);
    }

    let lines = str::lines(desc.get());

    let mut new_desc = None::<~str>;
    let mut current_section = None;
    let mut sections = ~[];

    for lines.each |line| {
        match parse_header(*line) {
          Some(header) => {
            if current_section.is_some() {
                sections += ~[current_section.get()];
            }
            current_section = Some({
                header: header,
                body: ~""
            });
          }
          None => {
            match copy current_section {
              Some(section) => {
                current_section = Some({
                    body: section.body + ~"\n" + *line,
                    .. section
                });
              }
              None => {
                new_desc = match new_desc {
                  Some(desc) => {
                    Some(desc + ~"\n" + *line)
                  }
                  None => {
                    Some(*line)
                  }
                };
              }
            }
          }
        }
    }

    if current_section.is_some() {
        sections += ~[current_section.get()];
    }

    (new_desc, sections)
}

fn parse_header(line: ~str) -> Option<~str> {
    if str::starts_with(line, ~"# ") {
        Some(str::slice(line, 2u, str::len(line)))
    } else {
        None
    }
}

#[test]
fn should_create_section_headers() {
    let doc = test::mk_doc(
        ~"#[doc = \"\
         # Header\n\
         Body\"]\
         mod a {
             #[legacy_exports]; }");
    assert str::contains(
        doc.cratemod().mods()[0].item.sections[0].header,
        ~"Header");
}

#[test]
fn should_create_section_bodies() {
    let doc = test::mk_doc(
        ~"#[doc = \"\
         # Header\n\
         Body\"]\
         mod a {
             #[legacy_exports]; }");
    assert str::contains(
        doc.cratemod().mods()[0].item.sections[0].body,
        ~"Body");
}

#[test]
fn should_not_create_sections_from_indented_headers() {
    let doc = test::mk_doc(
        ~"#[doc = \"\n\
         Text\n             # Header\n\
         Body\"]\
         mod a {
             #[legacy_exports]; }");
    assert vec::is_empty(doc.cratemod().mods()[0].item.sections);
}

#[test]
fn should_remove_section_text_from_main_desc() {
    let doc = test::mk_doc(
        ~"#[doc = \"\
         Description\n\n\
         # Header\n\
         Body\"]\
         mod a {
             #[legacy_exports]; }");
    assert !str::contains(
        doc.cratemod().mods()[0].desc().get(),
        ~"Header");
    assert !str::contains(
        doc.cratemod().mods()[0].desc().get(),
        ~"Body");
}

#[test]
fn should_eliminate_desc_if_it_is_just_whitespace() {
    let doc = test::mk_doc(
        ~"#[doc = \"\
         # Header\n\
         Body\"]\
         mod a {
             #[legacy_exports]; }");
    assert doc.cratemod().mods()[0].desc() == None;
}

#[test]
fn should_sectionalize_trait_methods() {
    let doc = test::mk_doc(
        ~"trait i {
         #[doc = \"\
         # Header\n\
         Body\"]\
         fn a(); }");
    assert doc.cratemod().traits()[0].methods[0].sections.len() == 1u;
}

#[test]
fn should_sectionalize_impl_methods() {
    let doc = test::mk_doc(
        ~"impl bool {
         #[doc = \"\
         # Header\n\
         Body\"]\
         fn a() { } }");
    assert doc.cratemod().impls()[0].methods[0].sections.len() == 1u;
}

#[cfg(test)]
mod test {
    #[legacy_exports];
    fn mk_doc(source: ~str) -> doc::Doc {
        do astsrv::from_str(source) |srv| {
            let doc = extract::from_srv(srv, ~"");
            let doc = (attr_pass::mk_pass().f)(srv, doc);
            run(srv, doc)
        }
    }
}
<commit_msg>librustdoc: More text fixes. rs=busted<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Breaks rustdocs into sections according to their headers

use astsrv;
use attr_pass;
use doc::ItemUtils;
use doc;
use extract;
use fold::Fold;
use fold;

use core::str;
use core::vec;
use std::par;

pub fn mk_pass() -> Pass {
    {
        name: ~"sectionalize",
        f: run
    }
}

fn run(_srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc {
    let fold = Fold {
        fold_item: fold_item,
        fold_trait: fold_trait,
        fold_impl: fold_impl,
        .. fold::default_any_fold(())
    };
    (fold.fold_doc)(&fold, doc)
}

fn fold_item(fold: &fold::Fold<()>, +doc: doc::ItemDoc) -> doc::ItemDoc {
    let doc = fold::default_seq_fold_item(fold, doc);
    let (desc, sections) = sectionalize(doc.desc);

    {
        desc: desc,
        sections: sections,
        .. doc
    }
}

fn fold_trait(fold: &fold::Fold<()>, +doc: doc::TraitDoc) -> doc::TraitDoc {
    let doc = fold::default_seq_fold_trait(fold, doc);

    {
        methods: do par::map(doc.methods) |method| {
            let (desc, sections) = sectionalize(method.desc);

            {
                desc: desc,
                sections: sections,
                .. *method
            }
        },
        .. doc
    }
}

fn fold_impl(fold: &fold::Fold<()>, +doc: doc::ImplDoc) -> doc::ImplDoc {
    let doc = fold::default_seq_fold_impl(fold, doc);

    {
        methods: do par::map(doc.methods) |method| {
            let (desc, sections) = sectionalize(method.desc);

            {
                desc: desc,
                sections: sections,
                .. *method
            }
        },
        .. doc
    }
}

fn sectionalize(desc: Option<~str>) -> (Option<~str>, ~[doc::Section]) {

    /*!
     * Take a description of the form
     *
     *     General text
     *
     *     # Section header
     *
     *     Section text
     *
     *     # Section header
     *
     *     Section text
     *
     * and remove each header and accompanying text into section records.
     */

    if desc.is_none() {
        return (None, ~[]);
    }

    let lines = str::lines(desc.get());

    let mut new_desc = None::<~str>;
    let mut current_section = None;
    let mut sections = ~[];

    for lines.each |line| {
        match parse_header(*line) {
          Some(header) => {
            if current_section.is_some() {
                sections += ~[current_section.get()];
            }
            current_section = Some({
                header: header,
                body: ~""
            });
          }
          None => {
            match copy current_section {
              Some(section) => {
                current_section = Some({
                    body: section.body + ~"\n" + *line,
                    .. section
                });
              }
              None => {
                new_desc = match new_desc {
                  Some(desc) => {
                    Some(desc + ~"\n" + *line)
                  }
                  None => {
                    Some(*line)
                  }
                };
              }
            }
          }
        }
    }

    if current_section.is_some() {
        sections += ~[current_section.get()];
    }

    (new_desc, sections)
}

fn parse_header(line: ~str) -> Option<~str> {
    if str::starts_with(line, ~"# ") {
        Some(str::slice(line, 2u, str::len(line)))
    } else {
        None
    }
}

#[test]
fn should_create_section_headers() {
    let doc = test::mk_doc(
        ~"#[doc = \"\
         # Header\n\
         Body\"]\
         mod a {
             #[legacy_exports]; }");
    assert str::contains(
        doc.cratemod().mods()[0].item.sections[0].header,
        ~"Header");
}

#[test]
fn should_create_section_bodies() {
    let doc = test::mk_doc(
        ~"#[doc = \"\
         # Header\n\
         Body\"]\
         mod a {
             #[legacy_exports]; }");
    assert str::contains(
        doc.cratemod().mods()[0].item.sections[0].body,
        ~"Body");
}

#[test]
fn should_not_create_sections_from_indented_headers() {
    let doc = test::mk_doc(
        ~"#[doc = \"\n\
         Text\n             # Header\n\
         Body\"]\
         mod a {
             #[legacy_exports]; }");
    assert vec::is_empty(doc.cratemod().mods()[0].item.sections);
}

#[test]
fn should_remove_section_text_from_main_desc() {
    let doc = test::mk_doc(
        ~"#[doc = \"\
         Description\n\n\
         # Header\n\
         Body\"]\
         mod a {
             #[legacy_exports]; }");
    assert !str::contains(
        doc.cratemod().mods()[0].desc().get(),
        ~"Header");
    assert !str::contains(
        doc.cratemod().mods()[0].desc().get(),
        ~"Body");
}

#[test]
fn should_eliminate_desc_if_it_is_just_whitespace() {
    let doc = test::mk_doc(
        ~"#[doc = \"\
         # Header\n\
         Body\"]\
         mod a {
             #[legacy_exports]; }");
    assert doc.cratemod().mods()[0].desc() == None;
}

#[test]
fn should_sectionalize_trait_methods() {
    let doc = test::mk_doc(
        ~"trait i {
         #[doc = \"\
         # Header\n\
         Body\"]\
         fn a(); }");
    assert doc.cratemod().traits()[0].methods[0].sections.len() == 1u;
}

#[test]
fn should_sectionalize_impl_methods() {
    let doc = test::mk_doc(
        ~"impl bool {
         #[doc = \"\
         # Header\n\
         Body\"]\
         fn a() { } }");
    assert doc.cratemod().impls()[0].methods[0].sections.len() == 1u;
}

#[cfg(test)]
mod test {
    #[legacy_exports];

    use astsrv;
    use attr_pass;
    use doc;
    use extract;

    fn mk_doc(source: ~str) -> doc::Doc {
        do astsrv::from_str(source) |srv| {
            let doc = extract::from_srv(srv, ~"");
            let doc = (attr_pass::mk_pass().f)(srv, doc);
            run(srv, doc)
        }
    }
}
<|endoftext|>


<commit_before>use quickcheck;
use quickcheck::{Arbitrary, Gen};
use field::Pos;
use hash_table::{HashType, HashData, HashTable};

#[derive(Clone, Copy, PartialEq, Debug)]
struct HashTypeArbitrary {
  hash_type: HashType
}

impl Arbitrary for HashTypeArbitrary {
  fn arbitrary<G: Gen>(gen: &mut G) -> HashTypeArbitrary {
    HashTypeArbitrary {
      hash_type: HashType::from((gen.next_u32() % 4) as usize)
    }
  }
}

#[test]
fn hash_data_check() {
  #[cfg_attr(feature="clippy", allow(needless_pass_by_value))]
  fn prop(depth: u32, hash_type_arbitrary: HashTypeArbitrary, pos: Pos, estimation: i32) -> bool {
    let hash_data = HashData::new(depth, hash_type_arbitrary.hash_type, pos, estimation);
    hash_data.depth() == depth &&
      hash_data.hash_type() == hash_type_arbitrary.hash_type &&
      hash_data.pos() == pos &&
      hash_data.estimation() == estimation
  }
  quickcheck::quickcheck(prop as fn(u32, HashTypeArbitrary, Pos, i32) -> bool);
}

#[test]
fn hash_table_put_get_one_entry() {
  let hash_table = HashTable::new(100);
  let hash = 1234567890u64;
  let data = HashData::new(3, HashType::Exact, 17, 1234);
  hash_table.put(hash, data);
  assert_eq!(hash_table.get(hash), data);
}

#[test]
fn hash_table_collision() {
  let hash_table = HashTable::new(100);
  let hash1 = 123u64;
  let hash2 = 723u64;
  let data1 = HashData::new(3, HashType::Exact, 17, 1234);
  let data2 = HashData::new(7, HashType::Alpha, 23, -4321);
  hash_table.put(hash1, data1);
  hash_table.put(hash2, data2);
  assert_eq!(hash_table.get(hash1).hash_type(), HashType::Empty);
  assert_eq!(hash_table.get(hash2), data2);
}
<commit_msg>Add tests.<commit_after>use quickcheck;
use quickcheck::{Arbitrary, Gen};
use field::Pos;
use hash_table::{HashType, HashData, HashTable};

#[derive(Clone, Copy, PartialEq, Debug)]
struct HashTypeArbitrary {
  hash_type: HashType
}

impl Arbitrary for HashTypeArbitrary {
  fn arbitrary<G: Gen>(gen: &mut G) -> HashTypeArbitrary {
    HashTypeArbitrary {
      hash_type: HashType::from((gen.next_u32() % 4) as usize)
    }
  }
}

#[test]
fn hash_data_check() {
  #[cfg_attr(feature="clippy", allow(needless_pass_by_value))]
  fn prop(depth: u32, hash_type_arbitrary: HashTypeArbitrary, pos: Pos, estimation: i32) -> bool {
    let hash_data = HashData::new(depth, hash_type_arbitrary.hash_type, pos, estimation);
    hash_data.depth() == depth &&
      hash_data.hash_type() == hash_type_arbitrary.hash_type &&
      hash_data.pos() == pos &&
      hash_data.estimation() == estimation
  }
  quickcheck::quickcheck(prop as fn(u32, HashTypeArbitrary, Pos, i32) -> bool);
}

#[test]
fn hash_table_put_get_one_entry() {
  let hash_table = HashTable::new(100);
  let hash = 1234567890u64;
  let data = HashData::new(3, HashType::Exact, 17, 1234);
  hash_table.put(hash, data);
  assert_eq!(hash_table.get(hash), data);
}

#[test]
fn hash_table_collision() {
  let hash_table = HashTable::new(100);
  let hash1 = 123u64;
  let hash2 = 723u64;
  let data1 = HashData::new(3, HashType::Exact, 17, 1234);
  let data2 = HashData::new(7, HashType::Alpha, 23, -4321);
  hash_table.put(hash1, data1);
  hash_table.put(hash2, data2);
  assert_eq!(hash_table.get(hash1).hash_type(), HashType::Empty);
  assert_eq!(hash_table.get(hash2), data2);
}

#[test]
fn hash_table_priority_replace() {
  let hash_table = HashTable::new(100);
  let hash = 1234567890u64;
  let data1 = HashData::new(3, HashType::Alpha, 17, 1234);
  let data2 = HashData::new(3, HashType::Exact, 19, 1237);
  hash_table.put(hash, data1);
  hash_table.put(hash, data2);
  assert_eq!(hash_table.get(hash), data2);
}

#[test]
fn hash_table_priority_remain() {
let hash_table = HashTable::new(100);
  let hash = 1234567890u64;
  let data1 = HashData::new(3, HashType::Exact, 17, 1234);
  let data2 = HashData::new(3, HashType::Alpha, 19, 1233);
  hash_table.put(hash, data1);
  hash_table.put(hash, data2);
  assert_eq!(hash_table.get(hash), data1);
}
<|endoftext|>


<commit_before>extern crate getopts;
pub use getopts::Options;
use std::collections::HashMap;
use std::num::Float;
use std::num::Int;
use std::iter::range_step;

#[macro_export]
macro_rules! solutions {
    (inputs: ($($n:ident : $ty:ty = $def:expr),*) $(sol $name:ident $content:block)+) => (
        {
            let args: Vec<String> = ::std::os::args();
            let mut opts = $crate::Options::new();

            $(
                opts.optopt("", stringify!($n), "", "VALUE");
            )*
            opts.optflag("h", "help", "Display this help text");

            let help = || {
                let brief = format!("Usage: {} [options] [versions] \nVersions: {:?}", &args[0], [$(stringify!($name)),+]);
                print!("{}", opts.usage(brief.as_slice()));
            };

            let matches = match opts.parse(args.tail()) {
                Ok(m) => m,
                Err(_) => { help(); return; }
            };

            if matches.opt_present("h") {
                help();
                return;
            }

            $(
                let $n: $ty = match matches.opt_str(stringify!($n)) {
                    Some(s) => { s.parse().unwrap_or($def) },
                    None => $def
                };
            )*

            $(
                let $name = || {
                    $content
                };
            )+

            let valid_solutions = vec![$(stringify!($name)),*];
            let solutions: Vec<&String> = matches.free.iter()
                .filter(|&m| valid_solutions.contains(&m.as_slice()))
                .collect();

            $(
                if solutions.len() <= 0 || solutions.contains(&&stringify!($name).to_string()) {
                    println!("Running: {}", stringify!($name));
                    println!("Result: {:?}", $name());
                    println!("");
                }
            )+
        }
    )
}

pub struct PrimeIterator {
    current: i64,
    previous_primes: Vec<i64>
}

impl PrimeIterator {
    pub fn new() -> PrimeIterator {
        PrimeIterator {
            current: 1,
            previous_primes: Vec::new()
        }
    }

    fn is_prime(&self, v: i64) -> bool {
        for &pp in self.previous_primes.iter() {
            if v % pp == 0 {
                return false;
            }
        }

        true
    }
}

impl Iterator for PrimeIterator {
    type Item = i64;

    fn next(&mut self) -> Option<i64> {
        loop {
            self.current += 1;

            if self.is_prime(self.current) {
                self.previous_primes.push(self.current);
                return Some(self.current);
            }
        }
    }
}

pub struct SieveOfAtkinIterator {
    ix: usize,
    generated: Vec<u64>
}

impl SieveOfAtkinIterator {
    pub fn new(limit: u64) -> SieveOfAtkinIterator {
        let sqroot = (limit as f64).sqrt() as u64 + 1;

        let mut is_prime = Vec::new();
        is_prime.resize(limit as usize, false);

        let mut primes = vec![2u64, 3];

        {
            let mut invert = |n: u64| {
                is_prime[n as usize] = !is_prime[n as usize];
            };

            for x in 0..sqroot {
                let xp2 = x*x;
                for y in 0..sqroot {
                    let yp2 = y*y;

                    let n = 3*xp2 + yp2;
                    if n <= limit && n % 12 == 7 {
                        invert(n);
                    }

                    let n = n + xp2;
                    if n <= limit && (n % 12 == 1 || n % 12 == 5) {
                        invert(n);
                    }

                    if x > y {
                        let n = n - (xp2 + 2*yp2);
                        if n <= limit && n % 12 == 11 {
                            invert(n);
                        }
                    }
                }
            }
        }

        for x in range_step(5, limit, 2) {
            if (is_prime[x as usize]) {
                for y in range_step(x*x, limit, x) {
                    is_prime[y as usize] = false;
                }

                primes.push(x as u64);
            }
        }

        SieveOfAtkinIterator {
            ix: 0,
            generated: primes
        }
    }
}

impl Iterator for SieveOfAtkinIterator {
    type Item = u64;

    fn next(&mut self) -> Option<u64> {
        self.ix += 1;
        if self.ix <= self.generated.len() {
            let val = self.generated[self.ix - 1];
            Some(val)
        } else {
            None
        }
    }
}
<commit_msg>Allow constructing a SieveOfAtkin without having an iterator<commit_after>extern crate getopts;
pub use getopts::Options;
use std::collections::HashMap;
use std::num::Float;
use std::num::Int;
use std::iter::range_step;

#[macro_export]
macro_rules! solutions {
    (inputs: ($($n:ident : $ty:ty = $def:expr),*) $(sol $name:ident $content:block)+) => (
        {
            let args: Vec<String> = ::std::os::args();
            let mut opts = $crate::Options::new();

            $(
                opts.optopt("", stringify!($n), "", "VALUE");
            )*
            opts.optflag("h", "help", "Display this help text");

            let help = || {
                let brief = format!("Usage: {} [options] [versions] \nVersions: {:?}", &args[0], [$(stringify!($name)),+]);
                print!("{}", opts.usage(brief.as_slice()));
            };

            let matches = match opts.parse(args.tail()) {
                Ok(m) => m,
                Err(_) => { help(); return; }
            };

            if matches.opt_present("h") {
                help();
                return;
            }

            $(
                let $n: $ty = match matches.opt_str(stringify!($n)) {
                    Some(s) => { s.parse().unwrap_or($def) },
                    None => $def
                };
            )*

            $(
                let $name = || {
                    $content
                };
            )+

            let valid_solutions = vec![$(stringify!($name)),*];
            let solutions: Vec<&String> = matches.free.iter()
                .filter(|&m| valid_solutions.contains(&m.as_slice()))
                .collect();

            $(
                if solutions.len() <= 0 || solutions.contains(&&stringify!($name).to_string()) {
                    println!("Running: {}", stringify!($name));
                    println!("Result: {:?}", $name());
                    println!("");
                }
            )+
        }
    )
}

pub struct PrimeIterator {
    current: i64,
    previous_primes: Vec<i64>
}

impl PrimeIterator {
    pub fn new() -> PrimeIterator {
        PrimeIterator {
            current: 1,
            previous_primes: Vec::new()
        }
    }

    fn is_prime(&self, v: i64) -> bool {
        for &pp in self.previous_primes.iter() {
            if v % pp == 0 {
                return false;
            }
        }

        true
    }
}

impl Iterator for PrimeIterator {
    type Item = i64;

    fn next(&mut self) -> Option<i64> {
        loop {
            self.current += 1;

            if self.is_prime(self.current) {
                self.previous_primes.push(self.current);
                return Some(self.current);
            }
        }
    }
}

pub struct SieveOfAtkin {
    primes: Vec<u64>
}

impl SieveOfAtkin {
    pub fn new(limit: u64) -> SieveOfAtkin {
        let sqroot = (limit as f64).sqrt() as u64 + 1;

        let mut is_prime = Vec::new();
        is_prime.resize(limit as usize, false);

        let mut primes = vec![2u64, 3];

        {
            let mut invert = |n: u64| {
                is_prime[n as usize] = !is_prime[n as usize];
            };

            for x in 0..sqroot {
                let xp2 = x*x;
                for y in 0..sqroot {
                    let yp2 = y*y;

                    let n = 3*xp2 + yp2;
                    if n <= limit && n % 12 == 7 {
                        invert(n);
                    }

                    let n = n + xp2;
                    if n <= limit && (n % 12 == 1 || n % 12 == 5) {
                        invert(n);
                    }

                    if x > y {
                        let n = n - (xp2 + 2*yp2);
                        if n <= limit && n % 12 == 11 {
                            invert(n);
                        }
                    }
                }
            }
        }

        for x in range_step(5, limit, 2) {
            if (is_prime[x as usize]) {
                for y in range_step(x*x, limit, x) {
                    is_prime[y as usize] = false;
                }

                primes.push(x as u64);
            }
        }

        SieveOfAtkin {
            primes: primes
        }
    }
}

pub struct SieveOfAtkinIterator {
    ix: usize,
    sieve: SieveOfAtkin
}

impl SieveOfAtkinIterator {
    pub fn new(limit: u64) -> SieveOfAtkinIterator {
        SieveOfAtkinIterator {
            ix: 0,
            sieve: SieveOfAtkin::new(limit)
        }
    }
}

impl Iterator for SieveOfAtkinIterator {
    type Item = u64;

    fn next(&mut self) -> Option<u64> {
        self.ix += 1;
        if self.ix <= self.sieve.primes.len() {
            let val = self.sieve.primes[self.ix - 1];
            Some(val)
        } else {
            None
        }
    }
}
<|endoftext|>


<commit_before>use std::str::FromStr;
use std::sync::Arc;

use futures::Future;
use hyper::client;
use hyper::header::Connection;
use hyper::header::ContentLength;
use hyper::header::Host;
use hyper::server::{Request, Response, Service};
use hyper::Uri;
use tokio_core::reactor::Handle;

use crate::http::app_manager::AppManager;

pub struct Dispatcher {
    app_manager: Arc<AppManager>,
    handle: Handle,
}

impl Dispatcher {
    pub fn new(app_manager: Arc<AppManager>, handle: Handle) -> Dispatcher {
        Dispatcher {
            app_manager,
            handle,
        }
    }

    fn extract_app_name(&self, request: &Request) -> String {
        let host = &request.headers().get::<Host>().unwrap().hostname();
        let host_parts = host.split('.').collect::<Vec<_>>();

        match host_parts.split_last() {
            Some((_, parts)) => parts.join("."),
            None => {
                panic!("zas: invalid Host header");
            }
        }
    }

    fn handle_zas_request(&self, _: Request) -> Box<Future<Item = Response, Error = hyper::Error>> {
        let mut response = Response::new();

        response.set_body("OK");

        Box::new(futures::future::ok(response))
    }

    fn handle_app_request(
        &self,
        request: Request,
        app_name: String,
    ) -> Box<Future<Item = Response, Error = hyper::Error>> {
        let result = self.app_manager.get_port(&app_name);

        let port = match result {
            Some(value) => value,
            None => {
                return Box::new(futures::future::ok(
                    Response::new()
                        .with_header(ContentLength("App not configured".len() as u64))
                        .with_body("App not configured"),
                ));
            }
        };

        let connection_header = match request.headers().get::<Connection>() {
            Some(value) => value.clone(),
            None => Connection::close(),
        };

        let app_url = format!("http://localhost:{}{}", port, request.uri());
        let app_uri = Uri::from_str(&app_url).unwrap();

        let mut client_req = client::Request::new(request.method().clone(), app_uri);
        client_req.headers_mut().extend(request.headers().iter());
        client_req.headers_mut().set(Connection::close());
        client_req.set_body(request.body());

        let client = hyper::Client::configure()
            .keep_alive(false)
            .build(&self.handle);

        let resp = client.request(client_req).then(move |result| match result {
            Ok(client_resp) => Ok(Response::new()
                .with_status(client_resp.status())
                .with_headers(client_resp.headers().clone())
                .with_header(connection_header)
                .with_body(client_resp.body())),
            Err(e) => {
                println!("{:?}", &e);
                Err(e)
            }
        });

        Box::new(resp)
    }
}

impl Service for Dispatcher {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = Box<Future<Item = Self::Response, Error = Self::Error>>;

    fn call(&self, request: Request) -> Self::Future {
        let app_name = self.extract_app_name(&request);

        if app_name == "zas" {
            self.handle_zas_request(request)
        } else {
            self.handle_app_request(request, app_name)
        }
    }
}
<commit_msg>refactor: Use explicit `dyn` keyword<commit_after>use std::str::FromStr;
use std::sync::Arc;

use futures::Future;
use hyper::client;
use hyper::header::Connection;
use hyper::header::ContentLength;
use hyper::header::Host;
use hyper::server::{Request, Response, Service};
use hyper::Uri;
use tokio_core::reactor::Handle;

use crate::http::app_manager::AppManager;

pub struct Dispatcher {
    app_manager: Arc<AppManager>,
    handle: Handle,
}

impl Dispatcher {
    pub fn new(app_manager: Arc<AppManager>, handle: Handle) -> Dispatcher {
        Dispatcher {
            app_manager,
            handle,
        }
    }

    fn extract_app_name(&self, request: &Request) -> String {
        let host = &request.headers().get::<Host>().unwrap().hostname();
        let host_parts = host.split('.').collect::<Vec<_>>();

        match host_parts.split_last() {
            Some((_, parts)) => parts.join("."),
            None => {
                panic!("zas: invalid Host header");
            }
        }
    }

    fn handle_zas_request(&self, _: Request) -> Box<dyn Future<Item = Response, Error = hyper::Error>> {
        let mut response = Response::new();

        response.set_body("OK");

        Box::new(futures::future::ok(response))
    }

    fn handle_app_request(
        &self,
        request: Request,
        app_name: String,
    ) -> Box<dyn Future<Item = Response, Error = hyper::Error>> {
        let result = self.app_manager.get_port(&app_name);

        let port = match result {
            Some(value) => value,
            None => {
                return Box::new(futures::future::ok(
                    Response::new()
                        .with_header(ContentLength("App not configured".len() as u64))
                        .with_body("App not configured"),
                ));
            }
        };

        let connection_header = match request.headers().get::<Connection>() {
            Some(value) => value.clone(),
            None => Connection::close(),
        };

        let app_url = format!("http://localhost:{}{}", port, request.uri());
        let app_uri = Uri::from_str(&app_url).unwrap();

        let mut client_req = client::Request::new(request.method().clone(), app_uri);
        client_req.headers_mut().extend(request.headers().iter());
        client_req.headers_mut().set(Connection::close());
        client_req.set_body(request.body());

        let client = hyper::Client::configure()
            .keep_alive(false)
            .build(&self.handle);

        let resp = client.request(client_req).then(move |result| match result {
            Ok(client_resp) => Ok(Response::new()
                .with_status(client_resp.status())
                .with_headers(client_resp.headers().clone())
                .with_header(connection_header)
                .with_body(client_resp.body())),
            Err(e) => {
                println!("{:?}", &e);
                Err(e)
            }
        });

        Box::new(resp)
    }
}

impl Service for Dispatcher {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = Box<dyn Future<Item = Self::Response, Error = Self::Error>>;

    fn call(&self, request: Request) -> Self::Future {
        let app_name = self.extract_app_name(&request);

        if app_name == "zas" {
            self.handle_zas_request(request)
        } else {
            self.handle_app_request(request, app_name)
        }
    }
}
<|endoftext|>


<commit_before>use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
// Deserialization of 'devices.json'

#[derive(Deserialize)]
pub struct DevicesDatabase {
    pub families: BTreeMap<String, FamilyData>,
}

#[derive(Deserialize)]
pub struct FamilyData {
    pub devices: BTreeMap<String, DeviceData>,
}

#[derive(Deserialize, Clone)]
pub struct DeviceData {
    pub packages: Vec<String>,
    pub idcode: u32,
    pub frames: usize,
    pub bits_per_frame: usize,
    pub pad_bits_after_frame: usize,
    pub pad_bits_before_frame: usize,
    pub frame_ecc_bits: usize,
    pub max_row: u32,
    pub max_col: u32,
    pub col_bias: u32,
    pub fuzz: bool,
}

// Deserialization of 'tilegrid.json'

#[derive(Deserialize)]
pub struct DeviceTilegrid {
    pub tiles: BTreeMap<String, TileData>,
}

#[derive(Deserialize)]
pub struct TileData {
    pub tiletype: String,
    pub x: u32,
    pub y: u32,
    pub start_bit: usize,
    pub start_frame: usize,
    pub bits: usize,
    pub frames: usize,
}

// Tile bit database structures

#[derive(Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct ConfigBit {
    pub frame: usize,
    pub bit: usize,
    pub invert: bool,
}

impl fmt::Debug for ConfigBit {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{}F{}B{}",
            match self.invert {
                true => "!",
                false => "",
            },
            self.frame,
            self.bit
        )
    }
}

#[derive(Deserialize, Serialize, Clone)]
pub struct ConfigPipData {
    pub from_wire: String,
    pub bits: BTreeSet<ConfigBit>,
}

#[derive(Deserialize, Serialize, Clone)]
pub struct ConfigWordData {
    pub defval: Vec<bool>,
    pub bits: Vec<BTreeSet<ConfigBit>>,
}

#[derive(Deserialize, Serialize, Clone)]
pub struct ConfigEnumData {
    pub defval: String,
    pub bits: BTreeMap<String, BTreeSet<ConfigBit>>,
}

#[derive(Deserialize, Serialize, Clone)]
pub struct FixedConnectionData {
    pub from_wire: String,
}

#[derive(Deserialize, Serialize, Clone)]
pub struct TileBitsDatabase {
    pub pips: BTreeMap<String, Vec<ConfigPipData>>,
    pub words: BTreeMap<String, ConfigWordData>,
    pub enums: BTreeMap<String, ConfigEnumData>,
    pub conns: BTreeMap<String, Vec<FixedConnectionData>>,
}

pub struct TileBitsData {
    tiletype: String,
    pub db: TileBitsDatabase,
    dirty: bool,
}

impl TileBitsData {
    pub fn new(tiletype: &str, db: TileBitsDatabase) -> TileBitsData {
        TileBitsData {
            tiletype: tiletype.to_string(),
            db: db.clone(),
            dirty: false,
        }
    }
    pub fn add_pip(&mut self, from: &str, to: &str, bits: BTreeSet<ConfigBit>) {
        if !self.db.pips.contains_key(to) {
            self.db.pips.insert(to.to_string(), Vec::new());
        }
        let ac = self.db.pips.get_mut(to).unwrap();
        for ad in ac.iter() {
            if ad.from_wire == from {
                if bits != ad.bits {
                    panic!(
                        "Bit conflict for {}.{}<-{} existing: {:?} new: {:?}",
                        self.tiletype, from, to, ad.bits, bits
                    );
                }
                return;
            }
        }
        self.dirty = true;
        ac.push(ConfigPipData {
            from_wire: from.to_string(),
            bits: bits.clone(),
        });
    }
    pub fn add_word(&mut self, name: &str, defval: Vec<bool>, bits: Vec<BTreeSet<ConfigBit>>) {
        self.dirty = true;
        match self.db.words.get(name) {
            None => {
                self.db.words.insert(
                    name.to_string(),
                    ConfigWordData {
                        defval: defval,
                        bits: bits.clone(),
                    },
                );
            }
            Some(word) => {
                if bits.len() != word.bits.len() {
                    panic!(
                        "Width conflict {}.{} existing: {:?} new: {:?}",
                        self.tiletype,
                        name,
                        word.bits.len(),
                        bits.len()
                    );
                }
                for (bit, (e, n)) in word.bits.iter().zip(bits.iter()).enumerate() {
                    if e != n {
                        panic!(
                            "Bit conflict for {}.{}[{}] existing: {:?} new: {:?}",
                            self.tiletype, name, bit, e, n
                        );
                    }
                }
            }
        }
    }
    pub fn add_conn(&mut self, from: &str, to: &str) {
        if !self.db.conns.contains_key(to) {
            self.db.conns.insert(to.to_string(), Vec::new());
        }
        let pc = self.db.conns.get_mut(to).unwrap();
        if pc.iter().any(|fc| fc.from_wire == from) {
            // Connection already exists
        } else {
            self.dirty = true;
            pc.push(FixedConnectionData {
                from_wire: from.to_string(),
            });
        }
    }
}

pub struct Database {
    root: String,
    devices: DevicesDatabase,
    tilegrids: HashMap<(String, String), DeviceTilegrid>,
    tilebits: HashMap<(String, String), TileBitsData>,
}

impl Database {
    pub fn new(root: &str) -> Database {
        let mut devices_json_buf = String::new();
        // read the whole file
        File::open(format!("{}/devices.json", root))
            .unwrap()
            .read_to_string(&mut devices_json_buf)
            .unwrap();
        Database {
            root: root.to_string(),
            devices: serde_json::from_str(&devices_json_buf).unwrap(),
            tilegrids: HashMap::new(),
            tilebits: HashMap::new(),
        }
    }
    // Both functions return a (family, name, data) 3-tuple
    pub fn device_by_name(&self, name: &str) -> Option<(String, String, DeviceData)> {
        for (f, fd) in self.devices.families.iter() {
            for (d, data) in fd.devices.iter() {
                if d == name {
                    return Some((f.to_string(), d.to_string(), data.clone()));
                }
            }
        }
        None
    }
    pub fn device_by_idcode(&self, idcode: u32) -> Option<(String, String, DeviceData)> {
        for (f, fd) in self.devices.families.iter() {
            for (d, data) in fd.devices.iter() {
                if data.idcode == idcode {
                    return Some((f.to_string(), d.to_string(), data.clone()));
                }
            }
        }
        None
    }
    // Tilegrid for a device by family and name
    pub fn device_tilegrid(&mut self, family: &str, device: &str) -> &DeviceTilegrid {
        let key = (family.to_string(), device.to_string());
        if !self.tilegrids.contains_key(&key) {
            let mut tg_json_buf = String::new();
            // read the whole file
            File::open(format!("{}/{}/{}/tilegrid.json", self.root, family, device))
                .unwrap()
                .read_to_string(&mut tg_json_buf)
                .unwrap();
            let tg = serde_json::from_str(&tg_json_buf).unwrap();
            self.tilegrids.insert(key.clone(), tg);
        }
        self.tilegrids.get(&key).unwrap()
    }
    // Bit database for a tile by family and tile type
    pub fn tile_bitdb(&mut self, family: &str, tiletype: &str) -> &mut TileBitsData {
        let key = (family.to_string(), tiletype.to_string());
        if !self.tilebits.contains_key(&key) {
            // read the whole file
            let filename = format!("{}/{}/tiletypes/{}.json", self.root, family, tiletype);
            let tb = if Path::new(&filename).exists() {
                let mut tt_json_buf = String::new();
                File::open(filename)
                    .unwrap()
                    .read_to_string(&mut tt_json_buf)
                    .unwrap();
                serde_json::from_str(&tt_json_buf).unwrap()
            } else {
                TileBitsDatabase {
                    pips: BTreeMap::new(),
                    words: BTreeMap::new(),
                    enums: BTreeMap::new(),
                    conns: BTreeMap::new(),
                }
            };
            self.tilebits
                .insert(key.clone(), TileBitsData::new(tiletype.clone(), tb));
        }
        self.tilebits.get_mut(&key).unwrap()
    }
    // Flush tile bit database changes to disk
    pub fn flush(&mut self) {
        for kv in self.tilebits.iter_mut() {
            let (family, tiletype) = kv.0;
            let tilebits = kv.1;
            if !tilebits.dirty {
                continue;
            }
            let tt_json_buf = serde_json::to_vec(&tilebits.db).unwrap();
            File::create(format!(
                "{}/{}/tiletypes/{}.json",
                self.root, family, tiletype
            ))
            .unwrap()
            .write_all(&tt_json_buf)
            .unwrap();
            tilebits.dirty = false;
        }
    }
}
<commit_msg>Switch from JSON to RON for bitdbs (tidier)<commit_after>use ron::ser::PrettyConfig;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet, HashMap};
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
// Deserialization of 'devices.json'

#[derive(Deserialize)]
pub struct DevicesDatabase {
    pub families: BTreeMap<String, FamilyData>,
}

#[derive(Deserialize)]
pub struct FamilyData {
    pub devices: BTreeMap<String, DeviceData>,
}

#[derive(Deserialize, Clone)]
pub struct DeviceData {
    pub packages: Vec<String>,
    pub idcode: u32,
    pub frames: usize,
    pub bits_per_frame: usize,
    pub pad_bits_after_frame: usize,
    pub pad_bits_before_frame: usize,
    pub frame_ecc_bits: usize,
    pub max_row: u32,
    pub max_col: u32,
    pub col_bias: u32,
    pub fuzz: bool,
}

// Deserialization of 'tilegrid.json'

#[derive(Deserialize)]
pub struct DeviceTilegrid {
    pub tiles: BTreeMap<String, TileData>,
}

#[derive(Deserialize)]
pub struct TileData {
    pub tiletype: String,
    pub x: u32,
    pub y: u32,
    pub start_bit: usize,
    pub start_frame: usize,
    pub bits: usize,
    pub frames: usize,
}

// Tile bit database structures

#[derive(Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct ConfigBit {
    pub frame: usize,
    pub bit: usize,
    pub invert: bool,
}

impl fmt::Debug for ConfigBit {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "{}F{}B{}",
            match self.invert {
                true => "!",
                false => "",
            },
            self.frame,
            self.bit
        )
    }
}

#[derive(Deserialize, Serialize, Clone)]
pub struct ConfigPipData {
    pub from_wire: String,
    pub bits: BTreeSet<ConfigBit>,
}

#[derive(Deserialize, Serialize, Clone)]
pub struct ConfigWordData {
    pub defval: Vec<bool>,
    pub bits: Vec<BTreeSet<ConfigBit>>,
}

#[derive(Deserialize, Serialize, Clone)]
pub struct ConfigEnumData {
    pub defval: String,
    pub bits: BTreeMap<String, BTreeSet<ConfigBit>>,
}

#[derive(Deserialize, Serialize, Clone)]
pub struct FixedConnectionData {
    pub from_wire: String,
}

#[derive(Deserialize, Serialize, Clone)]
pub struct TileBitsDatabase {
    pub pips: BTreeMap<String, Vec<ConfigPipData>>,
    pub words: BTreeMap<String, ConfigWordData>,
    pub enums: BTreeMap<String, ConfigEnumData>,
    pub conns: BTreeMap<String, Vec<FixedConnectionData>>,
}

pub struct TileBitsData {
    tiletype: String,
    pub db: TileBitsDatabase,
    dirty: bool,
}

impl TileBitsData {
    pub fn new(tiletype: &str, db: TileBitsDatabase) -> TileBitsData {
        TileBitsData {
            tiletype: tiletype.to_string(),
            db: db.clone(),
            dirty: false,
        }
    }
    pub fn add_pip(&mut self, from: &str, to: &str, bits: BTreeSet<ConfigBit>) {
        if !self.db.pips.contains_key(to) {
            self.db.pips.insert(to.to_string(), Vec::new());
        }
        let ac = self.db.pips.get_mut(to).unwrap();
        for ad in ac.iter() {
            if ad.from_wire == from {
                if bits != ad.bits {
                    panic!(
                        "Bit conflict for {}.{}<-{} existing: {:?} new: {:?}",
                        self.tiletype, from, to, ad.bits, bits
                    );
                }
                return;
            }
        }
        self.dirty = true;
        ac.push(ConfigPipData {
            from_wire: from.to_string(),
            bits: bits.clone(),
        });
    }
    pub fn add_word(&mut self, name: &str, defval: Vec<bool>, bits: Vec<BTreeSet<ConfigBit>>) {
        self.dirty = true;
        match self.db.words.get(name) {
            None => {
                self.db.words.insert(
                    name.to_string(),
                    ConfigWordData {
                        defval: defval,
                        bits: bits.clone(),
                    },
                );
            }
            Some(word) => {
                if bits.len() != word.bits.len() {
                    panic!(
                        "Width conflict {}.{} existing: {:?} new: {:?}",
                        self.tiletype,
                        name,
                        word.bits.len(),
                        bits.len()
                    );
                }
                for (bit, (e, n)) in word.bits.iter().zip(bits.iter()).enumerate() {
                    if e != n {
                        panic!(
                            "Bit conflict for {}.{}[{}] existing: {:?} new: {:?}",
                            self.tiletype, name, bit, e, n
                        );
                    }
                }
            }
        }
    }
    pub fn add_conn(&mut self, from: &str, to: &str) {
        if !self.db.conns.contains_key(to) {
            self.db.conns.insert(to.to_string(), Vec::new());
        }
        let pc = self.db.conns.get_mut(to).unwrap();
        if pc.iter().any(|fc| fc.from_wire == from) {
            // Connection already exists
        } else {
            self.dirty = true;
            pc.push(FixedConnectionData {
                from_wire: from.to_string(),
            });
        }
    }
}

pub struct Database {
    root: String,
    devices: DevicesDatabase,
    tilegrids: HashMap<(String, String), DeviceTilegrid>,
    tilebits: HashMap<(String, String), TileBitsData>,
}

impl Database {
    pub fn new(root: &str) -> Database {
        let mut devices_json_buf = String::new();
        // read the whole file
        File::open(format!("{}/devices.json", root))
            .unwrap()
            .read_to_string(&mut devices_json_buf)
            .unwrap();
        Database {
            root: root.to_string(),
            devices: serde_json::from_str(&devices_json_buf).unwrap(),
            tilegrids: HashMap::new(),
            tilebits: HashMap::new(),
        }
    }
    // Both functions return a (family, name, data) 3-tuple
    pub fn device_by_name(&self, name: &str) -> Option<(String, String, DeviceData)> {
        for (f, fd) in self.devices.families.iter() {
            for (d, data) in fd.devices.iter() {
                if d == name {
                    return Some((f.to_string(), d.to_string(), data.clone()));
                }
            }
        }
        None
    }
    pub fn device_by_idcode(&self, idcode: u32) -> Option<(String, String, DeviceData)> {
        for (f, fd) in self.devices.families.iter() {
            for (d, data) in fd.devices.iter() {
                if data.idcode == idcode {
                    return Some((f.to_string(), d.to_string(), data.clone()));
                }
            }
        }
        None
    }
    // Tilegrid for a device by family and name
    pub fn device_tilegrid(&mut self, family: &str, device: &str) -> &DeviceTilegrid {
        let key = (family.to_string(), device.to_string());
        if !self.tilegrids.contains_key(&key) {
            let mut tg_json_buf = String::new();
            // read the whole file
            File::open(format!("{}/{}/{}/tilegrid.json", self.root, family, device))
                .unwrap()
                .read_to_string(&mut tg_json_buf)
                .unwrap();
            let tg = serde_json::from_str(&tg_json_buf).unwrap();
            self.tilegrids.insert(key.clone(), tg);
        }
        self.tilegrids.get(&key).unwrap()
    }
    // Bit database for a tile by family and tile type
    pub fn tile_bitdb(&mut self, family: &str, tiletype: &str) -> &mut TileBitsData {
        let key = (family.to_string(), tiletype.to_string());
        if !self.tilebits.contains_key(&key) {
            // read the whole file
            let filename = format!("{}/{}/tiletypes/{}.ron", self.root, family, tiletype);
            let tb = if Path::new(&filename).exists() {
                let mut tt_ron_buf = String::new();
                File::open(filename)
                    .unwrap()
                    .read_to_string(&mut tt_ron_buf)
                    .unwrap();
                ron::de::from_str(&tt_ron_buf).unwrap()
            } else {
                TileBitsDatabase {
                    pips: BTreeMap::new(),
                    words: BTreeMap::new(),
                    enums: BTreeMap::new(),
                    conns: BTreeMap::new(),
                }
            };
            self.tilebits
                .insert(key.clone(), TileBitsData::new(tiletype.clone(), tb));
        }
        self.tilebits.get_mut(&key).unwrap()
    }
    // Flush tile bit database changes to disk
    pub fn flush(&mut self) {
        for kv in self.tilebits.iter_mut() {
            let (family, tiletype) = kv.0;
            let tilebits = kv.1;
            if !tilebits.dirty {
                continue;
            }
            let pretty = PrettyConfig {
                depth_limit: 5,
                new_line: "\n".to_string(),
                indentor: "  ".to_string(),
                enumerate_arrays: false,
                separate_tuple_members: false,
            };
            let tt_ron_buf = ron::ser::to_string_pretty(&tilebits.db, pretty).unwrap();
            File::create(format!(
                "{}/{}/tiletypes/{}.ron",
                self.root, family, tiletype
            ))
            .unwrap()
            .write_all(tt_ron_buf.as_bytes())
            .unwrap();
            tilebits.dirty = false;
        }
    }
}
<|endoftext|>


<commit_before>#![feature(convert)]
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate yak_client;
use std::env;

use yak_client::Client;

fn open_from_env(env_var: &str, name: &str) -> Client {
  let yak_url = env::var(env_var).ok()
    .expect(format!("env var {} not found", env_var).as_str());
  let full_url = format!("{}-{}", yak_url, name);
  Client::connect(&full_url).unwrap()
}

fn open_client(name: &str) -> (Client, Client) {
  let head = open_from_env("YAK_HEAD", name);
  let tail = open_from_env("YAK_TAIL", name);
  (head, tail)
}

#[test]
fn test_put_read_empty() {
  env_logger::init().unwrap_or(());

  let (mut head, mut tail) = open_client("test_put_read_empty");
  let key = "key";
  let val = "value";

  head.truncate().unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 0);
}

#[test]
fn test_put_read_single_value() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_put_read_single_value");
  let key = "key";
  let val = "value";

  head.truncate().unwrap();

  head.write(key.as_bytes(), val.as_bytes()).unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 1);
  assert_eq!(resp[0].content, val.as_bytes())
}

#[test]
fn test_put_read_persistence() {
  env_logger::init().unwrap_or(());
  let key = "key";
  let val = "value";
  {
    let (mut head, mut tail) = open_client("test_put_read_persistence");

    head.truncate().unwrap();

    head.write(key.as_bytes(), val.as_bytes()).unwrap();
  }

  {
    let (mut head, mut tail) = open_client("test_put_read_persistence");
    let resp = tail.read(key.as_bytes()).unwrap();
    assert_eq!(resp.len(), 1);
    assert_eq!(resp[0].content, val.as_bytes())
  }
}

#[test]
fn test_put_read_two_values() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_put_read_two_values");
  let key = "key";
  let vals = vec!["a".as_bytes(), "b".as_bytes()];

  head.truncate().unwrap();

  for val in &vals {
    head.write(key.as_bytes(), &val).unwrap();
  }

  let resp = tail.read(key.as_bytes()).unwrap();
  let returned : Vec<Vec<u8>> = resp.iter().map(|v| v.content.clone()).collect();
  assert_eq!(returned, vals);
}

#[test]
fn test_truncate() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_truncate");
  let key = "key";
  let val = "value";

  head.truncate().unwrap();
  head.write(key.as_bytes(), val.as_bytes()).unwrap();
  head.truncate().unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 0);
}
<commit_msg>Tidy warnings.<commit_after>#![feature(convert)]
#[macro_use]
extern crate log;
extern crate env_logger;
extern crate yak_client;
use std::env;

use yak_client::Client;

fn open_from_env(env_var: &str, name: &str) -> Client {
  let yak_url = env::var(env_var).ok()
    .expect(format!("env var {} not found", env_var).as_str());
  let full_url = format!("{}-{}", yak_url, name);
  Client::connect(&full_url).unwrap()
}

fn open_client(name: &str) -> (Client, Client) {
  let head = open_from_env("YAK_HEAD", name);
  let tail = open_from_env("YAK_TAIL", name);
  (head, tail)
}

#[test]
fn test_put_read_empty() {
  env_logger::init().unwrap_or(());

  let (mut head, mut tail) = open_client("test_put_read_empty");
  let key = "key";

  head.truncate().unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 0);
}

#[test]
fn test_put_read_single_value() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_put_read_single_value");
  let key = "key";
  let val = "value";

  head.truncate().unwrap();

  head.write(key.as_bytes(), val.as_bytes()).unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 1);
  assert_eq!(resp[0].content, val.as_bytes())
}

#[test]
fn test_put_read_persistence() {
  env_logger::init().unwrap_or(());
  let key = "key";
  let val = "value";
  {
    let (mut head, _) = open_client("test_put_read_persistence");

    head.truncate().unwrap();

    head.write(key.as_bytes(), val.as_bytes()).unwrap();
  }

  {
    let (_, mut tail) = open_client("test_put_read_persistence");
    let resp = tail.read(key.as_bytes()).unwrap();
    assert_eq!(resp.len(), 1);
    assert_eq!(resp[0].content, val.as_bytes())
  }
}

#[test]
fn test_put_read_two_values() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_put_read_two_values");
  let key = "key";
  let vals = vec!["a".as_bytes(), "b".as_bytes()];

  head.truncate().unwrap();

  for val in &vals {
    head.write(key.as_bytes(), &val).unwrap();
  }

  let resp = tail.read(key.as_bytes()).unwrap();
  let returned : Vec<Vec<u8>> = resp.iter().map(|v| v.content.clone()).collect();
  assert_eq!(returned, vals);
}

#[test]
fn test_truncate() {
  env_logger::init().unwrap_or(());
  let (mut head, mut tail) = open_client("test_truncate");
  let key = "key";
  let val = "value";

  head.truncate().unwrap();
  head.write(key.as_bytes(), val.as_bytes()).unwrap();
  head.truncate().unwrap();

  let resp = tail.read(key.as_bytes()).unwrap();
  assert_eq!(resp.len(), 0);
}
<|endoftext|>


<commit_before><commit_msg>build.rs: Wrap KernelSrc, Remove conditional compilation<commit_after><|endoftext|>


<commit_before><commit_msg>minor changes to pass the format check<commit_after><|endoftext|>


<commit_before>#![recursion_limit = "128"]
#![feature(proc_macro)]

#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
extern crate proc_macro;

use syn::{Visibility, Ident, Type, Expr};
use syn::synom::Synom;
use syn::spanned::Spanned;
use proc_macro::TokenStream;

/// Parses the following syntax, which aligns with the input of the real
/// `lazy_static` crate.
///
///     lazy_static! {
///         $VISIBILITY static ref $NAME: $TYPE = $EXPR;
///     }
///
/// For example:
///
///     lazy_static! {
///         static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
///     }
struct LazyStatic {
    visibility: Visibility,
    name: Ident,
    ty: Type,
    init: Expr,
}

impl Synom for LazyStatic {
    named!(parse -> Self, do_parse!(
        visibility: syn!(Visibility) >>
        keyword!(static) >>
        keyword!(ref) >>
        name: syn!(Ident) >>
        punct!(:) >>
        ty: syn!(Type) >>
        punct!(=) >>
        init: syn!(Expr) >>
        punct!(;) >>
        (LazyStatic { visibility, name, ty, init })
    ));
}

#[proc_macro]
pub fn lazy_static(input: TokenStream) -> TokenStream {
    let LazyStatic { visibility, name, ty, init } = syn::parse(input).unwrap();

    if name == "FOO" {
        name.span().unstable()
            .warning("come on, pick a more creative name")
            .emit();
    }

    if let Type::Tuple(ref ty) = ty {
        if ty.elems.is_empty() {
            ty.span().unstable()
                .error("I can't think of a legitimate use for lazily initializing `()`")
                .emit();
            return TokenStream::empty();
        }
    }

    // FIXME: ty.span().resolved_at(def_site)
    let ty_span = ty.span();
    let assert_sync = quote_spanned! {ty_span,
        fn assert_sync<T: Sync>() {}
        let _ = assert_sync::<#ty>;
    };

    // FIXME: init.span().resolved_at(def_site)
    let init_span = init.span();
    let init_ptr = quote_spanned! {init_span,
        Box::into_raw(Box::new(#init))
    };

    let expanded = quote! {
        extern crate std;

        #visibility struct #name;

        impl std::ops::Deref for #name {
            type Target = #ty;

            fn deref(&self) -> &#ty {
                #assert_sync

                static ONCE: std::sync::Once = std::sync::ONCE_INIT;
                static mut VALUE: *const #ty = 0 as *const #ty;

                unsafe {
                    ONCE.call_once(|| VALUE = #init_ptr);
                    &*VALUE
                }
            }
        }
    };

    expanded.into()
}
<commit_msg>Remove `assert_sync` from the error message<commit_after>#![recursion_limit = "128"]
#![feature(proc_macro)]

#[macro_use]
extern crate syn;
#[macro_use]
extern crate quote;
extern crate proc_macro;

use syn::{Visibility, Ident, Type, Expr};
use syn::synom::Synom;
use syn::spanned::Spanned;
use proc_macro::TokenStream;

/// Parses the following syntax, which aligns with the input of the real
/// `lazy_static` crate.
///
///     lazy_static! {
///         $VISIBILITY static ref $NAME: $TYPE = $EXPR;
///     }
///
/// For example:
///
///     lazy_static! {
///         static ref USERNAME: Regex = Regex::new("^[a-z0-9_-]{3,16}$").unwrap();
///     }
struct LazyStatic {
    visibility: Visibility,
    name: Ident,
    ty: Type,
    init: Expr,
}

impl Synom for LazyStatic {
    named!(parse -> Self, do_parse!(
        visibility: syn!(Visibility) >>
        keyword!(static) >>
        keyword!(ref) >>
        name: syn!(Ident) >>
        punct!(:) >>
        ty: syn!(Type) >>
        punct!(=) >>
        init: syn!(Expr) >>
        punct!(;) >>
        (LazyStatic { visibility, name, ty, init })
    ));
}

#[proc_macro]
pub fn lazy_static(input: TokenStream) -> TokenStream {
    let LazyStatic { visibility, name, ty, init } = syn::parse(input).unwrap();

    if name == "FOO" {
        name.span().unstable()
            .warning("come on, pick a more creative name")
            .emit();
    }

    if let Type::Tuple(ref ty) = ty {
        if ty.elems.is_empty() {
            ty.span().unstable()
                .error("I can't think of a legitimate use for lazily initializing `()`")
                .emit();
            return TokenStream::empty();
        }
    }

    // FIXME: ty.span().resolved_at(def_site)
    let ty_span = ty.span();
    let assert_sync = quote_spanned! {ty_span,
        struct _Assert where #ty: Sync;
    };

    // FIXME: init.span().resolved_at(def_site)
    let init_span = init.span();
    let init_ptr = quote_spanned! {init_span,
        Box::into_raw(Box::new(#init))
    };

    let expanded = quote! {
        extern crate std;

        #visibility struct #name;

        impl std::ops::Deref for #name {
            type Target = #ty;

            fn deref(&self) -> &#ty {
                #assert_sync

                static ONCE: std::sync::Once = std::sync::ONCE_INIT;
                static mut VALUE: *const #ty = 0 as *const #ty;

                unsafe {
                    ONCE.call_once(|| VALUE = #init_ptr);
                    &*VALUE
                }
            }
        }
    };

    expanded.into()
}
<|endoftext|>