<commit_before>use proc_macro2;
use syn;

use diagnostic_shim::*;
use meta::*;
use model::*;
use util::*;

pub fn derive(item: syn::DeriveInput) -> Result<proc_macro2::TokenStream, Diagnostic> {
    let model = Model::from_item(&item)?;
    let tokens = MetaItem::all_with_name(&item.attrs, "belongs_to")
        .into_iter()
        .filter_map(
            |attr| match derive_belongs_to(&model, &item.generics, attr) {
                Ok(t) => Some(t),
                Err(e) => {
                    e.emit();
                    None
                }
            },
        );

    Ok(wrap_in_dummy_mod(
        model.dummy_mod_name("associations"),
        quote!(#(#tokens)*),
    ))
}

fn derive_belongs_to(
    model: &Model,
    generics: &syn::Generics,
    meta: MetaItem,
) -> Result<proc_macro2::TokenStream, Diagnostic> {
    let AssociationOptions {
        parent_struct,
        foreign_key,
    } = AssociationOptions::from_meta(meta)?;
    let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

    let foreign_key_field = model.find_column(&foreign_key)?;
    let struct_name = &model.name;
    let foreign_key_access = foreign_key_field.name.access();
    let foreign_key_ty = inner_of_option_ty(&foreign_key_field.ty);
    let table_name = model.table_name();

    let foreign_key_expr = if is_option_ty(&foreign_key_field.ty) {
        quote!(self#foreign_key_access.as_ref())
    } else {
        quote!(std::option::Option::Some(&self#foreign_key_access))
    };

    Ok(quote! {
        impl #impl_generics diesel::associations::BelongsTo<#parent_struct>
            for #struct_name #ty_generics
        #where_clause
        {
            type ForeignKey = #foreign_key_ty;
            type ForeignKeyColumn = #table_name::#foreign_key;

            fn foreign_key(&self) -> std::option::Option<&Self::ForeignKey> {
                #foreign_key_expr
            }

            fn foreign_key_column() -> Self::ForeignKeyColumn {
                #table_name::#foreign_key
            }
        }
    })
}

struct AssociationOptions {
    parent_struct: syn::Ident,
    foreign_key: syn::Ident,
}

impl AssociationOptions {
    fn from_meta(meta: MetaItem) -> Result<Self, Diagnostic> {
        let parent_struct = meta.nested()?
            .nth(0)
            .ok_or_else(|| meta.span())
            .and_then(|m| m.word().map_err(|_| m.span()))
            .map_err(|span| {
                span.error("Expected a struct name")
                    .help("e.g. `#[belongs_to(User)]`")
            })?;
        let foreign_key = meta.nested_item("foreign_key")
            .ok()
            .map(|i| i.ident_value())
            .unwrap_or_else(|| Ok(infer_foreign_key(&parent_struct)))?;

        let unrecognized_options = meta.nested()?.skip(1).filter(|n| n.name() != "foreign_key");
        for ignored in unrecognized_options {
            ignored
                .span()
                .warning(format!("Unrecognized option {}", ignored.name()))
                .emit();
        }

        Ok(Self {
            parent_struct,
            foreign_key,
        })
    }
}

fn infer_foreign_key(name: &syn::Ident) -> syn::Ident {
    let snake_case = camel_to_snake(&name.to_string());
    syn::Ident::new(&format!("{}_id", snake_case), name.span())
}
<commit_msg>Allow to customize foreign types in `#[derive(Associations)]`<commit_after>use proc_macro2;
use syn;

use diagnostic_shim::*;
use meta::*;
use model::*;
use util::*;

pub fn derive(item: syn::DeriveInput) -> Result<proc_macro2::TokenStream, Diagnostic> {
    let model = Model::from_item(&item)?;
    let tokens = MetaItem::all_with_name(&item.attrs, "belongs_to")
        .into_iter()
        .filter_map(
            |attr| match derive_belongs_to(&model, &item.generics, attr) {
                Ok(t) => Some(t),
                Err(e) => {
                    e.emit();
                    None
                }
            },
        );

    Ok(wrap_in_dummy_mod(
        model.dummy_mod_name("associations"),
        quote!(#(#tokens)*),
    ))
}

fn derive_belongs_to(
    model: &Model,
    generics: &syn::Generics,
    meta: MetaItem,
) -> Result<proc_macro2::TokenStream, Diagnostic> {
    let AssociationOptions {
        parent_struct,
        foreign_key,
    } = AssociationOptions::from_meta(meta)?;
    let (_, ty_generics, _) = generics.split_for_impl();

    let foreign_key_field = model.find_column(&foreign_key)?;
    let struct_name = &model.name;
    let foreign_key_access = foreign_key_field.name.access();
    let foreign_key_ty = inner_of_option_ty(&foreign_key_field.ty);
    let table_name = model.table_name();

    let mut generics = generics.clone();

    // TODO: Remove this specialcasing as soon as we bump our minimal supported
    // rust version to >= 1.30.0
    // Then we could use the `&Option<T> -> `Option<&T>` from implementation in
    // std lib
    let foreign_key_expr = if is_option_ty(&foreign_key_field.ty) {
        quote!(self#foreign_key_access.as_ref().and_then(std::convert::Into::into))
    } else {
        quote!(std::convert::Into::into(&self#foreign_key_access))
    };

    generics.params.push(parse_quote!(__FK));
    {
        let where_clause = generics.where_clause.get_or_insert(parse_quote!(where));
        where_clause
            .predicates
            .push(parse_quote!(__FK: std::hash::Hash + std::cmp::Eq));
        where_clause.predicates.push(
            parse_quote!(for<'__a> &'__a #foreign_key_ty: std::convert::Into<::std::option::Option<&'__a __FK>>),
        );
        where_clause.predicates.push(
            parse_quote!(for<'__a> &'__a #parent_struct: diesel::associations::Identifiable<Id = &'__a __FK>),
        );
    }

    let (impl_generics, _, where_clause) = generics.split_for_impl();

    Ok(quote! {
        impl #impl_generics diesel::associations::BelongsTo<#parent_struct>
            for #struct_name #ty_generics
            #where_clause
        {
            type ForeignKey = __FK;
            type ForeignKeyColumn = #table_name::#foreign_key;

            fn foreign_key(&self) -> std::option::Option<&Self::ForeignKey> {
                #foreign_key_expr
            }

            fn foreign_key_column() -> Self::ForeignKeyColumn {
                #table_name::#foreign_key
            }
        }
    })
}

struct AssociationOptions {
    parent_struct: syn::Ident,
    foreign_key: syn::Ident,
}

impl AssociationOptions {
    fn from_meta(meta: MetaItem) -> Result<Self, Diagnostic> {
        let parent_struct = meta.nested()?
            .nth(0)
            .ok_or_else(|| meta.span())
            .and_then(|m| m.word().map_err(|_| m.span()))
            .map_err(|span| {
                span.error("Expected a struct name")
                    .help("e.g. `#[belongs_to(User)]`")
            })?;
        let foreign_key = meta.nested_item("foreign_key")
            .ok()
            .map(|i| i.ident_value())
            .unwrap_or_else(|| Ok(infer_foreign_key(&parent_struct)))?;

        let unrecognized_options = meta.nested()?.skip(1).filter(|n| n.name() != "foreign_key");
        for ignored in unrecognized_options {
            ignored
                .span()
                .warning(format!("Unrecognized option {}", ignored.name()))
                .emit();
        }

        Ok(Self {
            parent_struct,
            foreign_key,
        })
    }
}

fn infer_foreign_key(name: &syn::Ident) -> syn::Ident {
    let snake_case = camel_to_snake(&name.to_string());
    syn::Ident::new(&format!("{}_id", snake_case), name.span())
}
<|endoftext|>


<commit_before>extern crate redis;

use flowgger::config::Config;
use flowgger::decoder::Decoder;
use flowgger::encoder::Encoder;
use self::redis::Commands;
use std::io::{stderr, Write};
use std::sync::mpsc::SyncSender;
use super::Input;

const DEFAULT_CONNECT: &'static str = "127.0.0.1";
const DEFAULT_QUEUE_KEY: &'static str = "logs";

pub struct RedisInput {
    connect: String,
    queue_key: String,
    queue_key_tmp: String
}

impl RedisInput {
    pub fn new(config: &Config) -> RedisInput {
        let connect = config.lookup("input.redis_connect").map_or(DEFAULT_CONNECT, |x|x.as_str().
            expect("input.redis_connect must be an ip:port string")).to_owned();
        let queue_key = config.lookup("input.redis_queue_key").map_or(DEFAULT_QUEUE_KEY, |x|x.as_str().
            expect("input.redis_queue_key must be a string")).to_owned();
        let queue_key_tmp = queue_key.clone() + ".tmp";
        RedisInput {
            connect: connect,
            queue_key: queue_key,
            queue_key_tmp: queue_key_tmp
        }
    }
}

impl Input for RedisInput {
    fn accept(&self, tx: SyncSender<Vec<u8>>, decoder: Box<Decoder + Send>, encoder: Box<Encoder + Send>) {
        let redis_cnx = match redis::Client::open(format!("redis://{}/", self.connect).as_ref()) {
            Err(_) => panic!("Invalid connection string for the Redis server: [{}]", self.connect),
            Ok(client) => match client.get_connection() {
                Err(_) => panic!("Unable to connect to the Redis server: [{}]", self.connect),
                Ok(redis_cnx) => redis_cnx
            }
        };
        println!("Connected to Redis [{}], pulling messages from key [{}]", self.connect, self.queue_key);
        let (decoder, encoder): (Box<Decoder>, Box<Encoder>) = (decoder, encoder);
        loop {
            let line: String = match redis_cnx.brpoplpush(self.queue_key.clone(), self.queue_key_tmp.clone(), 0) {
                Err(_) => panic!("Redis protocol error in BRPOPLPUSH"),
                Ok(line) => line
            };
            if let Err(e) = handle_line(&line, &tx, &decoder, &encoder) {
                let _ = writeln!(stderr(), "{}: [{}]", e, line.trim());
            }
            match redis_cnx.lrem(self.queue_key.clone(), 1, line) {
                Err(_) => panic!("Redis protocol error in LREM"),
                Ok(()) => ()
            };
        }
    }
}

fn handle_line(line: &String, tx: &SyncSender<Vec<u8>>, decoder: &Box<Decoder>, encoder: &Box<Encoder>) -> Result<(), &'static str> {
    let decoded = try!(decoder.decode(&line));
    let reencoded = try!(encoder.encode(decoded));
    tx.send(reencoded).unwrap();
    Ok(())
}
<commit_msg>Redis: if old messages were stuck in the temporary queue, reinject them into the active queue at startup<commit_after>extern crate redis;

use flowgger::config::Config;
use flowgger::decoder::Decoder;
use flowgger::encoder::Encoder;
use self::redis::{Commands, RedisResult};
use std::io::{stderr, Write};
use std::sync::mpsc::SyncSender;
use super::Input;

const DEFAULT_CONNECT: &'static str = "127.0.0.1";
const DEFAULT_QUEUE_KEY: &'static str = "logs";

pub struct RedisInput {
    connect: String,
    queue_key: String,
    queue_key_tmp: String
}

impl RedisInput {
    pub fn new(config: &Config) -> RedisInput {
        let connect = config.lookup("input.redis_connect").map_or(DEFAULT_CONNECT, |x|x.as_str().
            expect("input.redis_connect must be an ip:port string")).to_owned();
        let queue_key = config.lookup("input.redis_queue_key").map_or(DEFAULT_QUEUE_KEY, |x|x.as_str().
            expect("input.redis_queue_key must be a string")).to_owned();
        let queue_key_tmp = queue_key.clone() + ".tmp";
        RedisInput {
            connect: connect,
            queue_key: queue_key,
            queue_key_tmp: queue_key_tmp
        }
    }
}

impl Input for RedisInput {
    fn accept(&self, tx: SyncSender<Vec<u8>>, decoder: Box<Decoder + Send>, encoder: Box<Encoder + Send>) {
        let redis_cnx = match redis::Client::open(format!("redis://{}/", self.connect).as_ref()) {
            Err(_) => panic!("Invalid connection string for the Redis server: [{}]", self.connect),
            Ok(client) => match client.get_connection() {
                Err(_) => panic!("Unable to connect to the Redis server: [{}]", self.connect),
                Ok(redis_cnx) => redis_cnx
            }
        };
        println!("Connected to Redis [{}], pulling messages from key [{}]", self.connect, self.queue_key);
        while {
            let dummy: RedisResult<()> = redis_cnx.rpoplpush(self.queue_key_tmp.clone(), self.queue_key.clone());
            dummy.is_ok()
        } { };
        let (decoder, encoder): (Box<Decoder>, Box<Encoder>) = (decoder, encoder);
        loop {
            let line: String = match redis_cnx.brpoplpush(self.queue_key.clone(), self.queue_key_tmp.clone(), 0) {
                Err(_) => panic!("Redis protocol error in BRPOPLPUSH"),
                Ok(line) => line
            };
            if let Err(e) = handle_line(&line, &tx, &decoder, &encoder) {
                let _ = writeln!(stderr(), "{}: [{}]", e, line.trim());
            }
            match redis_cnx.lrem(self.queue_key.clone(), 1, line) {
                Err(_) => panic!("Redis protocol error in LREM"),
                Ok(()) => ()
            };
        }
    }
}

fn handle_line(line: &String, tx: &SyncSender<Vec<u8>>, decoder: &Box<Decoder>, encoder: &Box<Encoder>) -> Result<(), &'static str> {
    let decoded = try!(decoder.decode(&line));
    let reencoded = try!(encoder.encode(decoded));
    tx.send(reencoded).unwrap();
    Ok(())
}
<|endoftext|>


<commit_before>#![feature(proc_macro_hygiene)]
extern crate dynasmrt;
extern crate dynasm;

use dynasm::dynasm;
use dynasmrt::{DynasmApi, DynasmLabelApi};

extern crate itertools;
use itertools::Itertools;
use itertools::multipeek;

use std::io::{Read, BufRead, Write, stdin, stdout, BufReader, BufWriter};
use std::env;
use std::fs::File;
use std::slice;
use std::mem;
use std::u8;

const TAPE_SIZE: usize = 30000;

dynasm!(ops
    ; .arch aarch64
    ; .alias a_state, x0
    ; .alias a_current, x1
    ; .alias a_begin, x2
    ; .alias a_end, x3
    ; .alias retval, x0
);

macro_rules! prologue {
    ($ops:ident) => {{
        let start = $ops.offset();
        dynasm!($ops
            ; str x30, [sp, #-16]!
            ; stp x0, x1, [sp, #-16]!
            ; stp x2, x3, [sp, #-16]!
        );
        start
    }};
}

macro_rules! epilogue {
    ($ops:ident, $e:expr) => {dynasm!($ops
        ; mov x0, $e
        ; add sp, sp, #32
        ; ldr x30, [sp], #16
        ; ret
    );};
}

macro_rules! call_extern {
    ($ops:ident, $addr:ident) => {dynasm!($ops
        ; str x1, [sp, #24]
        ; ldr x9, ->addr
        ; blr x9
        ; ldp x0, x1, [sp, #16]
        ; ldp x2, x3, [sp]
    );};
}

struct State<'a> {
    pub input: Box<dyn BufRead + 'a>,
    pub output: Box<dyn Write + 'a>,
    tape: [u8; TAPE_SIZE],
}

struct Program {
    code: dynasmrt::ExecutableBuffer,
    start: dynasmrt::AssemblyOffset,
}

impl Program {
    fn compile(program: &[u8]) -> Result<Program, &'static str> {
        let mut ops = dynasmrt::aarch64::Assembler::new().unwrap();
        let mut loops = Vec::new();
        let mut code = multipeek(program.iter().cloned());

        let start = prologue!(ops);

        // literal pool
        dynasm!(ops
            ; ->getchar:
            ; .qword State::getchar as _
            ; ->putchar:
            ; .qword State::putchar as _
        );

        while let Some(c) = code.next() {
            match c {
                b'<' => {
                    let amount = code.take_while_ref(|x| *x == b'<').count() + 1;
                    dynasm!(ops
                        ; sub a_current, a_current, (amount % TAPE_SIZE) as u32 & 0xFFF
                        ; sub a_current, a_current, (amount % TAPE_SIZE) as u32 >> 12, LSL #12
                        ; cmp a_current, a_begin
                        ; b.hs >wrap
                        ; add a_current, a_current, TAPE_SIZE as u32 & 0xFFF
                        ; add a_current, a_current, TAPE_SIZE as u32 >> 12, LSL #12
                        ;wrap:
                    );
                },
                b'>' => {
                    let amount = code.take_while_ref(|x| *x == b'>').count() + 1;
                    dynasm!(ops
                        ; add a_current, a_current, (amount % TAPE_SIZE) as u32 & 0xFFF
                        ; add a_current, a_current, (amount % TAPE_SIZE) as u32 >> 12, LSL #12
                        ; cmp a_current, a_end
                        ; b.lo >wrap
                        ; sub a_current, a_current, TAPE_SIZE as u32 & 0xFFF
                        ; sub a_current, a_current, TAPE_SIZE as u32 >> 12, LSL #12
                        ;wrap:
                    );
                },
                b'+' => {
                    let amount = code.take_while_ref(|x| *x == b'+').count() + 1;
                    if amount > u8::MAX as usize {
                        return Err("An overflow occurred");
                    }
                    dynasm!(ops
                        ; ldrb w9, [a_current]
                        ; add w9, w9, amount as u32
                        ; tbnz w9, 8, >fine
                        ; b ->overflow
                        ;fine:
                        ; strb w9, [a_current]
                    );
                },
                b'-' => {
                    let amount = code.take_while_ref(|x| *x == b'-').count() + 1;
                    if amount > u8::MAX as usize {
                        return Err("An overflow occurred");
                    }
                    dynasm!(ops
                        ; ldrb w9, [a_current]
                        ; sub w9, w9, amount as u32
                        ; tbnz w9, 8, >fine
                        ; b ->overflow
                        ;fine:
                        ; strb w9, [a_current]
                    );
                },
                b',' => {
                    dynasm!(ops
                        ;; call_extern!(ops, getchar)
                        ; cbnz x0, ->io_failure
                    );
                },
                b'.' => {
                    dynasm!(ops
                        ;; call_extern!(ops, putchar)
                        ; cbnz x0, ->io_failure
                    );
                },
                b'[' => {
                    let first = code.peek() == Some(&b'-');
                    if first && code.peek() == Some(&b']') {
                        code.next();
                        code.next();
                        dynasm!(ops
                            ; strb wzr, [a_current]
                        );
                    } else {
                        let backward_label = ops.new_dynamic_label();
                        let forward_label = ops.new_dynamic_label();
                        loops.push((backward_label, forward_label));
                        dynasm!(ops
                            ; ldrb w9, [a_current]
                            ; cbz w9, =>forward_label
                            ;=>backward_label
                        );
                    }
                },
                b']' => {
                    if let Some((backward_label, forward_label)) = loops.pop() {
                        dynasm!(ops
                            ; ldrb w9, [a_current]
                            ; cbnz w9, =>backward_label
                            ;=>forward_label
                        );
                    } else {
                        return Err("] without matching [");
                    }
                },
                _ => (),
            }
        }
        if loops.len() != 0 {
            return Err("[ without matching ]");
        }

        dynasm!(ops
            ;; epilogue!(ops, 0)
            ;->overflow:
            ;; epilogue!(ops, 1)
            ;->io_failure:
            ;; epilogue!(ops, 2)
        );

        let code = ops.finalize().unwrap();
        Ok(Program {
            code: code,
            start: start,
        })
    }

    fn run(self, state: &mut State) -> Result<(), &'static str> {
        let f: extern "aapcs" fn(*mut State, *mut u8, *mut u8, *const u8) -> u8 =
            unsafe { mem::transmute(self.code.ptr(self.start)) };
        let start = state.tape.as_mut_ptr();
        let end = unsafe { start.offset(TAPE_SIZE as isize) };
        let res = f(state, start, start, end);
        if res == 0 {
            Ok(())
        } else if res == 1 {
            Err("An overflow occurred")
        } else if res == 2 {
            Err("IO error")
        } else {
            panic!("Unknown error code");
        }
    }
}

impl<'a> State<'a> {
    unsafe extern "aapcs" fn getchar(state: *mut State, cell: *mut u8) -> u8 {
        let state = &mut *state;
        let err = state.output.flush().is_err();
        (state.input.read_exact(slice::from_raw_parts_mut(cell, 1)).is_err() || err) as u8
    }

    unsafe extern "aapcs" fn putchar(state: *mut State, cell: *mut u8) -> u8 {
        let state = &mut *state;
        state.output.write_all(slice::from_raw_parts(cell, 1)).is_err() as u8
    }

    fn new(input: Box<dyn BufRead + 'a>, output: Box<dyn Write + 'a>) -> State<'a> {
        State {
            input: input,
            output: output,
            tape: [0; TAPE_SIZE],
        }
    }
}

fn main() {
    let mut args: Vec<_> = env::args().collect();
    if args.len() != 2 {
        println!("Expected 1 argument, got {}", args.len());
        return;
    }
    let path = args.pop().unwrap();

    let mut f = if let Ok(f) = File::open(&path) {
        f
    } else {
        println!("Could not open file {}", path);
        return;
    };

    let mut buf = Vec::new();
    if let Err(_) = f.read_to_end(&mut buf) {
        println!("Failed to read from file");
        return;
    }

    let mut state = State::new(Box::new(BufReader::new(stdin())),
                               Box::new(BufWriter::new(stdout())));
    let program = match Program::compile(&buf) {
        Ok(p) => p,
        Err(e) => {
            println!("{}", e);
            return;
        }
    };
    if let Err(e) = program.run(&mut state) {
        println!("{}", e);
        return;
    }
}
<commit_msg>More bugfixes<commit_after>#![feature(proc_macro_hygiene)]
extern crate dynasmrt;
extern crate dynasm;

use dynasm::dynasm;
use dynasmrt::{DynasmApi, DynasmLabelApi};

extern crate itertools;
use itertools::Itertools;
use itertools::multipeek;

use std::io::{Read, BufRead, Write, stdin, stdout, BufReader, BufWriter};
use std::env;
use std::fs::File;
use std::slice;
use std::mem;
use std::u8;

const TAPE_SIZE: usize = 30000;

dynasm!(ops
    ; .arch aarch64
    ; .alias a_state, x0
    ; .alias a_current, x1
    ; .alias a_begin, x2
    ; .alias a_end, x3
    ; .alias retval, x0
);

macro_rules! prologue {
    ($ops:ident) => {{
        let start = $ops.offset();
        dynasm!($ops
            ; str x30, [sp, #-16]!
            ; stp x0, x1, [sp, #-16]!
            ; stp x2, x3, [sp, #-16]!
        );
        start
    }};
}

macro_rules! epilogue {
    ($ops:ident, $e:expr) => {dynasm!($ops
        ; mov x0, $e
        ; add sp, sp, #32
        ; ldr x30, [sp], #16
        ; ret
    );};
}

macro_rules! call_extern {
    ($ops:ident, $addr:ident) => {dynasm!($ops
        ; str x1, [sp, #24]
        ; ldr x9, ->$addr
        ; blr x9
        ; mov x9, x0
        ; ldp x0, x1, [sp, #16]
        ; ldp x2, x3, [sp]
    );};
}

struct State<'a> {
    pub input: Box<dyn BufRead + 'a>,
    pub output: Box<dyn Write + 'a>,
    tape: [u8; TAPE_SIZE],
}

struct Program {
    code: dynasmrt::ExecutableBuffer,
    start: dynasmrt::AssemblyOffset,
}

impl Program {
    fn compile(program: &[u8]) -> Result<Program, &'static str> {
        let mut ops = dynasmrt::aarch64::Assembler::new().unwrap();
        let mut loops = Vec::new();
        let mut code = multipeek(program.iter().cloned());

        // literal pool
        dynasm!(ops
            ; ->getchar:
            ; .qword State::getchar as _
            ; ->putchar:
            ; .qword State::putchar as _
        );

        let start = prologue!(ops);

        while let Some(c) = code.next() {
            match c {
                b'<' => {
                    let amount = code.take_while_ref(|x| *x == b'<').count() + 1;
                    dynasm!(ops
                        ; sub a_current, a_current, (amount % TAPE_SIZE) as u32 & 0xFFF
                        ; sub a_current, a_current, (amount % TAPE_SIZE) as u32 >> 12, LSL #12
                        ; cmp a_current, a_begin
                        ; b.hs >wrap
                        ; add a_current, a_current, TAPE_SIZE as u32 & 0xFFF
                        ; add a_current, a_current, TAPE_SIZE as u32 >> 12, LSL #12
                        ;wrap:
                    );
                },
                b'>' => {
                    let amount = code.take_while_ref(|x| *x == b'>').count() + 1;
                    dynasm!(ops
                        ; add a_current, a_current, (amount % TAPE_SIZE) as u32 & 0xFFF
                        ; add a_current, a_current, (amount % TAPE_SIZE) as u32 >> 12, LSL #12
                        ; cmp a_current, a_end
                        ; b.lo >wrap
                        ; sub a_current, a_current, TAPE_SIZE as u32 & 0xFFF
                        ; sub a_current, a_current, TAPE_SIZE as u32 >> 12, LSL #12
                        ;wrap:
                    );
                },
                b'+' => {
                    let amount = code.take_while_ref(|x| *x == b'+').count() + 1;
                    if amount > u8::MAX as usize {
                        return Err("An overflow occurred");
                    }
                    dynasm!(ops
                        ; ldrb w9, [a_current]
                        ; add w9, w9, amount as u32
                        ; tbz w9, 8, >fine
                        ; b ->overflow
                        ;fine:
                        ; strb w9, [a_current]
                    );
                },
                b'-' => {
                    let amount = code.take_while_ref(|x| *x == b'-').count() + 1;
                    if amount > u8::MAX as usize {
                        return Err("An overflow occurred");
                    }
                    dynasm!(ops
                        ; ldrb w9, [a_current]
                        ; sub w9, w9, amount as u32
                        ; tbz w9, 8, >fine
                        ; b ->overflow
                        ;fine:
                        ; strb w9, [a_current]
                    );
                },
                b',' => {
                    dynasm!(ops
                        ;; call_extern!(ops, getchar)
                        ; cbnz x9, ->io_failure
                    );
                },
                b'.' => {
                    dynasm!(ops
                        ;; call_extern!(ops, putchar)
                        ; cbnz x9, ->io_failure
                    );
                },
                b'[' => {
                    let first = code.peek() == Some(&b'-');
                    if first && code.peek() == Some(&b']') {
                        code.next();
                        code.next();
                        dynasm!(ops
                            ; strb wzr, [a_current]
                        );
                    } else {
                        let backward_label = ops.new_dynamic_label();
                        let forward_label = ops.new_dynamic_label();
                        loops.push((backward_label, forward_label));
                        dynasm!(ops
                            ; ldrb w9, [a_current]
                            ; cbz w9, =>forward_label
                            ;=>backward_label
                        );
                    }
                },
                b']' => {
                    if let Some((backward_label, forward_label)) = loops.pop() {
                        dynasm!(ops
                            ; ldrb w9, [a_current]
                            ; cbnz w9, =>backward_label
                            ;=>forward_label
                        );
                    } else {
                        return Err("] without matching [");
                    }
                },
                _ => (),
            }
        }
        if loops.len() != 0 {
            return Err("[ without matching ]");
        }

        dynasm!(ops
            ;; epilogue!(ops, 0)
            ;->overflow:
            ;; epilogue!(ops, 1)
            ;->io_failure:
            ;; epilogue!(ops, 2)
        );

        let code = ops.finalize().unwrap();
        Ok(Program {
            code: code,
            start: start,
        })
    }

    fn run(self, state: &mut State) -> Result<(), &'static str> {
        let f: extern "C" fn(*mut State, *mut u8, *mut u8, *const u8) -> u8 =
            unsafe { mem::transmute(self.code.ptr(self.start)) };
        let start = state.tape.as_mut_ptr();
        let end = unsafe { start.offset(TAPE_SIZE as isize) };
        let res = f(state, start, start, end);
        if res == 0 {
            Ok(())
        } else if res == 1 {
            Err("An overflow occurred")
        } else if res == 2 {
            Err("IO error")
        } else {
            panic!("Unknown error code");
        }
    }
}

impl<'a> State<'a> {
    unsafe extern "C" fn getchar(state: *mut State, cell: *mut u8) -> u8 {
        let state = &mut *state;
        let err = state.output.flush().is_err();
        (state.input.read_exact(slice::from_raw_parts_mut(cell, 1)).is_err() || err) as u8
    }

    unsafe extern "C" fn putchar(state: *mut State, cell: *mut u8) -> u8 {
        let state = &mut *state;
        state.output.write_all(slice::from_raw_parts(cell, 1)).is_err() as u8
    }

    fn new(input: Box<dyn BufRead + 'a>, output: Box<dyn Write + 'a>) -> State<'a> {
        State {
            input: input,
            output: output,
            tape: [0; TAPE_SIZE],
        }
    }
}

fn main() {
    let mut args: Vec<_> = env::args().collect();
    if args.len() != 2 {
        println!("Expected 2 argument, got {}", args.len());
        return;
    }
    let path = args.pop().unwrap();

    let mut f = if let Ok(f) = File::open(&path) {
        f
    } else {
        println!("Could not open file {}", path);
        return;
    };

    let mut buf = Vec::new();
    if let Err(_) = f.read_to_end(&mut buf) {
        println!("Failed to read from file");
        return;
    }

    let mut state = State::new(Box::new(BufReader::new(stdin())),
                               Box::new(BufWriter::new(stdout())));
    let program = match Program::compile(&buf) {
        Ok(p) => p,
        Err(e) => {
            println!("{}", e);
            return;
        }
    };
    if let Err(e) = program.run(&mut state) {
        println!("{}", e);
        return;
    }
}
<|endoftext|>


<commit_before>use lib::*;

const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;

#[inline]
pub fn encode(c: char) -> Encode {
    let code = c as u32;
    let mut buf = [0; 4];
    let pos = if code < MAX_ONE_B {
        buf[3] = code as u8;
        3
    } else if code < MAX_TWO_B {
        buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
        buf[3] = (code & 0x3F) as u8 | TAG_CONT;
        2
    } else if code < MAX_THREE_B {
        buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
        buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
        buf[3] = (code & 0x3F) as u8 | TAG_CONT;
        1
    } else {
        buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
        buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
        buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
        buf[3] = (code & 0x3F) as u8 | TAG_CONT;
        0
    };
    Encode { buf: buf, pos: pos }
}

pub struct Encode {
    buf: [u8; 4],
    pos: usize,
}

impl Encode {
    // FIXME: use this from_utf8_unchecked, since we know it can never fail
    pub fn as_str(&self) -> &str {
        str::from_utf8(&self.buf[self.pos..]).unwrap()
    }
}
<commit_msg>This is not a bottleneck<commit_after>use lib::*;

const TAG_CONT: u8 = 0b1000_0000;
const TAG_TWO_B: u8 = 0b1100_0000;
const TAG_THREE_B: u8 = 0b1110_0000;
const TAG_FOUR_B: u8 = 0b1111_0000;
const MAX_ONE_B: u32 = 0x80;
const MAX_TWO_B: u32 = 0x800;
const MAX_THREE_B: u32 = 0x10000;

#[inline]
pub fn encode(c: char) -> Encode {
    let code = c as u32;
    let mut buf = [0; 4];
    let pos = if code < MAX_ONE_B {
        buf[3] = code as u8;
        3
    } else if code < MAX_TWO_B {
        buf[2] = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
        buf[3] = (code & 0x3F) as u8 | TAG_CONT;
        2
    } else if code < MAX_THREE_B {
        buf[1] = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
        buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
        buf[3] = (code & 0x3F) as u8 | TAG_CONT;
        1
    } else {
        buf[0] = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
        buf[1] = (code >> 12 & 0x3F) as u8 | TAG_CONT;
        buf[2] = (code >> 6 & 0x3F) as u8 | TAG_CONT;
        buf[3] = (code & 0x3F) as u8 | TAG_CONT;
        0
    };
    Encode { buf: buf, pos: pos }
}

pub struct Encode {
    buf: [u8; 4],
    pos: usize,
}

impl Encode {
    pub fn as_str(&self) -> &str {
        str::from_utf8(&self.buf[self.pos..]).unwrap()
    }
}
<|endoftext|>


<commit_before>use std::any::Any;
use std::io::{Result as IoResult, Error as IoError};
use std::io::Write;
use std::ops::{Deref, DerefMut};
use std::os::raw::{c_void, c_int};
use std::sync::Arc;
use std::sync::atomic::AtomicBool;

use wayland_sys::client::*;
use wayland_sys::common::*;
use {Handler, Proxy};

type ProxyUserData = (*mut EventQueueHandle, Arc<AtomicBool>);

/// Handle to an event queue
///
/// This handle gives you access to methods on an event queue
/// that are safe to do from within a callback.
///
/// They are also available on an `EventQueue` object via `Deref`.
pub struct EventQueueHandle {
    handlers: Vec<Box<Any>>
}

impl EventQueueHandle {
    /// Register a proxy to a handler of this event queue.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    ///
    /// This overwrites any precedently set Handler for this proxy.
    pub fn register<P: Proxy, H: Handler<P> + Any + 'static>(&mut self, proxy: &P, handler_id: usize) {
        let h = self.handlers[handler_id].downcast_ref::<H>()
                    .expect("Handler type do not match.");
        unsafe {
            let data: *mut ProxyUserData = ffi_dispatch!(
                WAYLAND_CLIENT_HANDLE,
                wl_proxy_get_user_data,
                proxy.ptr()
            ) as *mut _;
            (&mut *data).0 = self as *const _ as *mut _;
            ffi_dispatch!(
                WAYLAND_CLIENT_HANDLE,
                wl_proxy_add_dispatcher,
                proxy.ptr(),
                dispatch_func::<P,H>,
                h as *const _ as *const c_void,
                data as *mut c_void
            );
        }
    }

    /// Insert a new handler to this event queue
    ///
    /// Returns the index of this handler in the internal array, which is needed
    /// to register proxies to it.
    pub fn add_handler<H: Any + 'static>(&mut self, handler: H) -> usize {
        self.handlers.push(Box::new(handler) as Box<Any>);
        self.handlers.len() - 1
    }
}

/// Guard to access internal state of an event queue
///
/// This guard allows you to get references to the handlers you
/// previously stored inside an event queue.
///
/// It borrows the event queue, so no event dispatching is possible
/// as long as the guard is in scope, for safety reasons.
pub struct StateGuard<'evq> {
    evq: &'evq mut EventQueue
}

impl<'evq> StateGuard<'evq> {
    /// Get a reference to a handler
    ///
    /// Provides a reference to a handler stored in this event loop.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    pub fn get_handler<H: Any + 'static>(&self, handler_id: usize) -> &H {
        self.evq.handle.handlers[handler_id].downcast_ref::<H>()
            .expect("Handler type do not match.")
    }

    /// Get a mutable reference to a handler
    ///
    /// Provides a reference to a handler stored in this event loop.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    pub fn get_mut_handler<H: Any + 'static>(&mut self, handler_id: usize) -> &mut H {
        self.evq.handle.handlers[handler_id].downcast_mut::<H>()
            .expect("Handler type do not match.")
    }
}

/// An event queue managing wayland events
///
/// Each wayland object can receive events from the server. To handle these events
/// you must use a handler object: a struct (or enum) which you have implemented
/// the appropriate `Handler` traits on it (each wayland interface defines a `Handler`
/// trait in its module), and declared it using the `declare_handler!(..)` macro.
///
/// This handler contains the state all your handler methods will be able to access
/// via the `&mut self` argument. You can then instanciate your type, and give ownership of
/// the handler object to the event queue, via the `add_handler(..)` method. Then, each
/// wayland object must be registered to a handler via the `register(..)` method (or its events
/// will all be ignored).
///
/// The event queues also provides you control on the flow of the program, via the `dispatch()` and
/// `dispatch_pending()` methods.
pub struct EventQueue {
    display: *mut wl_display,
    wlevq: Option<*mut wl_event_queue>,
    handle: Box<EventQueueHandle>
}

impl EventQueue {
    /// Dispatches events from the internal buffer.
    ///
    /// Dispatches all events to their appropriate handlers.
    /// If not events were in the internal buffer, will block until
    /// some events are read and dispatch them.
    /// This process can insert events in the internal buffers of
    /// other event queues.
    ///
    /// If an error is returned, your connexion with the wayland
    /// compositor is probably lost.
    pub fn dispatch(&mut self) -> IoResult<u32> {
        let ret = match self.wlevq {
            Some(evq) => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_queue,
                    self.display,
                    evq
                )
            },
            None => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch,
                    self.display
                )
            }
        };
        if ret >= 0 {
            Ok(ret as u32)
        } else {
            Err(IoError::last_os_error())
        }
    }

    /// Dispatches pending events from the internal buffer.
    ///
    /// Dispatches all events to their appropriate handlers.
    /// Never blocks, if not events were pending, simply returns
    /// `Ok(0)`.
    ///
    /// If an error is returned, your connexion with the wayland
    /// compositor is probably lost.
    pub fn dispatch_pending(&mut self) -> IoResult<u32> {
        let ret = match self.wlevq {
            Some(evq) => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_queue_pending,
                    self.display,
                    evq
                )
            },
            None => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_pending,
                    self.display
                )
            }
        };
        if ret >= 0 {
            Ok(ret as u32)
        } else {
            Err(IoError::last_os_error())
        }
    }

    /// Synchronous roundtrip
    ///
    /// This call will cause a synchonous roundtrip with the wayland server. It will block until all
    /// pending requests of this queue are send to the server and it has processed all of them and
    /// send the appropriate events.
    ///
    /// Handlers are called as a consequence.
    ///
    /// On success returns the number of dispatched events.
    pub fn sync_roundtrip(&mut self) -> IoResult<i32> {
        let ret = unsafe { match self.wlevq {
            Some(evtq) => {
                ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_roundtrip_queue,
                    self.display, evtq)
            }
            None => {
                ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_roundtrip, self.display)
            }
        }};
        if ret >= 0 { Ok(ret) } else { Err(IoError::last_os_error()) }
    }

    /// Get a handle to the internal state
    ///
    /// The returned guard object allows you to get references
    /// to the handler objects you previously inserted in this
    /// event queue.
    pub fn state(&mut self) -> StateGuard {
        StateGuard { evq: self }
    }
}

