<commit_before>extern crate rocket;

use rocket::request::{FromForm, FormItems};

pub struct SelectStructResult {sql: String}
pub struct WhereStructResult {
    sql: String, values: Vec<String>,
}

// My Results
type QueryOpResult = Result<&'static str, String>;
type SelectResult = Result<SelectStructResult, String>;
type WhereResult = Result<WhereStructResult, String>;

// TODO: Move there later
pub struct Params {
    pub k: String, pub v: String,
}
// implement QueryString
pub struct QueryString {
    pub query: Vec<Params>
}

impl<'f> FromForm<'f> for QueryString {
    type Error = ();

    fn from_form(items: &mut FormItems<'f>, strict: bool) -> Result<QueryString, ()> {
        let mut qs: QueryString = QueryString{ query: Vec::new() };
        for (k, v) in items {
            qs.query.push(Params{k: k.to_string(), v: v.url_decode().unwrap()});
        }
        Ok(qs)
    }
}

pub fn query_operator(qop: &str) -> QueryOpResult {
    match &qop[..] {
        "$eq" => Ok("="),
        "$ne" => Ok("!="),
        "$gt" => Ok(">"),
        "$lt" => Ok("<"),
        "$gte" => Ok(">="),
        "$lte" => Ok("<="),
        "$in" => Ok("IN"),
        "$nin" => Ok("NOT IN"),
        "$notnull" => Ok("IS NOT NULL"),
        "$null" => Ok("IS NULL"),
         _ => Err(format!("operator {} not found", qop)),
    }
}

fn collect_params(v: &Vec<Params>, collect_values: bool) -> Vec<String> {
    let mut pid: i32 = 0;
    v.iter()
        .map(|param| {
            pid = pid + 1;
            let result = match param.v.contains(".") {
                true => {
                    let value_splited = param.v.split(".").collect::<Vec<&str>>();
                    let operator = match query_operator(value_splited[0]) {
                        Ok(op) => op,
                        _ => "operator not found"
                    };
                    (operator, value_splited[1])
                },
                _ => ("=", param.v.as_str())
            };
            if collect_values {
                format!("{}", result.1)
            } else {
                format!("{}{}${}", param.k, result.0, pid)
            }
        })
        .collect()
}

pub fn ext_select(qs: QueryString) -> SelectResult {
    let mut select_syntax: String = "SELECT * FROM".to_string();
    let select_param = qs.query.iter().find(|param| param.k == "_select".to_string());
    let columns = match select_param {
        Some(param) => &param.v,
        _ => return Err("".to_string())
    };

    // empty string means that isn't `_select` command
    if columns != "" {
        select_syntax = format!("SELECT {} FROM", columns);
    }

    Ok(SelectStructResult{ sql: select_syntax })
}

// Get QueryString and return chunck WHERE statement with values
pub fn ext_where(qs: QueryString) -> WhereResult {
    let where_syntax: String;
    let ref iter_params = qs.query;
    let where_values = collect_params(iter_params, true);
    let where_fields = collect_params(iter_params, false);

    if where_fields.len() > 1 {
        where_syntax = format!("WHERE {}", where_fields.join(" AND "));
    } else {
        where_syntax = format!("WHERE {}", where_fields.join(" "));
    }

    Ok(WhereStructResult {
        sql: where_syntax,
        values: where_values
    })
}

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

    #[test]
    fn get_opetators() {
        use std::collections::HashMap;

        let mut test_cases = HashMap::new();
        test_cases.insert("$eq", "=");
        test_cases.insert("$ne", "!=");
        test_cases.insert("$gt", ">");
        test_cases.insert("$gte", ">=");
        test_cases.insert("$lt", "<");
        test_cases.insert("$lte", "<=");
        test_cases.insert("$in", "IN");
        test_cases.insert("$nin", "NOT IN");
        test_cases.insert("$notnull", "IS NOT NULL");
        test_cases.insert("$null", "IS NULL");

        for (op, expected) in &test_cases {
            match query_operator(&op.to_string()) {
                Ok(x) => assert_eq!(expected.to_string(), x),
                Err(e) => assert_eq!("", e)
            }
        }
    }

    #[test]
    fn get_opetators_error() {
        let invalid = "!tn".to_string();
        match query_operator(&invalid) {
            Ok(_) => println!("no result"),
            Err(e) => assert_eq!(format!("operator {} not found", invalid), e)
        }
    }

    #[test]
    fn where_by_request_one_querystring() {
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "5".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id=$1".to_string());
        assert_eq!(result.values, vec!["5".to_string()])
    }

    #[test]
    fn where_by_request_n_querystring() {
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id=$1 AND name=$2".to_string());
        assert_eq!(result.values, vec!["5".to_string(), "goga".to_string()])
    }

    #[test]
    fn where_by_request_with_query_operators(){
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "$ne.5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id!=$1 AND name=$2".to_string());
        assert_eq!(result.values, vec!["5".to_string(), "goga".to_string()])
    }

    #[test]
    fn where_by_request_with_query_invalid_operators(){
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "$nt.5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        match ext_where(qs) {
            Err(e) => assert_eq!(e, "operator $nt not found"),
            Ok(x) => println!("no result: {}", x.sql)
        }
    }

    #[test]
    fn select_by_request_one_column() {
        let mut hm = Vec::new();
        hm.push(Params{k: "_select".to_string(), v: "name".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_select(qs)
            .unwrap();
        assert_eq!(result.sql, "SELECT name FROM");
    }

    #[test]
    fn select_by_request_n_column() {
        let mut hm = Vec::new();
        hm.push(Params{k: "_select".to_string(), v: "name,age".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_select(qs)
            .unwrap();
        assert_eq!(result.sql, "SELECT name,age FROM");
    }
}
<commit_msg>BUGFIX tests<commit_after>extern crate rocket;

use rocket::request::{FromForm, FormItems};

pub struct SelectStructResult {sql: String}
pub struct WhereStructResult {
    sql: String, values: Vec<String>,
}

// My Results
type QueryOpResult = Result<&'static str, String>;
type SelectResult = Result<SelectStructResult, String>;
type WhereResult = Result<WhereStructResult, String>;

// TODO: Move there later
pub struct Params {
    pub k: String, pub v: String,
}
// implement QueryString
pub struct QueryString {
    pub query: Vec<Params>
}

impl<'f> FromForm<'f> for QueryString {
    type Error = ();

    fn from_form(items: &mut FormItems<'f>, strict: bool) -> Result<QueryString, ()> {
        let mut qs: QueryString = QueryString{ query: Vec::new() };
        for (k, v) in items {
            qs.query.push(Params{k: k.to_string(), v: v.url_decode().unwrap()});
        }
        Ok(qs)
    }
}

pub fn query_operator(qop: &str) -> QueryOpResult {
    match &qop[..] {
        "$eq" => Ok("="),
        "$ne" => Ok("!="),
        "$gt" => Ok(">"),
        "$lt" => Ok("<"),
        "$gte" => Ok(">="),
        "$lte" => Ok("<="),
        "$in" => Ok("IN"),
        "$nin" => Ok("NOT IN"),
        "$notnull" => Ok("IS NOT NULL"),
        "$null" => Ok("IS NULL"),
         _ => Err(format!("operator {} not found", qop)),
    }
}

fn collect_params(v: &Vec<Params>, collect_values: bool) -> Result<Vec<String>,String> {
    let mut pid: i32 = 0;
    v.iter()
        .map(|param| {
            pid = pid + 1;
            let result = match param.v.contains(".") {
                true => {
                    let value_splited = param.v.split(".").collect::<Vec<&str>>();
                    let operator = match query_operator(value_splited[0]) {
                        Ok(op) => op,
                        Err(e) => return Err(e)
                    };
                    (operator, value_splited[1])
                },
                _ => ("=", param.v.as_str())
            };
            if collect_values {
                Ok(format!("{}", result.1))
            } else {
                Ok(format!("{}{}${}", param.k, result.0, pid))
            }
        })
        .collect()
}

pub fn ext_select(qs: QueryString) -> SelectResult {
    let mut select_syntax: String = "SELECT * FROM".to_string();
    let select_param = qs.query.iter().find(|param| param.k == "_select".to_string());
    let columns = match select_param {
        Some(param) => &param.v,
        _ => return Err("".to_string())
    };

    // empty string means that isn't `_select` command
    if columns != "" {
        select_syntax = format!("SELECT {} FROM", columns);
    }

    Ok(SelectStructResult{ sql: select_syntax })
}

// Get QueryString and return chunck WHERE statement with values
pub fn ext_where(qs: QueryString) -> WhereResult {
    let where_syntax: String;
    let ref iter_params = qs.query;
    let where_values = match collect_params(iter_params, true) {
        Ok(result) => result,
        Err(e) => return Err(e.to_string())
    };
    let where_fields = match collect_params(iter_params, false) {
        Ok(result) => result,
        Err(e) => return Err(e.to_string())
    };

    if where_fields.len() > 1 {
        where_syntax = format!("WHERE {}", where_fields.join(" AND "));
    } else {
        where_syntax = format!("WHERE {}", where_fields.join(" "));
    }

    Ok(WhereStructResult {
        sql: where_syntax,
        values: where_values
    })
}

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

    #[test]
    fn get_opetators() {
        use std::collections::HashMap;

        let mut test_cases = HashMap::new();
        test_cases.insert("$eq", "=");
        test_cases.insert("$ne", "!=");
        test_cases.insert("$gt", ">");
        test_cases.insert("$gte", ">=");
        test_cases.insert("$lt", "<");
        test_cases.insert("$lte", "<=");
        test_cases.insert("$in", "IN");
        test_cases.insert("$nin", "NOT IN");
        test_cases.insert("$notnull", "IS NOT NULL");
        test_cases.insert("$null", "IS NULL");

        for (op, expected) in &test_cases {
            match query_operator(&op.to_string()) {
                Ok(x) => assert_eq!(expected.to_string(), x),
                Err(e) => assert_eq!("", e)
            }
        }
    }

    #[test]
    fn get_opetators_error() {
        let invalid = "!tn".to_string();
        match query_operator(&invalid) {
            Ok(_) => println!("no result"),
            Err(e) => assert_eq!(format!("operator {} not found", invalid), e)
        }
    }

    #[test]
    fn where_by_request_one_querystring() {
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "5".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id=$1".to_string());
        assert_eq!(result.values, vec!["5".to_string()])
    }

    #[test]
    fn where_by_request_n_querystring() {
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id=$1 AND name=$2".to_string());
        assert_eq!(result.values, vec!["5".to_string(), "goga".to_string()])
    }

    #[test]
    fn where_by_request_with_query_operators(){
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "$ne.5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_where(qs)
            .unwrap();
        assert_eq!(result.sql, "WHERE user_id!=$1 AND name=$2".to_string());
        assert_eq!(result.values, vec!["5".to_string(), "goga".to_string()])
    }

    #[test]
    fn where_by_request_with_query_invalid_operators(){
        let mut hm = Vec::new();
        hm.push(Params{k: "user_id".to_string(), v: "$nt.5".to_string()});
        hm.push(Params{k: "name".to_string(), v: "goga".to_string()});

        let qs = QueryString{ query: hm };
        match ext_where(qs) {
            Err(e) => assert_eq!(e, "operator $nt not found"),
            Ok(_) => println!("no result")
        }
    }

    #[test]
    fn select_by_request_one_column() {
        let mut hm = Vec::new();
        hm.push(Params{k: "_select".to_string(), v: "name".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_select(qs)
            .unwrap();
        assert_eq!(result.sql, "SELECT name FROM");
    }

    #[test]
    fn select_by_request_n_column() {
        let mut hm = Vec::new();
        hm.push(Params{k: "_select".to_string(), v: "name,age".to_string()});

        let qs = QueryString{ query: hm };
        let result = ext_select(qs)
            .unwrap();
        assert_eq!(result.sql, "SELECT name,age FROM");
    }
}
<|endoftext|>


<commit_before>//! Functions to read and write control registers.

pub use super::model_specific::{Efer, EferFlags};

use structures::paging::PhysFrame;
use PhysAddr;

/// Various control flags modifying the basic operation of the CPU.
pub struct Cr0;

impl Cr0 {
    /// Read the current set of CR0 flags.
    pub fn read() -> Cr0Flags {
        Cr0Flags::from_bits_truncate(Self::read_raw())
    }

    /// Read the current raw CR0 value.
    pub fn read_raw() -> u64 {
        let value: u64;
        unsafe {
            asm!("mov %cr0, $0" : "=r" (value));
        }
        value
    }

    /// Write CR0 flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
    /// safety by e.g. disabling paging.
    pub unsafe fn write(flags: Cr0Flags) {
        let old_value = Self::read_raw();
        let reserved = old_value & !(Cr0Flags::all().bits());
        let new_value = reserved | flags.bits();

        asm!("mov $0, %cr0" :: "r" (new_value) : "memory")
    }

    /// Updates CR0 flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
    /// safety by e.g. disabling paging.
    pub unsafe fn update<F>(f: F)
    where
        F: FnOnce(&mut Cr0Flags),
    {
        let mut flags = Self::read();
        f(&mut flags);
        Self::write(flags);
    }
}

bitflags! {
    pub struct Cr0Flags: u64 {
        const PROTECTED_MODE_ENABLE = 1 << 0;
        const MONITOR_COPROCESSOR = 1 << 1;
        const EMULATION = 1 << 2;
        const TASK_SWITCHED = 1 << 3;
        const EXTENSION_TYPE = 1 << 4;
        const NUMERIC_ERROR = 1 << 5;
        const WRITE_PROTECT = 1 << 16;
        const ALIGNMENT_MASK = 1 << 18;
        const NON_WRITE_THROUGH = 1 << 29;
        const CACHE_DISABLE = 1 << 30;
        const PAGING = 1 << 31;
    }
}

/// Contains the physical address of the level 4 page table.
pub struct Cr3;

impl Cr3 {
    /// Read the current P4 table address from the CR3 register.
    pub fn read() -> (PhysFrame, Cr3Flags) {
        let value: u64;
        unsafe {
            asm!("mov %cr3, $0" : "=r" (value));
        }
        let flags = Cr3Flags::from_bits_truncate(value);
        let addr = PhysAddr::new(value & 0x_000f_ffff_ffff_f000);
        let frame = PhysFrame::containing_address(addr);
        (frame, flags)
    }

    /// Write a new P4 table address into the CR3 register.
    ///
    /// ## Safety
    /// Changing the level 4 page table is unsafe, because it's possible to violate memory safety by
    /// changing the page mapping.
    pub unsafe fn write(frame: PhysFrame, flags: Cr3Flags) {
        let addr = frame.start_address();
        let value = addr.as_u64() | flags.bits();
        asm!("mov $0, %cr3" :: "r" (value) : "memory")
    }
}

bitflags! {
    /// Controls cache settings for the level 4 page table.
    pub struct Cr3Flags: u64 {
        /// Use a writethrough cache policy for the P4 table (else a writeback policy is used).
        const PAGE_LEVEL_WRITETHROUGH = 1 << 3;
        /// Disable caching for the P4 table.
        const PAGE_LEVEL_CACHE_DISABLE = 1 << 4;
    }
}
<commit_msg>Document and tweak Cr0Flags<commit_after>//! Functions to read and write control registers.

pub use super::model_specific::{Efer, EferFlags};

use structures::paging::PhysFrame;
use PhysAddr;

/// Various control flags modifying the basic operation of the CPU.
pub struct Cr0;

impl Cr0 {
    /// Read the current set of CR0 flags.
    pub fn read() -> Cr0Flags {
        Cr0Flags::from_bits_truncate(Self::read_raw())
    }

    /// Read the current raw CR0 value.
    pub fn read_raw() -> u64 {
        let value: u64;
        unsafe {
            asm!("mov %cr0, $0" : "=r" (value));
        }
        value
    }

    /// Write CR0 flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
    /// safety by e.g. disabling paging.
    pub unsafe fn write(flags: Cr0Flags) {
        let old_value = Self::read_raw();
        let reserved = old_value & !(Cr0Flags::all().bits());
        let new_value = reserved | flags.bits();

        Self::write_raw(new_value);
    }

    /// Write raw CR0 flags.
    ///
    /// Does _not_ preserve any values, including reserved fields. Unsafe because it's possible to violate memory
    /// safety by e.g. disabling paging.
    pub unsafe fn write_raw(value: u64) {
        asm!("mov $0, %cr0" :: "r" (value) : "memory")
    }

    /// Updates CR0 flags.
    ///
    /// Preserves the value of reserved fields. Unsafe because it's possible to violate memory
    /// safety by e.g. disabling paging.
    pub unsafe fn update<F>(f: F)
    where
        F: FnOnce(&mut Cr0Flags),
    {
        let mut flags = Self::read();
        f(&mut flags);
        Self::write(flags);
    }
}

bitflags! {
    /// Configuration flags of the Cr0 register.
    pub struct Cr0Flags: u64 {
        /// Enables protected mode.
        const PROTECTED_MODE_ENABLE = 1 << 0;
        /// Enables monitoring of the coprocessor, typical for x87 instructions.
        ///
        /// Controls together with the `TASK_SWITCHED` flag whether a `wait` or `fwait`
        /// instruction should cause a device-not-available exception.
        const MONITOR_COPROCESSOR = 1 << 1;
        /// Force all x87 and MMX instructions to cause an exception.
        const EMULATE_COPROCESSOR = 1 << 2;
        /// Automatically set to 1 on _hardware_ task switch.
        ///
        /// This flags allows lazily saving x87/MMX/SSE instructions on hardware context switches.
        const TASK_SWITCHED = 1 << 3;
        /// Enables the native error reporting mechanism for x87 FPU errors.
        const NUMERIC_ERROR = 1 << 5;
        /// Controls whether supervisor-level writes to read-only pages are inhibited.
        ///
        /// When set, it is not possible to write to read-only pages from ring 0.
        const WRITE_PROTECT = 1 << 16;
        /// Enables automatic alignment checking.
        const ALIGNMENT_MASK = 1 << 18;
        /// Ignored. Used to control write-back/write-through cache strategy on older CPUs.
        const NOT_WRITE_THROUGH = 1 << 29;
        /// Disables internal caches (only for some cases).
        const CACHE_DISABLE = 1 << 30;
        /// Enables page translation.
        const PAGING = 1 << 31;
    }
}

/// Contains the physical address of the level 4 page table.
pub struct Cr3;

impl Cr3 {
    /// Read the current P4 table address from the CR3 register.
    pub fn read() -> (PhysFrame, Cr3Flags) {
        let value: u64;
        unsafe {
            asm!("mov %cr3, $0" : "=r" (value));
        }
        let flags = Cr3Flags::from_bits_truncate(value);
        let addr = PhysAddr::new(value & 0x_000f_ffff_ffff_f000);
        let frame = PhysFrame::containing_address(addr);
        (frame, flags)
    }

    /// Write a new P4 table address into the CR3 register.
    ///
    /// ## Safety
    /// Changing the level 4 page table is unsafe, because it's possible to violate memory safety by
    /// changing the page mapping.
    pub unsafe fn write(frame: PhysFrame, flags: Cr3Flags) {
        let addr = frame.start_address();
        let value = addr.as_u64() | flags.bits();
        asm!("mov $0, %cr3" :: "r" (value) : "memory")
    }
}

bitflags! {
    /// Controls cache settings for the level 4 page table.
    pub struct Cr3Flags: u64 {
        /// Use a writethrough cache policy for the P4 table (else a writeback policy is used).
        const PAGE_LEVEL_WRITETHROUGH = 1 << 3;
        /// Disable caching for the P4 table.
        const PAGE_LEVEL_CACHE_DISABLE = 1 << 4;
    }
}
<|endoftext|>


<commit_before>use super::*;
use super::super::packets;
use crc;
use std::collections;
use std::net;
use mio;
use mio::udp;

const SOCKET_TOKEN: mio::Token = mio::Token(0);

//The actual server consists of this, the event loop, and the socket.
//The struct is later in this file.
pub struct MioHandler<'a> {
    outgoing_packets: collections::VecDeque<packets::Packet>,
    connections: collections::HashMap<(net::IpAddr, u16), Connection>,
    next_connection_id: u32, //TODO: a counter is not sufficient for long-running programs.

    socket: &'a udp::UdpSocket,
    incoming_packet_buffer: [u8; 1000],
    outgoing_packet_buffer: [u8; 1000],
}

impl<'a> MioHandler<'a> {
    pub fn new(socket: &'a udp::UdpSocket)->MioHandler<'a> {
        MioHandler {
            connections: collections::HashMap::new(),
            outgoing_packets: collections::VecDeque::with_capacity(100),
            next_connection_id: 0,
            socket: socket,
            incoming_packet_buffer: [0u8; 1000],
            outgoing_packet_buffer: [0u8; 1000],
        }
    }

    pub fn incoming_packet(&mut self, packet: &packets::Packet, ip: net::IpAddr) {
        //no-op for now.
    }

    fn get_outgoing_packet_count(&self)->usize {
        self.outgoing_packets.len()
    }

    fn pop_outgoing_packet(&mut self)->Option<packets::Packet> {
        self.outgoing_packets.pop_front()
    }
}

impl<'a> Server for MioHandler<'a> {
    fn send(&mut self, packet: &packets::Packet, ip: net::IpAddr, port: u16) {
    }

    fn make_connection(&mut self, ip: net::IpAddr, port: u16)->Result<u32, String> {
        let id = self.next_connection_id;
        self.next_connection_id += 1;
        let conn = Connection::new(id, ip, port);
        self.connections.insert((ip, port), conn);
        Ok(id)
    }
}

impl<'a> mio::Handler for MioHandler<'a> {
    type Timeout = ();
    type Message = ();

    fn ready(&mut self, event_loop: &mut mio::EventLoop<Self>, token: mio::Token, events: mio::EventSet) {
    }
}
<commit_msg>The mio::Handler implementation reads and forwards packets.<commit_after>use super::*;
use super::super::packets;
use crc;
use std::collections;
use std::net;
use mio;
use mio::udp;

const SOCKET_TOKEN: mio::Token = mio::Token(0);

//The actual server consists of this, the event loop, and the socket.
//The struct is later in this file.
pub struct MioHandler<'a> {
    outgoing_packets: collections::VecDeque<packets::Packet>,
    connections: collections::HashMap<(net::IpAddr, u16), Connection>,
    next_connection_id: u32, //TODO: a counter is not sufficient for long-running programs.

    socket: &'a udp::UdpSocket,
    incoming_packet_buffer: [u8; 1000],
    outgoing_packet_buffer: [u8; 1000],
}

impl<'a> MioHandler<'a> {
    pub fn new(socket: &'a udp::UdpSocket)->MioHandler<'a> {
        MioHandler {
            connections: collections::HashMap::new(),
            outgoing_packets: collections::VecDeque::with_capacity(100),
            next_connection_id: 0,
            socket: socket,
            incoming_packet_buffer: [0u8; 1000],
            outgoing_packet_buffer: [0u8; 1000],
        }
    }

    pub fn incoming_packet(&mut self, packet: &packets::Packet, ip: net::IpAddr) {
        //no-op for now.
    }

    fn get_outgoing_packet_count(&self)->usize {
        self.outgoing_packets.len()
    }

    fn pop_outgoing_packet(&mut self)->Option<packets::Packet> {
        self.outgoing_packets.pop_front()
    }

    fn got_packet(&mut self, size: usize, address: net::SocketAddr) {
        if size == 0 {return};
        let slice = &self.incoming_packet_buffer[0..size];
        //Todo: finish.
    }
}

impl<'a> Server for MioHandler<'a> {
    fn send(&mut self, packet: &packets::Packet, ip: net::IpAddr, port: u16) {
    }

    fn make_connection(&mut self, ip: net::IpAddr, port: u16)->Result<u32, String> {
        let id = self.next_connection_id;
        self.next_connection_id += 1;
        let conn = Connection::new(id, ip, port);
        self.connections.insert((ip, port), conn);
        Ok(id)
    }
}

impl<'a> mio::Handler for MioHandler<'a> {
    type Timeout = ();
    type Message = ();

    fn ready(&mut self, event_loop: &mut mio::EventLoop<Self>, token: mio::Token, events: mio::EventSet) {
        //We only have one socket, so can avoid the match on the token.
        if events.is_error() {
            //We need to do something sensible here, probably a callback with whatever state we can get.
        }
        if events.is_readable() {
            let result = self.socket.recv_from(&mut self.incoming_packet_buffer);
            if let Ok(Some((size, address))) = result {
                self.got_packet(size, address);
            }
        }
    }
}
<|endoftext|>


<commit_before>use libc::{size_t, c_int, c_uint};

// Bounded package merge algorithm, based on the paper
// "A Fast and Space-Economical Algorithm for Length-Limited Coding
// Jyrki Katajainen, Alistair Moffat, Andrew Turpin".

/// Nodes forming chains.
#[repr(C)]
pub struct Node {
  weight: size_t,     // Total weight (symbol count) of this chain.
  tail: *const Node,  // Previous node(s) of this chain, or 0 if none.
  count: c_int,       // Leaf symbol index, or number of leaves before this chain.
}

#[repr(C)]
pub struct Leaf {
  weight: size_t,     // Total weight (symbol count) of this chain.
  count: c_int,       // Leaf symbol index, or number of leaves before this chain.
}

/// Memory pool for nodes.
#[repr(C)]
pub struct NodePool {
  next: *const Node,   // Pointer to a possibly free node in the pool.
}

/// Initializes a chain node with the given values and marks it as in use.
#[no_mangle]
#[allow(non_snake_case)]
pub extern fn InitNode(weight: size_t, count: c_int, tail: *const Node, node_ptr: *mut Node) {
    let node = unsafe {
        assert!(!node_ptr.is_null());
        &mut *node_ptr
    };

    node.weight = weight;
    node.count = count;
    node.tail = tail;
}

/// Converts result of boundary package-merge to the bitlengths. The result in the
/// last chain of the last list contains the amount of active leaves in each list.
/// chain: Chain to extract the bit length from (last chain from last list).
#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ExtractBitLengths(chain: *const Node, leaves: *const Leaf, bitlengths: *mut c_uint) {
    let mut counts = [0; 16];
    let mut end = 16;
    let mut ptr = 15;
    let mut value = 1;

    let mut node_ptr = chain;
    while !node_ptr.is_null() {
        let node = unsafe {
           &*node_ptr
        };

        end -= 1;
        counts[end] = node.count;

        node_ptr = node.tail;
    }

    let mut val = counts[15];
    while ptr >= end {
        while val > counts[ptr - 1] {
            unsafe {
                let leaf = &*leaves.offset((val - 1) as isize);
                *bitlengths.offset(leaf.count as isize) = value;
            }
            val -= 1;
        }
        ptr -= 1;
        value += 1;
    }
}
<commit_msg>Add some test cases<commit_after>use libc::{size_t, c_int, c_uint};

// Bounded package merge algorithm, based on the paper
// "A Fast and Space-Economical Algorithm for Length-Limited Coding
// Jyrki Katajainen, Alistair Moffat, Andrew Turpin".

/// Nodes forming chains.
#[repr(C)]
pub struct Node {
  weight: size_t,     // Total weight (symbol count) of this chain.
  tail: *const Node,  // Previous node(s) of this chain, or 0 if none.
  count: c_int,       // Leaf symbol index, or number of leaves before this chain.
}

#[repr(C)]
pub struct Leaf {
  weight: size_t,     // Total weight (symbol count) of this chain.
  count: c_int,       // Leaf symbol index, or number of leaves before this chain.
}

/// Memory pool for nodes.
#[repr(C)]
pub struct NodePool {
  next: *const Node,   // Pointer to a possibly free node in the pool.
}

/// Initializes a chain node with the given values and marks it as in use.
#[no_mangle]
#[allow(non_snake_case)]
pub extern fn InitNode(weight: size_t, count: c_int, tail: *const Node, node_ptr: *mut Node) {
    let node = unsafe {
        assert!(!node_ptr.is_null());
        &mut *node_ptr
    };

    node.weight = weight;
    node.count = count;
    node.tail = tail;
}

/// Converts result of boundary package-merge to the bitlengths. The result in the
/// last chain of the last list contains the amount of active leaves in each list.
/// chain: Chain to extract the bit length from (last chain from last list).
#[no_mangle]
#[allow(non_snake_case)]
pub extern fn ExtractBitLengths(chain: *const Node, leaves: *const Leaf, bitlengths: *mut c_uint) {
    let mut counts = [0; 16];
    let mut end = 16;
    let mut ptr = 15;
    let mut value = 1;

    let mut node_ptr = chain;
    while !node_ptr.is_null() {
        let node = unsafe {
           &*node_ptr
        };

        end -= 1;
        counts[end] = node.count;

        node_ptr = node.tail;
    }

    let mut val = counts[15];
    while ptr >= end {
        while val > counts[ptr - 1] {
            unsafe {
                let leaf = &*leaves.offset((val - 1) as isize);
                *bitlengths.offset(leaf.count as isize) = value;
            }
            val -= 1;
        }
        ptr -= 1;
        value += 1;
    }
}

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

    #[test]
    fn test_from_paper_3() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 3);
        let answer = vec![3, 3, 3, 3, 2, 2];
        assert_eq!(output, answer);
    }

    #[test]
    fn test_from_paper_4() {
        let input = [1, 1, 5, 7, 10, 14];
        let output = length_limited_code_lengths(&input, 4);
        let answer = vec![4, 4, 3, 2, 2, 2];
        assert_eq!(output, answer);
    }

    // #[test]
    // fn one_test() {
    //     let input = [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    //     let output = length_limited_code_lengths(&input, 7);
    //     let answer = vec![1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    //     assert_eq!(output, answer);
    // }
}