impl Deref for EventQueue {
    type Target = EventQueueHandle;
    fn deref(&self) -> &EventQueueHandle {
        &*self.handle
    }
}

impl DerefMut for EventQueue {
    fn deref_mut(&mut self) -> &mut EventQueueHandle {
        &mut *self.handle
    }
}

pub unsafe fn create_event_queue(display: *mut wl_display, evq: Option<*mut wl_event_queue>) -> EventQueue {
    EventQueue {
        display: display,
        wlevq: evq,
        handle: Box::new(EventQueueHandle {
            handlers: Vec::new()
        })
    }
}

unsafe extern "C" fn dispatch_func<P: Proxy, H: Handler<P>>(
    handler: *const c_void,
    proxy: *mut c_void,
    opcode: u32,
    _msg: *const wl_message,
    args: *const wl_argument
) -> c_int {
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        // This cast from *const to *mut is legit because we enforce that a Handler
        // can only be assigned to a single EventQueue.
        // (this is actually the whole point of the design of this lib)
        let handler = &mut *(handler as *const H as *mut H);
        let proxy = P::from_ptr_initialized(proxy as *mut wl_proxy);
        let data = &mut *(ffi_dispatch!(
            WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, proxy.ptr()
        ) as *mut ProxyUserData);
        let evqhandle = &mut *data.0;
        handler.message(evqhandle, &proxy, opcode, args)
    });
    match ret {
        Ok(Ok(())) => return 0,   // all went well
        Ok(Err(())) => {
            // an unknown opcode was dispatched, this is not normal
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-client error] Attempted to dispatch unknown opcode {} for {}, aborting.",
                opcode, P::interface_name()
            );
            ::libc::abort();
        }
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-client error] A handler for {} panicked, aborting.",
                P::interface_name()
            );
            ::libc::abort();
        }
    }
}