// maxbits: 7
// frequencies: [252, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
// bitlengths: [1, 0, 6, 4, 3, 3, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
// maxbits: 7
// frequencies: [10, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, ]
// bitlengths: [3, 0, 6, 4, 3, 4, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 26, 0, ]
// bitlengths: [4, 0, 6, 4, 3, 3, 4, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1, 26, 0, ]
// bitlengths: [4, 0, 6, 4, 3, 4, 4, 4, 5, 0, 0, 0, 0, 0, 0, 0, 6, 1, 0, ]
// maxbits: 7
// frequencies: [19, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, ]
// bitlengths: [2, 0, 6, 3, 3, 2, 3, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, ]
// maxbits: 7
// frequencies: [8, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 3, ]
// bitlengths: [3, 0, 5, 3, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 4, 0, 4, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 10, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, ]
// bitlengths: [4, 0, 6, 3, 2, 2, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 5, 4, ]
// maxbits: 7
// frequencies: [4, 0, 1, 6, 9, 4, 6, 3, 2, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, ]
// bitlengths: [3, 0, 6, 3, 2, 3, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 6, 4, 4, ]
// maxbits: 15
// frequencies: [0, 0, 0, 0, 0, 0, 18, 0, 6, 0, 12, 2, 14, 9, 27, 15, 23, 15, 17, 8, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
// bitlengths: [0, 0, 0, 0, 0, 0, 3, 0, 5, 0, 4, 6, 4, 4, 3, 4, 3, 3, 3, 4, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]
<|endoftext|>


<commit_before>use std::os::getenv;
use std::vec::append_one;
struct Request {
    path: ~str,
    querystring: ~str
}

impl Request {
    fn populate() -> Request {
        Request{
            path: getenv("PATH_INFO").unwrap_or(~""),
            querystring: getenv("QUERY_STRING").unwrap_or(~"")
        }
    }
}

struct Route {
    path: ~str,
    handler: ~fn(&Request)
}

struct RouteList{
    routes: ~[Route],
}

impl RouteList{
    fn new() -> RouteList{
        RouteList{routes: ~[]}
    }
    fn add(&mut self, r: Route){
        self.routes.push(r);
    }
    fn execute(&self, req: &Request) {
        for route in self.routes.iter(){
            if(route.path == req.path){
                (route.handler)(req);
            }
        }
    }

}

fn index(r: &Request){
    println("yay index");
}

fn foo(r: &Request){
    println("yay foo");
}

fn main() {
    print("content-type: text/plain\r\n\r\n");

    let req=Request::populate();
    let mut routes=RouteList::new();
    routes.add(Route{path: ~"", handler: index});
    routes.add(Route{path: ~"/foo", handler: foo});
    routes.execute(&req);
    println("hello from rust!");
    println!("path: {:s}", req.path);
    println!("querystring: {:s}", req.querystring);
    println("done!");
}<commit_msg>OH MY GOD RUST HAS MUTABLE STRINGS!<commit_after>use std::os::getenv;
use std::vec::append_one;
struct Request {
    path: ~str,
    querystring: ~str
}

impl Request {
    fn populate() -> Request {
        Request{
            path: getenv("PATH_INFO").unwrap_or(~""),
            querystring: getenv("QUERY_STRING").unwrap_or(~"")
        }
    }
}

struct Response{
    contenttype: ~str,
    body: ~str
}

impl Response{
    fn new() -> Response{
        Response{contenttype: ~"text/plain", body: ~""}
    }
}

struct Route {
    path: ~str,
    handler: ~fn(&Request, &mut Response)
}

struct RouteList{
    routes: ~[Route],
}

impl RouteList{
    fn new() -> RouteList{
        RouteList{routes: ~[]}
    }
    fn add(&mut self, r: Route){
        self.routes.push(r);
    }
    fn execute(&self, req: &Request, res: &mut Response) {
        for route in self.routes.iter(){
            if(route.path == req.path){
                (route.handler)(req, res);
            }
        }
    }

}

fn index(r: &Request,res: &mut Response){
    res.body.push_str("yay index");
}

fn foo(r: &Request, res: &mut Response){
    res.body.push_str("yay foo");
}

fn main() {
    let req=Request::populate();
    let mut res=Response::new();
    let mut routes=RouteList::new();
    routes.add(Route{path: ~"", handler: index});
    routes.add(Route{path: ~"/foo", handler: foo});
    routes.execute(&req, &mut res);
    println(res.contenttype);
    println("");
    println(res.body);
    println("hello from rust!");
    println!("path: {:s}", req.path);
    println!("querystring: {:s}", req.querystring);
    println("done!");
}<|endoftext|>


<commit_before>//! A "compatibility layer" for spanning XP and Windows 7
//!
//! The standard library currently binds many functions that are not available
//! on Windows XP, but we would also like to support building executables that
//! run on XP. To do this we specify all non-XP APIs as having a fallback
//! implementation to do something reasonable.
//!
//! This dynamic runtime detection of whether a function is available is
//! implemented with `GetModuleHandle` and `GetProcAddress` paired with a
//! static-per-function which caches the result of the first check. In this
//! manner we pay a semi-large one-time cost up front for detecting whether a
//! function is available but afterwards it's just a load and a jump.

use crate::ffi::CString;
use crate::sys::c;

pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
    let mut module: Vec<u16> = module.encode_utf16().collect();
    module.push(0);
    let symbol = CString::new(symbol).unwrap();
    unsafe {
        let handle = c::GetModuleHandleW(module.as_ptr());
        match c::GetProcAddress(handle, symbol.as_ptr()) as usize {
            0 => None,
            n => Some(n),
        }
    }
}