/// Registers a handler type so it can be used in event queue
///
/// After having implemented the appropriate Handler trait for your type,
/// declare it via this macro, like this:
///
/// ```ignore
/// struct MyHandler;
///
/// impl wl_foo::Handler for MyHandler {
///     ...
/// }
///
/// declare_handler!(MyHandler, wl_foo::Handler, wl_foo::WlFoo);
/// ```
#[macro_export]
macro_rules! declare_handler(
    ($handler_struct: ty, $handler_trait: path, $handled_type: ty) => {
        unsafe impl $crate::Handler<$handled_type> for $handler_struct {
            unsafe fn message(&mut self, evq: &mut $crate::EventQueueHandle, proxy: &$handled_type, opcode: u32, args: *const $crate::sys::wl_argument) -> Result<(),()> {
                <$handler_struct as $handler_trait>::__message(self, evq, proxy, opcode, args)
            }
        }
    }
);
<commit_msg>client: add an example to EventQueue<commit_after>use std::any::Any;
use std::io::{Result as IoResult, Error as IoError};
use std::io::Write;
use std::ops::{Deref, DerefMut};
use std::os::raw::{c_void, c_int};
use std::sync::Arc;
use std::sync::atomic::AtomicBool;

use wayland_sys::client::*;
use wayland_sys::common::*;
use {Handler, Proxy};

type ProxyUserData = (*mut EventQueueHandle, Arc<AtomicBool>);

/// Handle to an event queue
///
/// This handle gives you access to methods on an event queue
/// that are safe to do from within a callback.
///
/// They are also available on an `EventQueue` object via `Deref`.
pub struct EventQueueHandle {
    handlers: Vec<Box<Any>>
}

impl EventQueueHandle {
    /// Register a proxy to a handler of this event queue.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    ///
    /// This overwrites any precedently set Handler for this proxy.
    pub fn register<P: Proxy, H: Handler<P> + Any + 'static>(&mut self, proxy: &P, handler_id: usize) {
        let h = self.handlers[handler_id].downcast_ref::<H>()
                    .expect("Handler type do not match.");
        unsafe {
            let data: *mut ProxyUserData = ffi_dispatch!(
                WAYLAND_CLIENT_HANDLE,
                wl_proxy_get_user_data,
                proxy.ptr()
            ) as *mut _;
            (&mut *data).0 = self as *const _ as *mut _;
            ffi_dispatch!(
                WAYLAND_CLIENT_HANDLE,
                wl_proxy_add_dispatcher,
                proxy.ptr(),
                dispatch_func::<P,H>,
                h as *const _ as *const c_void,
                data as *mut c_void
            );
        }
    }

    /// Insert a new handler to this event queue
    ///
    /// Returns the index of this handler in the internal array, which is needed
    /// to register proxies to it.
    pub fn add_handler<H: Any + 'static>(&mut self, handler: H) -> usize {
        self.handlers.push(Box::new(handler) as Box<Any>);
        self.handlers.len() - 1
    }
}

/// Guard to access internal state of an event queue
///
/// This guard allows you to get references to the handlers you
/// previously stored inside an event queue.
///
/// It borrows the event queue, so no event dispatching is possible
/// as long as the guard is in scope, for safety reasons.
pub struct StateGuard<'evq> {
    evq: &'evq mut EventQueue
}

impl<'evq> StateGuard<'evq> {
    /// Get a reference to a handler
    ///
    /// Provides a reference to a handler stored in this event loop.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    pub fn get_handler<H: Any + 'static>(&self, handler_id: usize) -> &H {
        self.evq.handle.handlers[handler_id].downcast_ref::<H>()
            .expect("Handler type do not match.")
    }

    /// Get a mutable reference to a handler
    ///
    /// Provides a reference to a handler stored in this event loop.
    ///
    /// The H type must be provided and match the type of the targetted Handler, or
    /// it will panic.
    pub fn get_mut_handler<H: Any + 'static>(&mut self, handler_id: usize) -> &mut H {
        self.evq.handle.handlers[handler_id].downcast_mut::<H>()
            .expect("Handler type do not match.")
    }
}