macro_rules! compat_fn {
    ($module:literal: $(
        $(#[$meta:meta])*
        pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty $body:block
    )*) => ($(
        $(#[$meta])*
        pub mod $symbol {
            use super::*;
            use crate::sync::atomic::{AtomicUsize, Ordering};
            use crate::mem;

            static PTR: AtomicUsize = AtomicUsize::new(0);

            #[allow(unused_variables)]
            unsafe extern "system" fn fallback($($argname: $argtype),*) -> $rettype $body

            #[cold]
            fn load() -> usize {
                // There is no locking here. It's okay if this is executed by multiple threads in
                // parallel. `lookup` will result in the same value, and it's okay if they overwrite
                // eachothers result as long as they do so atomically. We don't need any guarantees
                // about memory ordering, as this involves just a single atomic variable which is
                // not used to protect or order anything else.
                let addr = crate::sys::compat::lookup($module, stringify!($symbol))
                    .unwrap_or(fallback as usize);
                PTR.store(addr, Ordering::Relaxed);
                addr
            }

            fn addr() -> usize {
                match PTR.load(Ordering::Relaxed) {
                    0 => load(),
                    addr => addr,
                }
            }

            #[allow(dead_code)]
            pub fn is_available() -> bool {
                addr() != fallback as usize
            }

            pub unsafe fn call($($argname: $argtype),*) -> $rettype {
                type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
                mem::transmute::<usize, F>(addr())($($argname),*)
            }
        }

        pub use $symbol::call as $symbol;
    )*)
}
<commit_msg>Work around potential merging/duplication issues in sys/windows/compat.<commit_after>//! A "compatibility layer" for spanning XP and Windows 7
//!
//! The standard library currently binds many functions that are not available
//! on Windows XP, but we would also like to support building executables that
//! run on XP. To do this we specify all non-XP APIs as having a fallback
//! implementation to do something reasonable.
//!
//! This dynamic runtime detection of whether a function is available is
//! implemented with `GetModuleHandle` and `GetProcAddress` paired with a
//! static-per-function which caches the result of the first check. In this
//! manner we pay a semi-large one-time cost up front for detecting whether a
//! function is available but afterwards it's just a load and a jump.

use crate::ffi::CString;
use crate::sys::c;

pub fn lookup(module: &str, symbol: &str) -> Option<usize> {
    let mut module: Vec<u16> = module.encode_utf16().collect();
    module.push(0);
    let symbol = CString::new(symbol).unwrap();
    unsafe {
        let handle = c::GetModuleHandleW(module.as_ptr());
        match c::GetProcAddress(handle, symbol.as_ptr()) as usize {
            0 => None,
            n => Some(n),
        }
    }
}

macro_rules! compat_fn {
    ($module:literal: $(
        $(#[$meta:meta])*
        pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty $body:block
    )*) => ($(
        $(#[$meta])*
        pub mod $symbol {
            use super::*;
            use crate::sync::atomic::{AtomicUsize, Ordering};
            use crate::mem;

            type F = unsafe extern "system" fn($($argtype),*) -> $rettype;

            static PTR: AtomicUsize = AtomicUsize::new(0);

            #[allow(unused_variables)]
            unsafe extern "system" fn fallback($($argname: $argtype),*) -> $rettype $body

            /// This address is stored in `PTR` to incidate an unavailable API.
            ///
            /// This way, call() will end up calling fallback() if it is unavailable.
            ///
            /// This is a `static` to avoid rustc duplicating `fn fallback()`
            /// into both load() and is_available(), which would break
            /// is_available()'s comparison. By using the same static variable
            /// in both places, they'll refer to the same (copy of the)
            /// function.
            ///
            /// LLVM merging the address of fallback with other functions
            /// (because of unnamed_addr) is fine, since it's only compared to
            /// an address from GetProcAddress from an external dll.
            static FALLBACK: F = fallback;

            #[cold]
            fn load() -> usize {
                // There is no locking here. It's okay if this is executed by multiple threads in
                // parallel. `lookup` will result in the same value, and it's okay if they overwrite
                // eachothers result as long as they do so atomically. We don't need any guarantees
                // about memory ordering, as this involves just a single atomic variable which is
                // not used to protect or order anything else.
                let addr = crate::sys::compat::lookup($module, stringify!($symbol))
                    .unwrap_or(FALLBACK as usize);
                PTR.store(addr, Ordering::Relaxed);
                addr
            }

            fn addr() -> usize {
                match PTR.load(Ordering::Relaxed) {
                    0 => load(),
                    addr => addr,
                }
            }

            #[allow(dead_code)]
            pub fn is_available() -> bool {
                addr() != FALLBACK as usize
            }

            pub unsafe fn call($($argname: $argtype),*) -> $rettype {
                mem::transmute::<usize, F>(addr())($($argname),*)
            }
        }

        pub use $symbol::call as $symbol;
    )*)
}
<|endoftext|>


<commit_before>use livesplit_core::{Attempt, Run, RunMetadata, Segment, TimeSpan};
use livesplit_core::run::{parser, saver};
use super::{acc, acc_mut, alloc, output_str, output_time_span, output_vec, own, own_drop, str};
use std::io::Cursor;
use std::slice;
use std::path::PathBuf;
use libc::c_char;
use segment::OwnedSegment;
use parse_run_result::OwnedParseRunResult;

pub type OwnedRun = *mut Run;
pub type NullableOwnedRun = *mut Run;

#[no_mangle]
pub unsafe extern "C" fn Run_new() -> OwnedRun {
    alloc(Run::new())
}

#[no_mangle]
pub unsafe extern "C" fn Run_drop(this: OwnedRun) {
    own_drop(this);
}

#[no_mangle]
pub unsafe extern "C" fn Run_parse(
    data: *const u8,
    length: usize,
    path: *const c_char,
    load_files: bool,
) -> OwnedParseRunResult {
    let path = str(path);
    let path = if !path.is_empty() {
        Some(PathBuf::from(path))
    } else {
        None
    };

    alloc(parser::composite::parse(
        Cursor::new(slice::from_raw_parts(data, length)),
        path,
        load_files,
    ))
}

#[no_mangle]
pub unsafe extern "C" fn Run_clone(this: *const Run) -> OwnedRun {
    alloc(acc(this).clone())
}

#[no_mangle]
pub unsafe extern "C" fn Run_push_segment(this: *mut Run, segment: OwnedSegment) {
    acc_mut(this).push_segment(own(segment));
}

#[no_mangle]
pub unsafe extern "C" fn Run_game_name(this: *const Run) -> *const c_char {
    output_str(acc(this).game_name())
}

#[no_mangle]
pub unsafe extern "C" fn Run_set_game_name(this: *mut Run, game: *const c_char) {
    acc_mut(this).set_game_name(str(game));
}

#[no_mangle]
pub unsafe extern "C" fn Run_game_icon(this: *const Run) -> *const c_char {
    output_str(acc(this).game_icon().url())
}

#[no_mangle]
pub unsafe extern "C" fn Run_category_name(this: *const Run) -> *const c_char {
    output_str(acc(this).category_name())
}

#[no_mangle]
pub unsafe extern "C" fn Run_set_category_name(this: *mut Run, category: *const c_char) {
    acc_mut(this).set_category_name(str(category));
}

#[no_mangle]
pub unsafe extern "C" fn Run_extended_file_name(
    this: *const Run,
    use_extended_category_name: bool,
) -> *const c_char {
    output_str(acc(this).extended_file_name(use_extended_category_name))
}

#[no_mangle]
pub unsafe extern "C" fn Run_extended_name(
    this: *const Run,
    use_extended_category_name: bool,
) -> *const c_char {
    output_str(acc(this).extended_name(use_extended_category_name))
}

#[no_mangle]
pub unsafe extern "C" fn Run_extended_category_name(
    this: *const Run,
    show_region: bool,
    show_platform: bool,
    show_variables: bool,
) -> *const c_char {
    output_str(acc(this).extended_category_name(
        show_region,
        show_platform,
        show_variables,
    ))
}

#[no_mangle]
pub unsafe extern "C" fn Run_attempt_count(this: *const Run) -> u32 {
    acc(this).attempt_count()
}

#[no_mangle]
pub unsafe extern "C" fn Run_metadata(this: *const Run) -> *const RunMetadata {
    acc(this).metadata()
}

#[no_mangle]
pub unsafe extern "C" fn Run_offset(this: *const Run) -> *const TimeSpan {
    output_time_span(acc(this).offset())
}

#[no_mangle]
pub unsafe extern "C" fn Run_len(this: *const Run) -> usize {
    acc(this).len()
}

#[no_mangle]
pub unsafe extern "C" fn Run_segment(this: *const Run, index: usize) -> *const Segment {
    acc(this).segment(index)
}

#[no_mangle]
pub unsafe extern "C" fn Run_attempt_history_len(this: *const Run) -> usize {
    acc(this).attempt_history().len()
}

#[no_mangle]
pub unsafe extern "C" fn Run_attempt_history_index(
    this: *const Run,
    index: usize,
) -> *const Attempt {
    &acc(this).attempt_history()[index]
}

#[no_mangle]
pub unsafe extern "C" fn Run_save_as_lss(this: *const Run) -> *const c_char {
    output_vec(|o| { saver::livesplit::save(acc(this), o).unwrap(); })
}

#[no_mangle]
pub unsafe extern "C" fn Run_custom_comparisons_len(this: *const Run) -> usize {
    acc(this).custom_comparisons().len()
}

#[no_mangle]
pub unsafe extern "C" fn Run_custom_comparison(this: *const Run, index: usize) -> *const c_char {
    output_str(&acc(this).custom_comparisons()[index])
}

#[no_mangle]
pub unsafe extern "C" fn Run_auto_splitter_settings(this: *const Run) -> *const c_char {
    output_vec(|o| o.extend_from_slice(acc(this).auto_splitter_settings()))
}
<commit_msg>Implement Parsing a File Handle<commit_after>use livesplit_core::{Attempt, Run, RunMetadata, Segment, TimeSpan};
use livesplit_core::run::{parser, saver};
use super::{acc, acc_mut, alloc, output_str, output_time_span, output_vec, own, own_drop, str};
use std::io::{BufReader, Cursor};
use std::slice;
use std::path::PathBuf;
use std::fs::File;
use libc::c_char;
use segment::OwnedSegment;
use parse_run_result::OwnedParseRunResult;

pub type OwnedRun = *mut Run;
pub type NullableOwnedRun = *mut Run;

#[no_mangle]
pub unsafe extern "C" fn Run_new() -> OwnedRun {
    alloc(Run::new())
}

#[no_mangle]
pub unsafe extern "C" fn Run_drop(this: OwnedRun) {
    own_drop(this);
}

#[no_mangle]
pub unsafe extern "C" fn Run_parse(
    data: *const u8,
    length: usize,
    path: *const c_char,
    load_files: bool,
) -> OwnedParseRunResult {
    let path = str(path);
    let path = if !path.is_empty() {
        Some(PathBuf::from(path))
    } else {
        None
    };

    alloc(parser::composite::parse(
        Cursor::new(slice::from_raw_parts(data, length)),
        path,
        load_files,
    ))
}

/// On Unix you pass a file descriptor to this function.
/// On Windows you pass a file handle to this function.
/// The file descriptor / handle does not get closed.
#[no_mangle]
pub unsafe extern "C" fn Run_parse_file_handle(
    handle: i64,
    path: *const c_char,
    load_files: bool,
) -> OwnedParseRunResult {
    let path = str(path);
    let path = if !path.is_empty() {
        Some(PathBuf::from(path))
    } else {
        None
    };

    #[cfg(unix)]
    unsafe fn get_file(fd: i64) -> File {
        use std::os::unix::io::FromRawFd;
        File::from_raw_fd(fd as _)
    }

    #[cfg(windows)]
    unsafe fn get_file(handle: i64) -> File {
        use std::os::windows::io::FromRawHandle;
        File::from_raw_handle(handle as *mut () as _)
    }

    #[cfg(not(any(windows, unix)))]
    unsafe fn get_file(_: i64) -> File {
        panic!("File Descriptor Parsing is not implemented for this platform");
    }

    let file = get_file(handle);

    let run = alloc(parser::composite::parse(
        BufReader::new(&file),
        path,
        load_files,
    ));

    #[cfg(unix)]
    fn release_file(file: File) {
        use std::os::unix::io::IntoRawFd;
        file.into_raw_fd();
    }

    #[cfg(windows)]
    fn release_file(file: File) {
        use std::os::windows::io::IntoRawHandle;
        file.into_raw_handle();
    }

    #[cfg(not(any(windows, unix)))]
    fn release_file(_: File) {}

    release_file(file);

    run
}

#[no_mangle]
pub unsafe extern "C" fn Run_clone(this: *const Run) -> OwnedRun {
    alloc(acc(this).clone())
}

#[no_mangle]
pub unsafe extern "C" fn Run_push_segment(this: *mut Run, segment: OwnedSegment) {
    acc_mut(this).push_segment(own(segment));
}

#[no_mangle]
pub unsafe extern "C" fn Run_game_name(this: *const Run) -> *const c_char {
    output_str(acc(this).game_name())
}

#[no_mangle]
pub unsafe extern "C" fn Run_set_game_name(this: *mut Run, game: *const c_char) {
    acc_mut(this).set_game_name(str(game));
}

#[no_mangle]
pub unsafe extern "C" fn Run_game_icon(this: *const Run) -> *const c_char {
    output_str(acc(this).game_icon().url())
}

#[no_mangle]
pub unsafe extern "C" fn Run_category_name(this: *const Run) -> *const c_char {
    output_str(acc(this).category_name())
}

#[no_mangle]
pub unsafe extern "C" fn Run_set_category_name(this: *mut Run, category: *const c_char) {
    acc_mut(this).set_category_name(str(category));
}

#[no_mangle]
pub unsafe extern "C" fn Run_extended_file_name(
    this: *const Run,
    use_extended_category_name: bool,
) -> *const c_char {
    output_str(acc(this).extended_file_name(use_extended_category_name))
}

#[no_mangle]
pub unsafe extern "C" fn Run_extended_name(
    this: *const Run,
    use_extended_category_name: bool,
) -> *const c_char {
    output_str(acc(this).extended_name(use_extended_category_name))
}

#[no_mangle]
pub unsafe extern "C" fn Run_extended_category_name(
    this: *const Run,
    show_region: bool,
    show_platform: bool,
    show_variables: bool,
) -> *const c_char {
    output_str(acc(this).extended_category_name(
        show_region,
        show_platform,
        show_variables,
    ))
}

#[no_mangle]
pub unsafe extern "C" fn Run_attempt_count(this: *const Run) -> u32 {
    acc(this).attempt_count()
}

#[no_mangle]
pub unsafe extern "C" fn Run_metadata(this: *const Run) -> *const RunMetadata {
    acc(this).metadata()
}

#[no_mangle]
pub unsafe extern "C" fn Run_offset(this: *const Run) -> *const TimeSpan {
    output_time_span(acc(this).offset())
}

#[no_mangle]
pub unsafe extern "C" fn Run_len(this: *const Run) -> usize {
    acc(this).len()
}

#[no_mangle]
pub unsafe extern "C" fn Run_segment(this: *const Run, index: usize) -> *const Segment {
    acc(this).segment(index)
}

#[no_mangle]
pub unsafe extern "C" fn Run_attempt_history_len(this: *const Run) -> usize {
    acc(this).attempt_history().len()
}

#[no_mangle]
pub unsafe extern "C" fn Run_attempt_history_index(
    this: *const Run,
    index: usize,
) -> *const Attempt {
    &acc(this).attempt_history()[index]
}

#[no_mangle]
pub unsafe extern "C" fn Run_save_as_lss(this: *const Run) -> *const c_char {
    output_vec(|o| { saver::livesplit::save(acc(this), o).unwrap(); })
}

#[no_mangle]
pub unsafe extern "C" fn Run_custom_comparisons_len(this: *const Run) -> usize {
    acc(this).custom_comparisons().len()
}

#[no_mangle]
pub unsafe extern "C" fn Run_custom_comparison(this: *const Run, index: usize) -> *const c_char {
    output_str(&acc(this).custom_comparisons()[index])
}

#[no_mangle]
pub unsafe extern "C" fn Run_auto_splitter_settings(this: *const Run) -> *const c_char {
    output_vec(|o| o.extend_from_slice(acc(this).auto_splitter_settings()))
}
<|endoftext|>


<commit_before>use crate::ast::{Enum, Field, Input, Struct};
use crate::valid;
use proc_macro2::TokenStream;
use quote::{format_ident, quote, quote_spanned};
use syn::spanned::Spanned;
use syn::{DeriveInput, Member, PathArguments, Result, Type};

pub fn derive(node: &DeriveInput) -> Result<TokenStream> {
    let input = Input::from_syn(node)?;
    input.validate()?;
    Ok(match input {
        Input::Struct(input) => impl_struct(input),
        Input::Enum(input) => impl_enum(input),
    })
}

fn impl_struct(input: Struct) -> TokenStream {
    let ty = &input.ident;
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    let source_method = input.source_field().map(|source_field| {
        let source = &source_field.member;
        let asref = if type_is_option(source_field.ty) {
            Some(quote_spanned!(source.span()=> .as_ref()?))
        } else {
            None
        };
        let dyn_error = quote_spanned!(source.span()=> self.#source #asref.as_dyn_error());
        quote! {
            fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> {
                use thiserror::private::AsDynError;
                std::option::Option::Some(#dyn_error)
            }
        }
    });

    let backtrace_method = input.backtrace_field().map(|backtrace| {
        let backtrace = &backtrace.member;
        let body = if let Some(source_field) = input.source_field() {
            let source = &source_field.member;
            let source_backtrace = if type_is_option(source_field.ty) {
                quote_spanned! {source.span()=>
                    self.#source.as_ref().and_then(|source| source.as_dyn_error().backtrace())
                }
            } else {
                quote_spanned! {source.span()=>
                    self.#source.as_dyn_error().backtrace()
                }
            };
            quote!({
                use thiserror::private::AsDynError;
                #source_backtrace.unwrap_or(&self.#backtrace)
            })
        } else {
            quote! {
                &self.#backtrace
            }
        };
        quote! {
            fn backtrace(&self) -> std::option::Option<&std::backtrace::Backtrace> {
                std::option::Option::Some(#body)
            }
        }
    });

    let display_impl = input.attrs.display.as_ref().map(|display| {
        let pat = fields_pat(&input.fields);
        quote! {
            impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                    #[allow(unused_variables)]
                    let Self #pat = self;
                    #display
                }
            }
        }
    });

    quote! {
        impl #impl_generics std::error::Error for #ty #ty_generics #where_clause {
            #source_method
            #backtrace_method
        }
        #display_impl
    }
}

fn impl_enum(input: Enum) -> TokenStream {
    let ty = &input.ident;
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    let source_method = if input.has_source() {
        let arms = input.variants.iter().map(|variant| {
            let ident = &variant.ident;
            match variant.source_field() {
                Some(source_field) => {
                    let source = &source_field.member;
                    let asref = if type_is_option(source_field.ty) {
                        Some(quote_spanned!(source.span()=> .as_ref()?))
                    } else {
                        None
                    };
                    let dyn_error = quote_spanned!(source.span()=> source #asref.as_dyn_error());
                    quote! {
                        #ty::#ident {#source: source, ..} => std::option::Option::Some(#dyn_error),
                    }
                }
                None => quote! {
                    #ty::#ident {..} => std::option::Option::None,
                },
            }
        });
        Some(quote! {
            fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> {
                use thiserror::private::AsDynError;
                match self {
                    #(#arms)*
                }
            }
        })
    } else {
        None
    };

    let backtrace_method = if input.has_backtrace() {
        let arms = input.variants.iter().map(|variant| {
            let ident = &variant.ident;
            match (variant.backtrace_field(), variant.source_field()) {
                (Some(backtrace), Some(source_field)) if backtrace.attrs.backtrace.is_none() => {
                    let backtrace = &backtrace.member;
                    let source = &source_field.member;
                    let source_backtrace = if type_is_option(source_field.ty) {
                        quote_spanned! {source.span()=>
                            source.as_ref().and_then(|source| source.as_dyn_error().backtrace())
                        }
                    } else {
                        quote_spanned! {source.span()=>
                            source.as_dyn_error().backtrace()
                        }
                    };
                    quote! {
                        #ty::#ident {
                            #backtrace: backtrace,
                            #source: source,
                            ..
                        } => std::option::Option::Some({
                            use thiserror::private::AsDynError;
                            #source_backtrace.unwrap_or(backtrace)
                        }),
                    }
                }
                (Some(backtrace), _) => {
                    let backtrace = &backtrace.member;
                    quote! {
                        #ty::#ident {#backtrace: backtrace, ..} => std::option::Option::Some(backtrace),
                    }
                }
                (None, _) => quote! {
                    #ty::#ident {..} => std::option::Option::None,
                },
            }
        });
        Some(quote! {
            fn backtrace(&self) -> std::option::Option<&std::backtrace::Backtrace> {
                match self {
                    #(#arms)*
                }
            }
        })
    } else {
        None
    };

    let display_impl = if input.has_display() {
        let void_deref = if input.variants.is_empty() {
            Some(quote!(*))
        } else {
            None
        };
        let arms = input.variants.iter().map(|variant| {
            let display = variant.attrs.display.as_ref().expect(valid::CHECKED);
            let ident = &variant.ident;
            let pat = fields_pat(&variant.fields);
            quote! {
                #ty::#ident #pat => #display
            }
        });
        Some(quote! {
            impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                    #[allow(unused_variables)]
                    match #void_deref self {
                        #(#arms,)*
                    }
                }
            }
        })
    } else {
        None
    };

    quote! {
        impl #impl_generics std::error::Error for #ty #ty_generics #where_clause {
            #source_method
            #backtrace_method
        }
        #display_impl
    }
}

fn fields_pat(fields: &[Field]) -> TokenStream {
    let mut members = fields.iter().map(|field| &field.member).peekable();
    match members.peek() {
        Some(Member::Named(_)) => quote!({ #(#members),* }),
        Some(Member::Unnamed(_)) => {
            let vars = members.map(|member| match member {
                Member::Unnamed(member) => format_ident!("_{}", member.index),
                Member::Named(_) => unreachable!(),
            });
            quote!((#(#vars),*))
        }
        None => quote!({}),
    }
}

fn type_is_option(ty: &Type) -> bool {
    let path = match ty {
        Type::Path(ty) => &ty.path,
        _ => return false,
    };

    let last = path.segments.last().unwrap();
    if last.ident != "Option" {
        return false;
    }

    match &last.arguments {
        PathArguments::AngleBracketed(bracketed) => bracketed.args.len() == 1,
        _ => false,
    }
}
<commit_msg>Support Option<Backtrace><commit_after>use crate::ast::{Enum, Field, Input, Struct};
use crate::valid;
use proc_macro2::TokenStream;
use quote::{format_ident, quote, quote_spanned};
use syn::spanned::Spanned;
use syn::{DeriveInput, Member, PathArguments, Result, Type};

pub fn derive(node: &DeriveInput) -> Result<TokenStream> {
    let input = Input::from_syn(node)?;
    input.validate()?;
    Ok(match input {
        Input::Struct(input) => impl_struct(input),
        Input::Enum(input) => impl_enum(input),
    })
}

fn impl_struct(input: Struct) -> TokenStream {
    let ty = &input.ident;
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    let source_method = input.source_field().map(|source_field| {
        let source = &source_field.member;
        let asref = if type_is_option(source_field.ty) {
            Some(quote_spanned!(source.span()=> .as_ref()?))
        } else {
            None
        };
        let dyn_error = quote_spanned!(source.span()=> self.#source #asref.as_dyn_error());
        quote! {
            fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> {
                use thiserror::private::AsDynError;
                std::option::Option::Some(#dyn_error)
            }
        }
    });

    let backtrace_method = input.backtrace_field().map(|backtrace_field| {
        let backtrace = &backtrace_field.member;
        let body = if let Some(source_field) = input.source_field() {
            let source = &source_field.member;
            let source_backtrace = if type_is_option(source_field.ty) {
                quote_spanned! {source.span()=>
                    self.#source.as_ref().and_then(|source| source.as_dyn_error().backtrace())
                }
            } else {
                quote_spanned! {source.span()=>
                    self.#source.as_dyn_error().backtrace()
                }
            };
            let combinator = if type_is_option(backtrace_field.ty) {
                quote! {
                    #source_backtrace.or(self.#backtrace.as_ref())
                }
            } else {
                quote! {
                    std::option::Option::Some(#source_backtrace.unwrap_or(&self.#backtrace))
                }
            };
            quote! {
                use thiserror::private::AsDynError;
                #combinator
            }
        } else if type_is_option(backtrace_field.ty) {
            quote! {
                self.#backtrace.as_ref()
            }
        } else {
            quote! {
                std::option::Option::Some(&self.#backtrace)
            }
        };
        quote! {
            fn backtrace(&self) -> std::option::Option<&std::backtrace::Backtrace> {
                #body
            }
        }
    });

    let display_impl = input.attrs.display.as_ref().map(|display| {
        let pat = fields_pat(&input.fields);
        quote! {
            impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                    #[allow(unused_variables)]
                    let Self #pat = self;
                    #display
                }
            }
        }
    });

    quote! {
        impl #impl_generics std::error::Error for #ty #ty_generics #where_clause {
            #source_method
            #backtrace_method
        }
        #display_impl
    }
}

fn impl_enum(input: Enum) -> TokenStream {
    let ty = &input.ident;
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();

    let source_method = if input.has_source() {
        let arms = input.variants.iter().map(|variant| {
            let ident = &variant.ident;
            match variant.source_field() {
                Some(source_field) => {
                    let source = &source_field.member;
                    let asref = if type_is_option(source_field.ty) {
                        Some(quote_spanned!(source.span()=> .as_ref()?))
                    } else {
                        None
                    };
                    let dyn_error = quote_spanned!(source.span()=> source #asref.as_dyn_error());
                    quote! {
                        #ty::#ident {#source: source, ..} => std::option::Option::Some(#dyn_error),
                    }
                }
                None => quote! {
                    #ty::#ident {..} => std::option::Option::None,
                },
            }
        });
        Some(quote! {
            fn source(&self) -> std::option::Option<&(dyn std::error::Error + 'static)> {
                use thiserror::private::AsDynError;
                match self {
                    #(#arms)*
                }
            }
        })
    } else {
        None
    };

    let backtrace_method = if input.has_backtrace() {
        let arms = input.variants.iter().map(|variant| {
            let ident = &variant.ident;
            match (variant.backtrace_field(), variant.source_field()) {
                (Some(backtrace_field), Some(source_field))
                    if backtrace_field.attrs.backtrace.is_none() =>
                {
                    let backtrace = &backtrace_field.member;
                    let source = &source_field.member;
                    let source_backtrace = if type_is_option(source_field.ty) {
                        quote_spanned! {source.span()=>
                            source.as_ref().and_then(|source| source.as_dyn_error().backtrace())
                        }
                    } else {
                        quote_spanned! {source.span()=>
                            source.as_dyn_error().backtrace()
                        }
                    };
                    let combinator = if type_is_option(backtrace_field.ty) {
                        quote! {
                            #source_backtrace.or(backtrace.as_ref())
                        }
                    } else {
                        quote! {
                            std::option::Option::Some(#source_backtrace.unwrap_or(backtrace))
                        }
                    };
                    quote! {
                        #ty::#ident {
                            #backtrace: backtrace,
                            #source: source,
                            ..
                        } => {
                            use thiserror::private::AsDynError;
                            #combinator
                        }
                    }
                }
                (Some(backtrace_field), _) => {
                    let backtrace = &backtrace_field.member;
                    let body = if type_is_option(backtrace_field.ty) {
                        quote!(backtrace.as_ref())
                    } else {
                        quote!(std::option::Option::Some(backtrace))
                    };
                    quote! {
                        #ty::#ident {#backtrace: backtrace, ..} => #body,
                    }
                }
                (None, _) => quote! {
                    #ty::#ident {..} => std::option::Option::None,
                },
            }
        });
        Some(quote! {
            fn backtrace(&self) -> std::option::Option<&std::backtrace::Backtrace> {
                match self {
                    #(#arms)*
                }
            }
        })
    } else {
        None
    };

    let display_impl = if input.has_display() {
        let void_deref = if input.variants.is_empty() {
            Some(quote!(*))
        } else {
            None
        };
        let arms = input.variants.iter().map(|variant| {
            let display = variant.attrs.display.as_ref().expect(valid::CHECKED);
            let ident = &variant.ident;
            let pat = fields_pat(&variant.fields);
            quote! {
                #ty::#ident #pat => #display
            }
        });
        Some(quote! {
            impl #impl_generics std::fmt::Display for #ty #ty_generics #where_clause {
                fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
                    #[allow(unused_variables)]
                    match #void_deref self {
                        #(#arms,)*
                    }
                }
            }
        })
    } else {
        None
    };

    quote! {
        impl #impl_generics std::error::Error for #ty #ty_generics #where_clause {
            #source_method
            #backtrace_method
        }
        #display_impl
    }
}

fn fields_pat(fields: &[Field]) -> TokenStream {
    let mut members = fields.iter().map(|field| &field.member).peekable();
    match members.peek() {
        Some(Member::Named(_)) => quote!({ #(#members),* }),
        Some(Member::Unnamed(_)) => {
            let vars = members.map(|member| match member {
                Member::Unnamed(member) => format_ident!("_{}", member.index),
                Member::Named(_) => unreachable!(),
            });
            quote!((#(#vars),*))
        }
        None => quote!({}),
    }
}

fn type_is_option(ty: &Type) -> bool {
    let path = match ty {
        Type::Path(ty) => &ty.path,
        _ => return false,
    };

    let last = path.segments.last().unwrap();
    if last.ident != "Option" {
        return false;
    }

    match &last.arguments {
        PathArguments::AngleBracketed(bracketed) => bracketed.args.len() == 1,
        _ => false,
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::chained_bft::liveness::proposer_election::{next, ProposerElection};
use consensus_types::{
    block::Block,
    common::{Author, Round},
};
use libra_types::block_metadata::{new_block_event_key, NewBlockEvent};
use libradb::LibraDBTrait;
use serde::export::PhantomData;
use std::{
    cmp::Ordering,
    collections::HashSet,
    sync::{Arc, Mutex},
};

/// Interface to query committed BlockMetadata.
pub trait MetadataBackend: Send + Sync {
    /// Return a contiguous BlockMetadata window in which last one is at target_round or
    /// latest committed, return all previous one if not enough.
    fn get_block_metadata(&self, target_round: Round) -> Vec<NewBlockEvent>;
}

pub struct LibraDBBackend {
    window_size: usize,
    libra_db: Arc<dyn LibraDBTrait>,
    window: Mutex<Vec<(u64, NewBlockEvent)>>,
}

impl LibraDBBackend {
    pub fn new(window_size: usize, libra_db: Arc<dyn LibraDBTrait>) -> Self {
        Self {
            window_size,
            libra_db,
            window: Mutex::new(vec![]),
        }
    }

    fn refresh_window(&self, target_round: Round) {
        // assumes target round is not too far from latest commit
        let buffer = 10;
        let events = self
            .libra_db
            .get_events(
                &new_block_event_key(),
                u64::max_value(),
                self.window_size as u64 + buffer,
            )
            .unwrap();
        let events: Vec<_> = events
            .into_iter()
            .map(|(v, e)| (v, lcs::from_bytes::<NewBlockEvent>(e.event_data()).unwrap()))
            .filter(|(_, e)| e.round() <= target_round)
            .take(self.window_size)
            .collect();
        *self.window.lock().unwrap() = events;
    }
}

impl MetadataBackend for LibraDBBackend {
    // assume the target_round only increases
    fn get_block_metadata(&self, target_round: Round) -> Vec<NewBlockEvent> {
        let (known_version, known_round) = self
            .window
            .lock()
            .unwrap()
            .first()
            .map(|(v, e)| (*v, e.round()))
            .unwrap_or((0, 0));
        if !(known_round == target_round
            || known_version == self.libra_db.get_latest_version().unwrap())
        {
            self.refresh_window(target_round);
        }
        self.window
            .lock()
            .unwrap()
            .clone()
            .into_iter()
            .map(|(_, e)| e)
            .collect()
    }
}

/// Interface to calculate weights for proposers based on history.
pub trait ReputationHeuristic: Send + Sync {
    /// Return the weights of all candidates based on the history.
    fn get_weights(&self, candidates: &[Author], history: &[NewBlockEvent]) -> Vec<u64>;
}

/// If candidate appear in the history, it's assigned active_weight otherwise inactive weight.
pub struct ActiveInactiveHeuristic {
    active_weight: u64,
    inactive_weight: u64,
}

impl ActiveInactiveHeuristic {
    pub fn new(active_weight: u64, inactive_weight: u64) -> Self {
        Self {
            active_weight,
            inactive_weight,
        }
    }
}

impl ReputationHeuristic for ActiveInactiveHeuristic {
    fn get_weights(&self, candidates: &[Author], history: &[NewBlockEvent]) -> Vec<u64> {
        let set = history.iter().fold(HashSet::new(), |mut set, meta| {
            set.insert(meta.proposer());
            set.extend(meta.votes().into_iter());
            set
        });
        candidates
            .iter()
            .map(|author| {
                if set.contains(&author) {
                    self.active_weight
                } else {
                    self.inactive_weight
                }
            })
            .collect()
    }
}

/// Committed history based proposer election implementation that could help bias towards
/// successful leaders to help improve performance.
pub struct LeaderReputation<T> {
    proposers: Vec<Author>,
    backend: Box<dyn MetadataBackend>,
    heuristic: Box<dyn ReputationHeuristic>,
    phantom: PhantomData<T>,
}

impl<T> LeaderReputation<T> {
    pub fn new(
        proposers: Vec<Author>,
        backend: Box<dyn MetadataBackend>,
        heuristic: Box<dyn ReputationHeuristic>,
    ) -> Self {
        Self {
            proposers,
            backend,
            heuristic,
            phantom: PhantomData,
        }
    }
}

impl<T> ProposerElection<T> for LeaderReputation<T> {
    fn is_valid_proposer(&self, author: Author, round: Round) -> Option<Author> {
        if self.get_valid_proposers(round).contains(&author) {
            Some(author)
        } else {
            None
        }
    }

    fn get_valid_proposers(&self, round: Round) -> Vec<Author> {
        // TODO: configure the round gap
        let target_round = if round >= 4 { round - 4 } else { 0 };
        let sliding_window = self.backend.get_block_metadata(target_round);
        let mut weights = self.heuristic.get_weights(&self.proposers, &sliding_window);
        assert_eq!(weights.len(), self.proposers.len());
        let mut total_weight = 0;
        for w in &mut weights {
            total_weight += *w;
            *w = total_weight;
        }
        let mut state = round.to_le_bytes().to_vec();
        let chosen_weight = next(&mut state) % total_weight;
        let chosen_index = weights
            .binary_search_by(|w| {
                if *w <= chosen_weight {
                    Ordering::Less
                } else {
                    Ordering::Greater
                }
            })
            .unwrap_err();
        vec![self.proposers[chosen_index]]
    }

    fn process_proposal(&mut self, proposal: Block<T>) -> Option<Block<T>> {
        let author = proposal.author()?;
        if self.get_valid_proposers(proposal.round()).contains(&author) {
            Some(proposal)
        } else {
            None
        }
    }

    fn take_backup_proposal(&mut self, _round: Round) -> Option<Block<T>> {
        None
    }
}
<commit_msg>[leader reputation] graceful error handling<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::chained_bft::liveness::proposer_election::{next, ProposerElection};
use consensus_types::{
    block::Block,
    common::{Author, Round},
};
use libra_logger::prelude::*;
use libra_types::block_metadata::{new_block_event_key, NewBlockEvent};
use libradb::LibraDBTrait;
use serde::export::PhantomData;
use std::{
    cmp::Ordering,
    collections::HashSet,
    sync::{Arc, Mutex},
};

/// Interface to query committed BlockMetadata.
pub trait MetadataBackend: Send + Sync {
    /// Return a contiguous BlockMetadata window in which last one is at target_round or
    /// latest committed, return all previous one if not enough.
    fn get_block_metadata(&self, target_round: Round) -> Vec<NewBlockEvent>;
}

pub struct LibraDBBackend {
    window_size: usize,
    libra_db: Arc<dyn LibraDBTrait>,
    window: Mutex<Vec<(u64, NewBlockEvent)>>,
}

impl LibraDBBackend {
    pub fn new(window_size: usize, libra_db: Arc<dyn LibraDBTrait>) -> Self {
        Self {
            window_size,
            libra_db,
            window: Mutex::new(vec![]),
        }
    }

    fn refresh_window(&self, target_round: Round) -> anyhow::Result<()> {
        // assumes target round is not too far from latest commit
        let buffer = 10;
        let events = self.libra_db.get_events(
            &new_block_event_key(),
            u64::max_value(),
            self.window_size as u64 + buffer,
        )?;
        let mut result = vec![];
        for (v, e) in events {
            let e = lcs::from_bytes::<NewBlockEvent>(e.event_data())?;
            if e.round() <= target_round && result.len() < self.window_size {
                result.push((v, e));
            }
        }
        *self.window.lock().unwrap() = result;
        Ok(())
    }
}

impl MetadataBackend for LibraDBBackend {
    // assume the target_round only increases
    fn get_block_metadata(&self, target_round: Round) -> Vec<NewBlockEvent> {
        let (known_version, known_round) = self
            .window
            .lock()
            .unwrap()
            .first()
            .map(|(v, e)| (*v, e.round()))
            .unwrap_or((0, 0));
        if !(known_round == target_round
            || known_version == self.libra_db.get_latest_version().unwrap_or(0))
        {
            if let Err(e) = self.refresh_window(target_round) {
                error!("[leader reputation] Fail to refresh window: {:?}", e);
                return vec![];
            }
        }
        self.window
            .lock()
            .unwrap()
            .clone()
            .into_iter()
            .map(|(_, e)| e)
            .collect()
    }
}

/// Interface to calculate weights for proposers based on history.
pub trait ReputationHeuristic: Send + Sync {
    /// Return the weights of all candidates based on the history.
    fn get_weights(&self, candidates: &[Author], history: &[NewBlockEvent]) -> Vec<u64>;
}

/// If candidate appear in the history, it's assigned active_weight otherwise inactive weight.
pub struct ActiveInactiveHeuristic {
    active_weight: u64,
    inactive_weight: u64,
}

impl ActiveInactiveHeuristic {
    pub fn new(active_weight: u64, inactive_weight: u64) -> Self {
        Self {
            active_weight,
            inactive_weight,
        }
    }
}

impl ReputationHeuristic for ActiveInactiveHeuristic {
    fn get_weights(&self, candidates: &[Author], history: &[NewBlockEvent]) -> Vec<u64> {
        let set = history.iter().fold(HashSet::new(), |mut set, meta| {
            set.insert(meta.proposer());
            set.extend(meta.votes().into_iter());
            set
        });
        candidates
            .iter()
            .map(|author| {
                if set.contains(&author) {
                    self.active_weight
                } else {
                    self.inactive_weight
                }
            })
            .collect()
    }
}

/// Committed history based proposer election implementation that could help bias towards
/// successful leaders to help improve performance.
pub struct LeaderReputation<T> {
    proposers: Vec<Author>,
    backend: Box<dyn MetadataBackend>,
    heuristic: Box<dyn ReputationHeuristic>,
    phantom: PhantomData<T>,
}

impl<T> LeaderReputation<T> {
    pub fn new(
        proposers: Vec<Author>,
        backend: Box<dyn MetadataBackend>,
        heuristic: Box<dyn ReputationHeuristic>,
    ) -> Self {
        Self {
            proposers,
            backend,
            heuristic,
            phantom: PhantomData,
        }
    }
}

impl<T> ProposerElection<T> for LeaderReputation<T> {
    fn is_valid_proposer(&self, author: Author, round: Round) -> Option<Author> {
        if self.get_valid_proposers(round).contains(&author) {
            Some(author)
        } else {
            None
        }
    }

    fn get_valid_proposers(&self, round: Round) -> Vec<Author> {
        // TODO: configure the round gap
        let target_round = if round >= 4 { round - 4 } else { 0 };
        let sliding_window = self.backend.get_block_metadata(target_round);
        let mut weights = self.heuristic.get_weights(&self.proposers, &sliding_window);
        assert_eq!(weights.len(), self.proposers.len());
        let mut total_weight = 0;
        for w in &mut weights {
            total_weight += *w;
            *w = total_weight;
        }
        let mut state = round.to_le_bytes().to_vec();
        let chosen_weight = next(&mut state) % total_weight;
        let chosen_index = weights
            .binary_search_by(|w| {
                if *w <= chosen_weight {
                    Ordering::Less
                } else {
                    Ordering::Greater
                }
            })
            .unwrap_err();
        vec![self.proposers[chosen_index]]
    }

    fn process_proposal(&mut self, proposal: Block<T>) -> Option<Block<T>> {
        let author = proposal.author()?;
        if self.get_valid_proposers(proposal.round()).contains(&author) {
            Some(proposal)
        } else {
            None
        }
    }

    fn take_backup_proposal(&mut self, _round: Round) -> Option<Block<T>> {
        None
    }
}
<|endoftext|>


<commit_before>fn collatz(num: u32) -> u32 {
    if num == 1 {
        return num;
    }

    if num % 2 == 0 {
        num / 2
    } else {
        (num * 3) + 1
    }
}

fn main() {
    let mut max_terms: u32 = 0;
    let mut max_terms_number: u32 = 0;

    for i in (2..1_000_000).rev() {
        let mut current_terms: u32 = 0;
        let mut result: u32 = i;
        while result != 1 {
            result = collatz(result);
            current_terms += 1;
            if current_terms > max_terms {
                max_terms = current_terms;
                max_terms_number = i;
            }
        }
        // println!("collatz({}) -> {}", i, current_terms);
    }

    println!("Result: {}", max_terms_number);
}
<commit_msg>small fix for problem 14 rust<commit_after>fn collatz(num: u32) -> u32 {
    if num == 1 {
        return num;
    }

    if num % 2 == 0 {
        num / 2
    } else {
        (num * 3) + 1
    }
}

fn main() {
    let mut max_terms: u32 = 0;
    let mut max_terms_number: u32 = 0;

    for i in 2..1_000_001 {
        let mut current_terms: u32 = 0;
        let mut result: u32 = i;
        while result != 1 {
            result = collatz(result);
            current_terms += 1;
            if current_terms > max_terms {
                max_terms = current_terms;
                max_terms_number = i;
            }
        }
        // println!("collatz({}) -> {}", i, current_terms);
    }

    println!("Result: {}", max_terms_number);
}
<|endoftext|>


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

use rocksdb::{DB, Options};
use util::DBPath;

#[test]
fn test_set_num_levels() {
    let n = DBPath::new("_rust_rocksdb_test_set_num_levels");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_num_levels(2);
        let _db = DB::open(&opts, n).unwrap();
    }
}
<commit_msg>Test fix: Ensuring db cleanup doesn't happen until after test completion...<commit_after>// Copyright 2014 Tyler Neely
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
extern crate rocksdb;
mod util;

use rocksdb::{DB, Options};
use util::DBPath;

#[test]
fn test_set_num_levels() {
    let n = DBPath::new("_rust_rocksdb_test_set_num_levels");
    {
        let mut opts = Options::default();
        opts.create_if_missing(true);
        opts.set_num_levels(2);
        let _db = DB::open(&opts, &n).unwrap();
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::fs::File;
use std::io::Write;
use ::api_parser::*;

static HEADER: &'static [u8] = b"
#pragma once\n
#include <stdint.h>\n
#ifdef __cplusplus
extern \"C\" {
#endif\n\n";

static FOOTER: &'static [u8] = b"
#ifdef __cplusplus
}
#endif\n";

fn get_type_name(tname: &str, primitve: bool) -> String {
    if primitve {
        if tname == "f32" {
            "float".to_owned()
        } else if tname == "f64" {
            return "double".to_owned()
        } else {
            // here we will have u8/i8,u32/etc
           if tname.starts_with("u") {
                format!("uint{}_t", &tname[1..])
            } else {
                format!("int{}_t", &tname[1..])
            }
        }
    } else {
        // Unknown type here, we always assume to use a struct Type*
        format!("struct {}*", tname)
    }
}

pub fn generate_c_api(filename: &str, api_def: &ApiDef) -> io::Result<()> {
	let mut f = File::create(filename)?;

	for sdef in &api_def.entries {
	    println!("name {}", sdef.name);
    }

    f.write_all(HEADER)?;

    // Write forward declarations

	for sdef in &api_def.entries {
        f.write_fmt(format_args!("struct PU{};\n", sdef.name))?;
    }

    f.write_all(b"\n")?;

    // Write the struct defs

	for sdef in &api_def.entries {
        f.write_fmt(format_args!("struct PU{} {{;\n", sdef.name))?;

        for entry in &sdef.entries {
            match *entry {
                StructEntry::Var(ref var) => {
                    f.write_fmt(format_args!("    {} {},\n", get_type_name(&var.vtype, var.primitive), var.name))?;
                },

                _ => (),
            }
        }

        f.write_fmt(format_args!("}}\n\n"))?;
    }

    f.write_all(FOOTER)?;

    Ok(())
}

<commit_msg>Fixed some code in the C generator<commit_after>use std::io;
use std::fs::File;
use std::io::Write;
use ::api_parser::*;

static HEADER: &'static [u8] = b"
#pragma once\n
#include <stdint.h>\n
#ifdef __cplusplus
extern \"C\" {
#endif\n\n";

static FOOTER: &'static [u8] = b"
#ifdef __cplusplus
}
#endif\n";

fn get_type_name(tname: &str, primitve: bool) -> String {
    if primitve {
        if tname == "f32" {
            "float".to_owned()
        } else if tname == "f64" {
            return "double".to_owned()
        } else {
            // here we will have u8/i8,u32/etc
           if tname.starts_with("u") {
                format!("uint{}_t", &tname[1..])
            } else {
                format!("int{}_t", &tname[1..])
            }
        }
    } else {
        // Unknown type here, we always assume to use a struct Type*
        format!("struct {}*", tname)
    }
}

pub fn generate_c_api(filename: &str, api_def: &ApiDef) -> io::Result<()> {
	let mut f = File::create(filename)?;

	for sdef in &api_def.entries {
	    println!("name {}", sdef.name);
    }

    f.write_all(HEADER)?;

    // Write forward declarations

	for sdef in &api_def.entries {
        f.write_fmt(format_args!("struct PU{};\n", sdef.name))?;
    }

    f.write_all(b"\n")?;

    // Write the struct defs

	for sdef in &api_def.entries {
        f.write_fmt(format_args!("struct PU{} {{\n", sdef.name))?;

        for entry in &sdef.entries {
            match *entry {
                StructEntry::Var(ref var) => {
                    f.write_fmt(format_args!("    {} {};\n", get_type_name(&var.vtype, var.primitive), var.name))?;
                },

                _ => (),
            }
        }

        f.write_fmt(format_args!("}};\n\n"))?;
    }

    f.write_all(FOOTER)?;

    Ok(())
}

<|endoftext|>