/// An event queue managing wayland events
///
/// Each wayland object can receive events from the server. To handle these events
/// you must use a handler object: a struct (or enum) which you have implemented
/// the appropriate `Handler` traits on it (each wayland interface defines a `Handler`
/// trait in its module), and declared it using the `declare_handler!(..)` macro.
///
/// This handler contains the state all your handler methods will be able to access
/// via the `&mut self` argument. You can then instanciate your type, and give ownership of
/// the handler object to the event queue, via the `add_handler(..)` method. Then, each
/// wayland object must be registered to a handler via the `register(..)` method (or its events
/// will all be ignored).
///
/// The event queues also provides you control on the flow of the program, via the `dispatch()` and
/// `dispatch_pending()` methods.
///
/// ## example of use
///
/// ```ignore
/// struct MyHandler { /* ... */ }
///
/// impl wl_surface::Handler for MyHandler {
///     // implementation of the handler methods
/// }
///
/// declare_handler!(MyHandler, wl_surface::Handler, wl_surface::WlSurface);
///
/// fn main() {
///     /* ... setup of your environment ... */
///     let surface = compositor.create_surface().expect("Compositor cannot be destroyed.");
///     let my_id = eventqueue.add_handler(MyHandler::new());
///     eventqueue.register::<_, MyHandler>(&surface, my_id);
///
///     // main event loop
///     loop {
///         // flush requests to the server
///         display.flush().unwrap();
///         // dispatch events from the server, blocking if needed
///         eventqueue.dispatch().unwrap();
///     }
/// }
/// ```
pub struct EventQueue {
    display: *mut wl_display,
    wlevq: Option<*mut wl_event_queue>,
    handle: Box<EventQueueHandle>
}

impl EventQueue {
    /// Dispatches events from the internal buffer.
    ///
    /// Dispatches all events to their appropriate handlers.
    /// If not events were in the internal buffer, will block until
    /// some events are read and dispatch them.
    /// This process can insert events in the internal buffers of
    /// other event queues.
    ///
    /// If an error is returned, your connexion with the wayland
    /// compositor is probably lost.
    pub fn dispatch(&mut self) -> IoResult<u32> {
        let ret = match self.wlevq {
            Some(evq) => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_queue,
                    self.display,
                    evq
                )
            },
            None => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch,
                    self.display
                )
            }
        };
        if ret >= 0 {
            Ok(ret as u32)
        } else {
            Err(IoError::last_os_error())
        }
    }

    /// Dispatches pending events from the internal buffer.
    ///
    /// Dispatches all events to their appropriate handlers.
    /// Never blocks, if not events were pending, simply returns
    /// `Ok(0)`.
    ///
    /// If an error is returned, your connexion with the wayland
    /// compositor is probably lost.
    pub fn dispatch_pending(&mut self) -> IoResult<u32> {
        let ret = match self.wlevq {
            Some(evq) => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_queue_pending,
                    self.display,
                    evq
                )
            },
            None => unsafe {
                ffi_dispatch!(
                    WAYLAND_CLIENT_HANDLE,
                    wl_display_dispatch_pending,
                    self.display
                )
            }
        };
        if ret >= 0 {
            Ok(ret as u32)
        } else {
            Err(IoError::last_os_error())
        }
    }

    /// Synchronous roundtrip
    ///
    /// This call will cause a synchonous roundtrip with the wayland server. It will block until all
    /// pending requests of this queue are send to the server and it has processed all of them and
    /// send the appropriate events.
    ///
    /// Handlers are called as a consequence.
    ///
    /// On success returns the number of dispatched events.
    pub fn sync_roundtrip(&mut self) -> IoResult<i32> {
        let ret = unsafe { match self.wlevq {
            Some(evtq) => {
                ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_roundtrip_queue,
                    self.display, evtq)
            }
            None => {
                ffi_dispatch!(WAYLAND_CLIENT_HANDLE, wl_display_roundtrip, self.display)
            }
        }};
        if ret >= 0 { Ok(ret) } else { Err(IoError::last_os_error()) }
    }

    /// Get a handle to the internal state
    ///
    /// The returned guard object allows you to get references
    /// to the handler objects you previously inserted in this
    /// event queue.
    pub fn state(&mut self) -> StateGuard {
        StateGuard { evq: self }
    }
}

impl Deref for EventQueue {
    type Target = EventQueueHandle;
    fn deref(&self) -> &EventQueueHandle {
        &*self.handle
    }
}

impl DerefMut for EventQueue {
    fn deref_mut(&mut self) -> &mut EventQueueHandle {
        &mut *self.handle
    }
}

pub unsafe fn create_event_queue(display: *mut wl_display, evq: Option<*mut wl_event_queue>) -> EventQueue {
    EventQueue {
        display: display,
        wlevq: evq,
        handle: Box::new(EventQueueHandle {
            handlers: Vec::new()
        })
    }
}

unsafe extern "C" fn dispatch_func<P: Proxy, H: Handler<P>>(
    handler: *const c_void,
    proxy: *mut c_void,
    opcode: u32,
    _msg: *const wl_message,
    args: *const wl_argument
) -> c_int {
    // We don't need to worry about panic-safeness, because if there is a panic,
    // we'll abort the process, so no access to corrupted data is possible.
    let ret = ::std::panic::catch_unwind(move || {
        // This cast from *const to *mut is legit because we enforce that a Handler
        // can only be assigned to a single EventQueue.
        // (this is actually the whole point of the design of this lib)
        let handler = &mut *(handler as *const H as *mut H);
        let proxy = P::from_ptr_initialized(proxy as *mut wl_proxy);
        let data = &mut *(ffi_dispatch!(
            WAYLAND_CLIENT_HANDLE, wl_proxy_get_user_data, proxy.ptr()
        ) as *mut ProxyUserData);
        let evqhandle = &mut *data.0;
        handler.message(evqhandle, &proxy, opcode, args)
    });
    match ret {
        Ok(Ok(())) => return 0,   // all went well
        Ok(Err(())) => {
            // an unknown opcode was dispatched, this is not normal
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-client error] Attempted to dispatch unknown opcode {} for {}, aborting.",
                opcode, P::interface_name()
            );
            ::libc::abort();
        }
        Err(_) => {
            // a panic occured
            let _ = write!(
                ::std::io::stderr(),
                "[wayland-client error] A handler for {} panicked, aborting.",
                P::interface_name()
            );
            ::libc::abort();
        }
    }
}

/// Registers a handler type so it can be used in event queue
///
/// After having implemented the appropriate Handler trait for your type,
/// declare it via this macro, like this:
///
/// ```ignore
/// struct MyHandler;
///
/// impl wl_foo::Handler for MyHandler {
///     ...
/// }
///
/// declare_handler!(MyHandler, wl_foo::Handler, wl_foo::WlFoo);
/// ```
#[macro_export]
macro_rules! declare_handler(
    ($handler_struct: ty, $handler_trait: path, $handled_type: ty) => {
        unsafe impl $crate::Handler<$handled_type> for $handler_struct {
            unsafe fn message(&mut self, evq: &mut $crate::EventQueueHandle, proxy: &$handled_type, opcode: u32, args: *const $crate::sys::wl_argument) -> Result<(),()> {
                <$handler_struct as $handler_trait>::__message(self, evq, proxy, opcode, args)
            }
        }
    }
);
<|endoftext|>


<commit_before>use alloc::arc::Arc;

use arch::context::{CONTEXT_STACK_SIZE, CONTEXT_STACK_ADDR, context_switch, context_userspace, Context, ContextMemory};
use arch::elf::Elf;
use arch::memory;
use arch::regs::Regs;

use collections::string::{String, ToString};
use collections::vec::Vec;

use common::slice::GetSlice;

use core::cell::UnsafeCell;
use core::ops::DerefMut;
use core::{mem, ptr};

use fs::Url;

use system::error::{Error, Result, ENOEXEC};

fn execute_inner(url: Url) -> Result<(*mut Context, usize)> {
    let mut vec: Vec<u8> = Vec::new();

    {
        let mut resource = try!(url.open());
        'reading: loop {
            let mut bytes = [0; 4096];
            match resource.read(&mut bytes) {
                Ok(0) => break 'reading,
                Ok(count) => vec.push_all(bytes.get_slice(.. count)),
                Err(err) => return Err(err)
            }
        }
    }

    match Elf::from(&vec) {
        Ok(executable) => {
            let entry = unsafe { executable.entry() };
            let mut memory = Vec::new();
            unsafe {
                for segment in executable.load_segment().iter() {
                    let virtual_address = segment.vaddr as usize;
                    let virtual_size = segment.mem_len as usize;

                    let offset = virtual_address % 4096;

                    let physical_address = memory::alloc(virtual_size + offset);

                    if physical_address > 0 {
                        // Copy progbits
                        ::memcpy((physical_address + offset) as *mut u8,
                                 (executable.data.as_ptr() as usize + segment.off as usize) as *const u8,
                                 segment.file_len as usize);
                        // Zero bss
                        if segment.mem_len > segment.file_len {
                            ::memset((physical_address + offset + segment.file_len as usize) as *mut u8,
                                    0,
                                    segment.mem_len as usize - segment.file_len as usize);
                        }

                        memory.push(ContextMemory {
                            physical_address: physical_address,
                            virtual_address: virtual_address - offset,
                            virtual_size: virtual_size + offset,
                            writeable: segment.flags & 2 == 2,
                            allocated: true,
                        });
                    }
                }
            }

            if entry > 0 && ! memory.is_empty() {
                let mut contexts = ::env().contexts.lock();
                let mut context = try!(contexts.current_mut());

                //debugln!("{}: {}: execute {}", context.pid, context.name, url.string);

                context.name = url.string;
                context.cwd = Arc::new(UnsafeCell::new(unsafe { (*context.cwd.get()).clone() }));

                unsafe { context.unmap() };
                context.memory = Arc::new(UnsafeCell::new(memory));
                unsafe { context.map() };

                Ok((context.deref_mut(), entry))
            } else {
                Err(Error::new(ENOEXEC))
            }
        },
        Err(msg) => {
            debugln!("execute: failed to exec '{}': {}", url.string, msg);
            Err(Error::new(ENOEXEC))
        }
    }
}

pub fn execute_outer(context_ptr: *mut Context, entry: usize, mut args: Vec<String>) -> ! {
    Context::spawn("kexec".to_string(), box move || {
        let context = unsafe { &mut *context_ptr };

        let mut context_args: Vec<usize> = Vec::new();
        context_args.push(0); // ENVP
        context_args.push(0); // ARGV NULL
        let mut argc = 0;
        while let Some(mut arg) = args.pop() {
            if ! arg.ends_with('\0') {
                arg.push('\0');
            }

            let physical_address = arg.as_ptr() as usize;
            let virtual_address = context.next_mem();
            let virtual_size = arg.len();

            mem::forget(arg);

            unsafe {
                (*context.memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: virtual_size,
                    writeable: false,
                    allocated: true,
                });
            }

            context_args.push(virtual_address as usize);
            argc += 1;
        }
        context_args.push(argc);

        context.regs = Regs::default();
        context.regs.sp = context.kernel_stack + CONTEXT_STACK_SIZE - 128;

        context.stack = Some(ContextMemory {
            physical_address: unsafe { memory::alloc(CONTEXT_STACK_SIZE) },
            virtual_address: CONTEXT_STACK_ADDR,
            virtual_size: CONTEXT_STACK_SIZE,
            writeable: true,
            allocated: true,
        });

        let user_sp = if let Some(ref stack) = context.stack {
            let mut sp = stack.physical_address + stack.virtual_size - 128;
            for arg in context_args.iter() {
                sp -= mem::size_of::<usize>();
                unsafe { ptr::write(sp as *mut usize, *arg) };
            }
            sp - stack.physical_address + stack.virtual_address
        } else {
            0
        };

        unsafe {
            context.push(0x20 | 3);
            context.push(user_sp);
            context.push(1 << 9);
            context.push(0x18 | 3);
            context.push(entry);
            context.push(context_userspace as usize);
        }

        if let Some(vfork) = context.vfork.take() {
            unsafe { (*vfork).blocked = false; }
        }
    });

    loop {
        unsafe { context_switch() };
    }
}

/// Execute an executable
pub fn execute(args: Vec<String>) -> Result<usize> {
    let contexts = ::env().contexts.lock();
    let current = try!(contexts.current());

    if let Ok((context_ptr, entry)) = execute_inner(Url::from_string(current.canonicalize(args.get(0).map_or("", |p| &p)))) {
        execute_outer(context_ptr, entry, args);
    }else{
        let (context_ptr, entry) = try!(execute_inner(Url::from_string("file:/bin/".to_string() + args.get(0).map_or("", |p| &p))));
        execute_outer(context_ptr, entry, args);
    }
}
<commit_msg>Hack to fix sys_brk<commit_after>use alloc::arc::Arc;

use arch::context::{CONTEXT_STACK_SIZE, CONTEXT_STACK_ADDR, context_switch, context_userspace, Context, ContextMemory};
use arch::elf::Elf;
use arch::memory;
use arch::regs::Regs;

use collections::string::{String, ToString};
use collections::vec::Vec;

use common::slice::GetSlice;

use core::cell::UnsafeCell;
use core::ops::DerefMut;
use core::{mem, ptr};

use fs::Url;

use system::error::{Error, Result, ENOEXEC};

fn execute_inner(url: Url) -> Result<(*mut Context, usize)> {
    let mut vec: Vec<u8> = Vec::new();

    {
        let mut resource = try!(url.open());
        'reading: loop {
            let mut bytes = [0; 4096];
            match resource.read(&mut bytes) {
                Ok(0) => break 'reading,
                Ok(count) => vec.push_all(bytes.get_slice(.. count)),
                Err(err) => return Err(err)
            }
        }
    }

    match Elf::from(&vec) {
        Ok(executable) => {
            let entry = unsafe { executable.entry() };
            let mut memory = Vec::new();
            unsafe {
                for segment in executable.load_segment().iter() {
                    let virtual_address = segment.vaddr as usize;
                    let virtual_size = segment.mem_len as usize;

                    let offset = virtual_address % 4096;

                    let physical_address = memory::alloc(virtual_size + offset);

                    if physical_address > 0 {
                        // Copy progbits
                        ::memcpy((physical_address + offset) as *mut u8,
                                 (executable.data.as_ptr() as usize + segment.off as usize) as *const u8,
                                 segment.file_len as usize);
                        // Zero bss
                        if segment.mem_len > segment.file_len {
                            ::memset((physical_address + offset + segment.file_len as usize) as *mut u8,
                                    0,
                                    segment.mem_len as usize - segment.file_len as usize);
                        }

                        memory.push(ContextMemory {
                            physical_address: physical_address,
                            virtual_address: virtual_address - offset,
                            virtual_size: virtual_size + offset,
                            writeable: segment.flags & 2 == 2,
                            allocated: true,
                        });
                    }
                }
            }

            if entry > 0 && ! memory.is_empty() {
                let mut contexts = ::env().contexts.lock();
                let mut context = try!(contexts.current_mut());

                //debugln!("{}: {}: execute {}", context.pid, context.name, url.string);

                context.name = url.string;
                context.cwd = Arc::new(UnsafeCell::new(unsafe { (*context.cwd.get()).clone() }));

                unsafe { context.unmap() };
                context.memory = Arc::new(UnsafeCell::new(memory));
                unsafe { context.map() };

                Ok((context.deref_mut(), entry))
            } else {
                Err(Error::new(ENOEXEC))
            }
        },
        Err(msg) => {
            debugln!("execute: failed to exec '{}': {}", url.string, msg);
            Err(Error::new(ENOEXEC))
        }
    }
}

pub fn execute_outer(context_ptr: *mut Context, entry: usize, mut args: Vec<String>) -> ! {
    Context::spawn("kexec".to_string(), box move || {
        let context = unsafe { &mut *context_ptr };

        let mut context_args: Vec<usize> = Vec::new();
        context_args.push(0); // ENVP
        context_args.push(0); // ARGV NULL
        let mut argc = 0;
        while let Some(mut arg) = args.pop() {
            if ! arg.ends_with('\0') {
                arg.push('\0');
            }

            let physical_address = arg.as_ptr() as usize;
            let virtual_address = context.next_mem();
            let virtual_size = arg.len();

            mem::forget(arg);

            unsafe {
                (*context.memory.get()).push(ContextMemory {
                    physical_address: physical_address,
                    virtual_address: virtual_address,
                    virtual_size: virtual_size,
                    writeable: false,
                    allocated: true,
                });
            }

            context_args.push(virtual_address as usize);
            argc += 1;
        }
        context_args.push(argc);

        //TODO: No default heap, fix brk
        {
            let virtual_address = context.next_mem();
            let virtual_size = 4096;
            let physical_address = unsafe { memory::alloc(virtual_size) };
            if physical_address > 0 {
                unsafe {
                    (*context.memory.get()).push(ContextMemory {
                        physical_address: physical_address,
                        virtual_address: virtual_address,
                        virtual_size: virtual_size,
                        writeable: true,
                        allocated: true
                    });
                }
            }
        }

        context.regs = Regs::default();
        context.regs.sp = context.kernel_stack + CONTEXT_STACK_SIZE - 128;

        context.stack = Some(ContextMemory {
            physical_address: unsafe { memory::alloc(CONTEXT_STACK_SIZE) },
            virtual_address: CONTEXT_STACK_ADDR,
            virtual_size: CONTEXT_STACK_SIZE,
            writeable: true,
            allocated: true,
        });

        let user_sp = if let Some(ref stack) = context.stack {
            let mut sp = stack.physical_address + stack.virtual_size - 128;
            for arg in context_args.iter() {
                sp -= mem::size_of::<usize>();
                unsafe { ptr::write(sp as *mut usize, *arg) };
            }
            sp - stack.physical_address + stack.virtual_address
        } else {
            0
        };

        unsafe {
            context.push(0x20 | 3);
            context.push(user_sp);
            context.push(1 << 9);
            context.push(0x18 | 3);
            context.push(entry);
            context.push(context_userspace as usize);
        }

        if let Some(vfork) = context.vfork.take() {
            unsafe { (*vfork).blocked = false; }
        }
    });

    loop {
        unsafe { context_switch() };
    }
}

/// Execute an executable
pub fn execute(args: Vec<String>) -> Result<usize> {
    let contexts = ::env().contexts.lock();
    let current = try!(contexts.current());

    if let Ok((context_ptr, entry)) = execute_inner(Url::from_string(current.canonicalize(args.get(0).map_or("", |p| &p)))) {
        execute_outer(context_ptr, entry, args);
    }else{
        let (context_ptr, entry) = try!(execute_inner(Url::from_string("file:/bin/".to_string() + args.get(0).map_or("", |p| &p))));
        execute_outer(context_ptr, entry, args);
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![allow(unrooted_must_root)]

use dom::document::Document;
use url::Url;
use util::str::DOMString;

pub enum ParseContext {
    Owner(Option<i32>)
}

pub fn parse_xml(document: &Document,
                 input: DOMString,
                 url: Url,
                 context: ParseContext) {
}
<commit_msg>Auto merge of #8344 - Ms2ger:warnings, r=saneyuki<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#![allow(unrooted_must_root)]

use dom::document::Document;
use url::Url;
use util::str::DOMString;

pub enum ParseContext {
    Owner(Option<i32>)
}

pub fn parse_xml(_document: &Document,
                 _input: DOMString,
                 _url: Url,
                 _context: ParseContext) {
}
<|endoftext|>


<commit_before>//  rpc-perf - RPC Performance Testing
//  Copyright 2015 Twitter, Inc
//
//  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 byteorder;

use byteorder::{ByteOrder, BigEndian};

/// this is work in progress to speak framed binary thrift

pub struct Buffer {
    buffer: Vec<u8>,
}

impl Buffer {
    pub fn new() -> Buffer {
        let mut buffer = Vec::<u8>::new();
        buffer.resize(4, 0);

        Buffer { buffer: buffer }
    }

    pub fn buffer(&mut self) -> Vec<u8> {
        self.buffer.clone()
    }

    /// add protocol version to buffer
    ///
    /// # Example
    /// ```
    /// # use rpcperf_request::thrift::*;
    ///
    // let mut buffer = Vec::<u8>::new();
    // protocol_header(&mut buffer);
    // let expected = vec![128, 1, 0, 1];
    // assert_eq!(buffer, expected);
    pub fn protocol_header(&mut self) -> &Self {
        self.buffer.extend_from_slice(&[128, 1, 0, 1]);
        self
    }

    /// write the framed length to the buffer
    ///
    /// # Example
    /// ```
    /// # use rpcperf_request::thrift::*;
    ///
    /// let mut b = Buffer::new();
    /// b.sequence_id(0_i32);
    /// b.frame();
    /// let expected = vec![0, 0, 0, 4, 0, 0, 0, 0];
    /// assert_eq!(b.buffer(), expected);
    pub fn frame(&mut self) -> &Self {
        let bytes = self.buffer.len() - 4;
        BigEndian::write_i32(&mut self.buffer[..4], bytes as i32);
        self
    }

    /// add method name to buffer
    ///
    /// # Example
    /// ```
    /// # use rpcperf_request::thrift::Buffer;
    ///
    /// let mut b = Buffer::new();
    /// b.method_name("ping".to_string());
    /// let expected = vec![0, 0, 0, 0, 0, 0, 0, 4, 112, 105, 110, 103];
    /// assert_eq!(b.buffer(), expected);
    pub fn method_name(&mut self, method: String) -> &Self {
        self.write_string(method)
    }

    /// add sequence id to buffer
    ///
    /// # Example
    /// ```
    /// # use rpcperf_request::thrift::Buffer;
    ///
    /// let mut b = Buffer::new();
    /// b.sequence_id(0_i32);
    /// let expected = vec![0, 0, 0, 0, 0, 0, 0, 0];
    /// assert_eq!(b.buffer(), expected);
    pub fn sequence_id(&mut self, id: i32) -> &Self {
        self.write_i32(id as i32)
    }

    /// add stop sequence to buffer
    ///
    /// # Example
    /// ```
    /// # use rpcperf_request::thrift::Buffer;
    ///
    /// let mut b = Buffer::new();
    /// b.stop();
    /// let expected = vec![0, 0, 0, 0, 0];
    /// assert_eq!(b.buffer(), expected);
    pub fn stop(&mut self) -> &Self {
        self.write_bytes(&[0])
    }

    fn write_i32(&mut self, value: i32) -> &Self {
        let bytes = self.buffer.len();
        self.buffer.resize(bytes + 4, 0);
        BigEndian::write_i32(&mut self.buffer[bytes..], value);
        self
    }

    fn write_bytes(&mut self, bytes: &[u8]) -> &Self {
        self.buffer.extend_from_slice(bytes);
        self
    }

    fn write_string(&mut self, string: String) -> &Self {
        let mut string = string.into_bytes();
        self.write_i32(string.len() as i32);
        self.buffer.append(&mut string);
        self
    }
}

/// create a ping request
///
/// # Example
/// ```
/// # use rpcperf_request::thrift::*;
///
/// assert_eq!(ping(), [0, 0, 0, 17, 128, 1, 0, 1, 0, 0, 0, 4, 112, 105, 110, 103, 0, 0, 0, 0, 0]);
pub fn ping() -> Vec<u8> {
    let mut buffer = Buffer::new();
    buffer.protocol_header();
    buffer.method_name("ping".to_owned());
    buffer.sequence_id(0);
    buffer.stop();
    buffer.frame();
    buffer.buffer()
}
<commit_msg>Reduce copies in thrift buffer system<commit_after>//  rpc-perf - RPC Performance Testing
//  Copyright 2015 Twitter, Inc
//
//  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 byteorder;

use byteorder::{ByteOrder, BigEndian, WriteBytesExt};

/// this is work in progress to speak framed binary thrift

#[derive(Clone)]
pub struct Buffer {
    buffer: Vec<u8>,
}

impl Buffer {
    pub fn new() -> Buffer {
        let mut buffer = Vec::<u8>::new();
        buffer.resize(4, 0);

        Buffer { buffer: buffer }
    }

    pub fn into_vec(self) -> Vec<u8> {
        self.buffer
    }

    /// add protocol version to buffer
    ///
    /// # Example
    /// ```
    /// # use rpcperf_request::thrift::*;
    ///
    // let mut buffer = Vec::<u8>::new();
    // protocol_header(&mut buffer);
    // let expected = vec![128, 1, 0, 1];
    // assert_eq!(buffer, expected);
    pub fn protocol_header(&mut self) -> &Self {
        self.buffer.extend_from_slice(&[128, 1, 0, 1]);
        self
    }

    /// write the framed length to the buffer
    ///
    /// # Example
    /// ```
    /// # use rpcperf_request::thrift::*;
    ///
    /// let mut b = Buffer::new();
    /// b.sequence_id(0_i32);
    /// b.frame();
    /// let expected = vec![0, 0, 0, 4, 0, 0, 0, 0];
    /// assert_eq!(b.into_vec(), expected);
    #[inline]
    pub fn frame(&mut self) -> &Self {
        let bytes = self.buffer.len() - 4;
        BigEndian::write_i32(&mut self.buffer[..4], bytes as i32);
        self
    }

    /// add method name to buffer
    ///
    /// # Example
    /// ```
    /// # use rpcperf_request::thrift::Buffer;
    ///
    /// let mut b = Buffer::new();
    /// b.method_name("ping");
    /// let expected = vec![0, 0, 0, 0, 0, 0, 0, 4, 112, 105, 110, 103];
    /// assert_eq!(b.into_vec(), expected);
    #[inline]
    pub fn method_name(&mut self, method: &str) -> &Self {
        self.write_str(method)
    }

    /// add sequence id to buffer
    ///
    /// # Example
    /// ```
    /// # use rpcperf_request::thrift::Buffer;
    ///
    /// let mut b = Buffer::new();
    /// b.sequence_id(0_i32);
    /// let expected = vec![0, 0, 0, 0, 0, 0, 0, 0];
    /// assert_eq!(b.into_vec(), expected);
    #[inline]
    pub fn sequence_id(&mut self, id: i32) -> &Self {
        self.write_i32(id as i32)
    }

    /// add stop sequence to buffer
    ///
    /// # Example
    /// ```
    /// # use rpcperf_request::thrift::Buffer;
    ///
    /// let mut b = Buffer::new();
    /// b.stop();
    /// let expected = vec![0, 0, 0, 0, 0];
    /// assert_eq!(b.into_vec(), expected);
    pub fn stop(&mut self) -> &Self {
        self.write_bytes(&[0])
    }

    #[inline]
    fn write_i32(&mut self, value: i32) -> &Self {
        let _ = self.buffer.write_i32::<BigEndian>(value).unwrap();
        self
    }

    #[inline]
    fn write_bytes(&mut self, bytes: &[u8]) -> &Self {
        self.buffer.extend_from_slice(bytes);
        self
    }

    #[inline]
    fn write_str(&mut self, string: &str) -> &Self {
        let string = string.as_bytes();
        self.write_i32(string.len() as i32);
        self.buffer.extend_from_slice(string);
        self
    }
}

/// create a ping request
///
/// # Example
/// ```
/// # use rpcperf_request::thrift::*;
///
/// assert_eq!(ping(), [0, 0, 0, 17, 128, 1, 0, 1, 0, 0, 0, 4, 112, 105, 110, 103, 0, 0, 0, 0, 0]);
pub fn ping() -> Vec<u8> {
    let mut buffer = Buffer::new();
    buffer.protocol_header();
    buffer.method_name("ping");
    buffer.sequence_id(0);
    buffer.stop();
    buffer.frame();
    buffer.into_vec()
}
<|endoftext|>


<commit_before>#[derive(Debug, Default)]
pub struct RegConfig {
    // EP
    data_transfer_pattern: DataTransferPattern,

    // BE
    endianness: Endianness,

    cu: bool,
    kseg0_cache_enabled: bool
}

impl From<u32> for RegConfig {
    fn from(value: u32) -> Self {
        RegConfig {
            data_transfer_pattern: value.into(),

            endianness: value.into(),

            cu: (value & (1 << 3)) != 0,
            kseg0_cache_enabled: value & 0b111 != 0b010
        }
    }
}

#[derive(Debug)]
enum DataTransferPattern {
    Normal, // D
    DxxDxx
}

impl Default for DataTransferPattern {
    fn default() -> Self {
        DataTransferPattern::Normal
    }
}

impl From<u32> for DataTransferPattern {
    fn from(value: u32) -> Self {
        match (value >> 24) & 0b1111 {
            0 => DataTransferPattern::Normal,
            6 => DataTransferPattern::DxxDxx,
            _ => panic!("Invalid data transfer pattern (EP): {:#x}", value)
        }
    }
}

#[derive(Debug)]
enum Endianness {
    Little,
    Big
}

impl Default for Endianness {
    fn default() -> Self {
        Endianness::Big
    }
}

impl From<u32> for Endianness {
    fn from(value: u32) -> Self {
        match (value >> 15) & 0b1 {
            0 => Endianness::Little,
            1 => Endianness::Big,
            _ => unreachable!()
        }
    }
}
<commit_msg>Explicitly modeled kseg0_cache bits<commit_after>#[derive(Debug, Default)]
pub struct RegConfig {
    // EP
    data_transfer_pattern: DataTransferPattern,

    // BE
    endianness: Endianness,

    cu: bool,
    kseg0_cache_bits: [bool;3],
    kseg0_cache_enabled: bool
}

impl From<u32> for RegConfig {
    fn from(value: u32) -> Self {
        RegConfig {
            data_transfer_pattern: value.into(),

            endianness: value.into(),

            cu: (value & (1 << 3)) != 0,
            kseg0_cache_bits: [
                (value & (1 << 0)) != 0,
                (value & (1 << 1)) != 0,
                (value & (1 << 2)) != 0,
            ],
            // TODO: Extract to method?
            kseg0_cache_enabled: value & 0b111 != 0b010
        }
    }
}

#[derive(Debug)]
enum DataTransferPattern {
    Normal, // D
    DxxDxx
}

impl Default for DataTransferPattern {
    fn default() -> Self {
        DataTransferPattern::Normal
    }
}

impl From<u32> for DataTransferPattern {
    fn from(value: u32) -> Self {
        match (value >> 24) & 0b1111 {
            0 => DataTransferPattern::Normal,
            6 => DataTransferPattern::DxxDxx,
            _ => panic!("Invalid data transfer pattern (EP): {:#x}", value)
        }
    }
}

#[derive(Debug)]
enum Endianness {
    Little,
    Big
}

impl Default for Endianness {
    fn default() -> Self {
        Endianness::Big
    }
}

impl From<u32> for Endianness {
    fn from(value: u32) -> Self {
        match (value >> 15) & 0b1 {
            0 => Endianness::Little,
            1 => Endianness::Big,
            _ => unreachable!()
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::iter::Iterator;
use std::ops::Bound::{Excluded, Unbounded};
use std::vec::Vec;

use rand::{seq::SliceRandom, thread_rng, Rng};
use test::{black_box, Bencher};

macro_rules! map_insert_rand_bench {
    ($name: ident, $n: expr, $map: ident) => {
        #[bench]
        pub fn $name(b: &mut Bencher) {
            let n: usize = $n;
            let mut map = $map::new();
            // setup
            let mut rng = thread_rng();

            for _ in 0..n {
                let i = rng.gen::<usize>() % n;
                map.insert(i, i);
            }

            // measure
            b.iter(|| {
                let k = rng.gen::<usize>() % n;
                map.insert(k, k);
                map.remove(&k);
            });
            black_box(map);
        }
    };
}

macro_rules! map_insert_seq_bench {
    ($name: ident, $n: expr, $map: ident) => {
        #[bench]
        pub fn $name(b: &mut Bencher) {
            let mut map = $map::new();
            let n: usize = $n;
            // setup
            for i in 0..n {
                map.insert(i * 2, i * 2);
            }

            // measure
            let mut i = 1;
            b.iter(|| {
                map.insert(i, i);
                map.remove(&i);
                i = (i + 2) % n;
            });
            black_box(map);
        }
    };
}

macro_rules! map_find_rand_bench {
    ($name: ident, $n: expr, $map: ident) => {
        #[bench]
        pub fn $name(b: &mut Bencher) {
            let mut map = $map::new();
            let n: usize = $n;

            // setup
            let mut rng = thread_rng();
            let mut keys: Vec<_> = (0..n).map(|_| rng.gen::<usize>() % n).collect();

            for &k in &keys {
                map.insert(k, k);
            }

            keys.shuffle(&mut rng);

            // measure
            let mut i = 0;
            b.iter(|| {
                let t = map.get(&keys[i]);
                i = (i + 1) % n;
                black_box(t);
            })
        }
    };
}

macro_rules! map_find_seq_bench {
    ($name: ident, $n: expr, $map: ident) => {
        #[bench]
        pub fn $name(b: &mut Bencher) {
            let mut map = $map::new();
            let n: usize = $n;

            // setup
            for i in 0..n {
                map.insert(i, i);
            }

            // measure
            let mut i = 0;
            b.iter(|| {
                let x = map.get(&i);
                i = (i + 1) % n;
                black_box(x);
            })
        }
    };
}

map_insert_rand_bench! {insert_rand_100,    100,    BTreeMap}
map_insert_rand_bench! {insert_rand_10_000, 10_000, BTreeMap}

map_insert_seq_bench! {insert_seq_100,    100,    BTreeMap}
map_insert_seq_bench! {insert_seq_10_000, 10_000, BTreeMap}

map_find_rand_bench! {find_rand_100,    100,    BTreeMap}
map_find_rand_bench! {find_rand_10_000, 10_000, BTreeMap}

map_find_seq_bench! {find_seq_100,    100,    BTreeMap}
map_find_seq_bench! {find_seq_10_000, 10_000, BTreeMap}

fn bench_iter(b: &mut Bencher, size: i32) {
    let mut map = BTreeMap::<i32, i32>::new();
    let mut rng = thread_rng();

    for _ in 0..size {
        map.insert(rng.gen(), rng.gen());
    }

    b.iter(|| {
        for entry in &map {
            black_box(entry);
        }
    });
}

#[bench]
pub fn iter_20(b: &mut Bencher) {
    bench_iter(b, 20);
}

#[bench]
pub fn iter_1000(b: &mut Bencher) {
    bench_iter(b, 1000);
}

#[bench]
pub fn iter_100000(b: &mut Bencher) {
    bench_iter(b, 100000);
}

fn bench_iter_mut(b: &mut Bencher, size: i32) {
    let mut map = BTreeMap::<i32, i32>::new();
    let mut rng = thread_rng();

    for _ in 0..size {
        map.insert(rng.gen(), rng.gen());
    }

    b.iter(|| {
        for kv in map.iter_mut() {
            black_box(kv);
        }
    });
}

#[bench]
pub fn iter_mut_20(b: &mut Bencher) {
    bench_iter_mut(b, 20);
}

#[bench]
pub fn iter_mut_1000(b: &mut Bencher) {
    bench_iter_mut(b, 1000);
}

#[bench]
pub fn iter_mut_100000(b: &mut Bencher) {
    bench_iter_mut(b, 100000);
}

fn bench_first_and_last(b: &mut Bencher, size: i32) {
    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
    b.iter(|| {
        for _ in 0..10 {
            black_box(map.first_key_value());
            black_box(map.last_key_value());
        }
    });
}

#[bench]
pub fn first_and_last_0(b: &mut Bencher) {
    bench_first_and_last(b, 0);
}

#[bench]
pub fn first_and_last_100(b: &mut Bencher) {
    bench_first_and_last(b, 100);
}

#[bench]
pub fn first_and_last_10k(b: &mut Bencher) {
    bench_first_and_last(b, 10_000);
}

#[bench]
pub fn range_excluded_excluded(b: &mut Bencher) {
    let size = 144;
    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
    b.iter(|| {
        for first in 0..size {
            for last in first + 1..size {
                black_box(map.range((Excluded(first), Excluded(last))));
            }
        }
    });
}

#[bench]
pub fn range_excluded_unbounded(b: &mut Bencher) {
    let size = 144;
    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
    b.iter(|| {
        for first in 0..size {
            black_box(map.range((Excluded(first), Unbounded)));
        }
    });
}

#[bench]
pub fn range_included_included(b: &mut Bencher) {
    let size = 144;
    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
    b.iter(|| {
        for first in 0..size {
            for last in first..size {
                black_box(map.range(first..=last));
            }
        }
    });
}

#[bench]
pub fn range_included_unbounded(b: &mut Bencher) {
    let size = 144;
    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
    b.iter(|| {
        for first in 0..size {
            black_box(map.range(first..));
        }
    });
}

#[bench]
pub fn range_unbounded_unbounded(b: &mut Bencher) {
    let size = 144;
    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
    b.iter(|| map.range(..));
}
<commit_msg>Introduce BTreeMap benches of iter itself<commit_after>use std::collections::BTreeMap;
use std::iter::Iterator;
use std::ops::RangeBounds;
use std::vec::Vec;

use rand::{seq::SliceRandom, thread_rng, Rng};
use test::{black_box, Bencher};

macro_rules! map_insert_rand_bench {
    ($name: ident, $n: expr, $map: ident) => {
        #[bench]
        pub fn $name(b: &mut Bencher) {
            let n: usize = $n;
            let mut map = $map::new();
            // setup
            let mut rng = thread_rng();

            for _ in 0..n {
                let i = rng.gen::<usize>() % n;
                map.insert(i, i);
            }

            // measure
            b.iter(|| {
                let k = rng.gen::<usize>() % n;
                map.insert(k, k);
                map.remove(&k);
            });
            black_box(map);
        }
    };
}

macro_rules! map_insert_seq_bench {
    ($name: ident, $n: expr, $map: ident) => {
        #[bench]
        pub fn $name(b: &mut Bencher) {
            let mut map = $map::new();
            let n: usize = $n;
            // setup
            for i in 0..n {
                map.insert(i * 2, i * 2);
            }

            // measure
            let mut i = 1;
            b.iter(|| {
                map.insert(i, i);
                map.remove(&i);
                i = (i + 2) % n;
            });
            black_box(map);
        }
    };
}

macro_rules! map_find_rand_bench {
    ($name: ident, $n: expr, $map: ident) => {
        #[bench]
        pub fn $name(b: &mut Bencher) {
            let mut map = $map::new();
            let n: usize = $n;

            // setup
            let mut rng = thread_rng();
            let mut keys: Vec<_> = (0..n).map(|_| rng.gen::<usize>() % n).collect();

            for &k in &keys {
                map.insert(k, k);
            }

            keys.shuffle(&mut rng);

            // measure
            let mut i = 0;
            b.iter(|| {
                let t = map.get(&keys[i]);
                i = (i + 1) % n;
                black_box(t);
            })
        }
    };
}

macro_rules! map_find_seq_bench {
    ($name: ident, $n: expr, $map: ident) => {
        #[bench]
        pub fn $name(b: &mut Bencher) {
            let mut map = $map::new();
            let n: usize = $n;

            // setup
            for i in 0..n {
                map.insert(i, i);
            }

            // measure
            let mut i = 0;
            b.iter(|| {
                let x = map.get(&i);
                i = (i + 1) % n;
                black_box(x);
            })
        }
    };
}

map_insert_rand_bench! {insert_rand_100,    100,    BTreeMap}
map_insert_rand_bench! {insert_rand_10_000, 10_000, BTreeMap}

map_insert_seq_bench! {insert_seq_100,    100,    BTreeMap}
map_insert_seq_bench! {insert_seq_10_000, 10_000, BTreeMap}

map_find_rand_bench! {find_rand_100,    100,    BTreeMap}
map_find_rand_bench! {find_rand_10_000, 10_000, BTreeMap}

map_find_seq_bench! {find_seq_100,    100,    BTreeMap}
map_find_seq_bench! {find_seq_10_000, 10_000, BTreeMap}

fn bench_iteration(b: &mut Bencher, size: i32) {
    let mut map = BTreeMap::<i32, i32>::new();
    let mut rng = thread_rng();

    for _ in 0..size {
        map.insert(rng.gen(), rng.gen());
    }

    b.iter(|| {
        for entry in &map {
            black_box(entry);
        }
    });
}

#[bench]
pub fn iteration_20(b: &mut Bencher) {
    bench_iteration(b, 20);
}

#[bench]
pub fn iteration_1000(b: &mut Bencher) {
    bench_iteration(b, 1000);
}

#[bench]
pub fn iteration_100000(b: &mut Bencher) {
    bench_iteration(b, 100000);
}

fn bench_iteration_mut(b: &mut Bencher, size: i32) {
    let mut map = BTreeMap::<i32, i32>::new();
    let mut rng = thread_rng();

    for _ in 0..size {
        map.insert(rng.gen(), rng.gen());
    }

    b.iter(|| {
        for kv in map.iter_mut() {
            black_box(kv);
        }
    });
}

#[bench]
pub fn iteration_mut_20(b: &mut Bencher) {
    bench_iteration_mut(b, 20);
}

#[bench]
pub fn iteration_mut_1000(b: &mut Bencher) {
    bench_iteration_mut(b, 1000);
}

#[bench]
pub fn iteration_mut_100000(b: &mut Bencher) {
    bench_iteration_mut(b, 100000);
}

fn bench_first_and_last(b: &mut Bencher, size: i32) {
    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
    b.iter(|| {
        for _ in 0..10 {
            black_box(map.first_key_value());
            black_box(map.last_key_value());
        }
    });
}

#[bench]
pub fn first_and_last_0(b: &mut Bencher) {
    bench_first_and_last(b, 0);
}

#[bench]
pub fn first_and_last_100(b: &mut Bencher) {
    bench_first_and_last(b, 100);
}

#[bench]
pub fn first_and_last_10k(b: &mut Bencher) {
    bench_first_and_last(b, 10_000);
}

const BENCH_RANGE_SIZE: i32 = 145;
const BENCH_RANGE_COUNT: i32 = BENCH_RANGE_SIZE * (BENCH_RANGE_SIZE - 1) / 2;

fn bench_range<F, R>(b: &mut Bencher, f: F)
where
    F: Fn(i32, i32) -> R,
    R: RangeBounds<i32>,
{
    let map: BTreeMap<_, _> = (0..BENCH_RANGE_SIZE).map(|i| (i, i)).collect();
    b.iter(|| {
        let mut c = 0;
        for i in 0..BENCH_RANGE_SIZE {
            for j in i + 1..BENCH_RANGE_SIZE {
                black_box(map.range(f(i, j)));
                c += 1;
            }
        }
        debug_assert_eq!(c, BENCH_RANGE_COUNT);
    });
}

#[bench]
pub fn range_included_excluded(b: &mut Bencher) {
    bench_range(b, |i, j| i..j);
}

#[bench]
pub fn range_included_included(b: &mut Bencher) {
    bench_range(b, |i, j| i..=j);
}

#[bench]
pub fn range_included_unbounded(b: &mut Bencher) {
    bench_range(b, |i, _| i..);
}

#[bench]
pub fn range_unbounded_unbounded(b: &mut Bencher) {
    bench_range(b, |_, _| ..);
}

fn bench_iter(b: &mut Bencher, repeats: i32, size: i32) {
    let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect();
    b.iter(|| {
        for _ in 0..repeats {
            black_box(map.iter());
        }
    });
}

/// Contrast range_unbounded_unbounded with `iter()`.
#[bench]
pub fn range_unbounded_vs_iter(b: &mut Bencher) {
    bench_iter(b, BENCH_RANGE_COUNT, BENCH_RANGE_SIZE);
}

#[bench]
pub fn iter_0(b: &mut Bencher) {
    bench_iter(b, 1_000, 0);
}

#[bench]
pub fn iter_1(b: &mut Bencher) {
    bench_iter(b, 1_000, 1);
}

#[bench]
pub fn iter_100(b: &mut Bencher) {
    bench_iter(b, 1_000, 100);
}

#[bench]
pub fn iter_10k(b: &mut Bencher) {
    bench_iter(b, 1_000, 10_000);
}

#[bench]
pub fn iter_1m(b: &mut Bencher) {
    bench_iter(b, 1_000, 1_000_000);
}
<|endoftext|>