<commit_before>extern crate llvm_sys;

use std::collections::HashMap;
use std::ffi::CString;
use self::llvm_sys::core::*;
use self::llvm_sys::analysis::*;
use self::llvm_sys::execution_engine::*;
use self::llvm_sys::prelude::*;
//use self::llvm_sys::target::*;
use syntax::ast::op::*;
use syntax::ast::expr::*;
use syntax::ast::literals::*;

// Struct to keep track of data needed to build IR
pub struct Context {
    context: LLVMContextRef,
    module: LLVMModuleRef,
    builder: LLVMBuilderRef,
    execution_engine: LLVMExecutionEngineRef,
    named_values: HashMap<String, LLVMValueRef>,
}

impl Context {
    #![allow(unused_mut)]
    #![allow(unused_variables)]
    pub unsafe fn new(module_name: &str) -> Context {
        // Needed for codegen but not available until llvm-sys 0.11
        // which isn't available atm over crates due to a renaming problem..
        // LLVM_InitializeNativeTarget();
        // LLVM_InitializeNativeTargetAsmPrinter();
        // LLVM_InitializeNativeTargetAsmParser();

        let context = LLVMContextCreate();
        let module = LLVMModuleCreateWithNameInContext(c_str_ptr(module_name), context);
        let builder = LLVMCreateBuilderInContext(context);
        let named_values = HashMap::new();
        let mut execution_engine = 0 as LLVMExecutionEngineRef;
        let mut error_msg = 0 as *mut i8;

        // LLVMCreateExecutionEngineForModule(&mut execution_engine, module, &mut error_msg);
        // assert!(execution_engine != 0 as LLVMExecutionEngineRef, "Failed to initialize the execution engine.");

        Context {
            context: context,
            module: module,
            builder: builder,
            execution_engine: execution_engine,
            named_values: named_values,
        }
    }

    // Dump the IR to stdout
    pub unsafe fn dump(&self) {
        LLVMDumpModule(self.module);
    }

    // Verifies that the llvm code is valid. Optionally prints
    // the error message, else abort.
    pub unsafe fn verify(&self) {
        let action = LLVMVerifierFailureAction::LLVMPrintMessageAction;
        let msg = vec![c_str_ptr("")];

        LLVMVerifyModule(self.module, action, msg.as_ptr() as *mut _);
        LLVMDisposeMessage(msg[0] as *mut _);
    }

    pub unsafe fn run(&self) -> u64 {
        let main = LLVMGetNamedFunction(self.module, c_str_ptr("main"));
        let result = LLVMRunFunction(self.execution_engine, main, 0, 0 as *mut LLVMGenericValueRef);

        LLVMGenericValueToInt(result, 1)
    }

    // Struct getters
    pub fn get_context(&self) -> LLVMContextRef {
        self.context
    }

    pub fn get_module(&self) -> LLVMModuleRef {
        self.module
    }

    pub fn get_builder(&self) -> LLVMBuilderRef {
        self.builder
    }

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

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeExecutionEngine(self.execution_engine);
            LLVMDisposeBuilder(self.builder);
            LLVMDisposeModule(self.module);
            LLVMContextDispose(self.context);
        }
    }
}

pub trait CodeGen {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef>;
}

impl CodeGen for ExprWrapper {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef> {
        self.get_expr().gen_code(context)
    }
}

impl CodeGen for Expr {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef> {
        match *self {
            Expr::Block(ref vec) => {
                let mut gen = None;

                for expr in vec {
                    gen = expr.gen_code(context);
                }

                gen
            },
            Expr::Ident(ref name) => {
                match context.named_values.get(name) {
                    Some(val) => Some(*val),
                    None => {
                        println!("Error: Unknown variable named {}", name);

                        None
                    }
                }
            },
            Expr::Literal(ref literal_type) => {
                match literal_type {
                    &Literals::UTF8String(ref val) => {
                        // Types
                        let array_type1 = LLVMArrayType(LLVMInt8TypeInContext(context.get_context()), val.len() as u32);
                        // let string_struct_type = LLVMGetNamedGlobal(context.get_module(), c_str_ptr("struct.string"));
                        // if string_struct_type.is_null() {
                        //     println!("TMP Error: Cannot find builtin string type!");
                        // }
                        let i8_type = LLVMInt8TypeInContext(context.get_context());
                        let i8_ptr_type = LLVMPointerType(i8_type, 0);
                        let i32_type = LLVMInt32TypeInContext(context.get_context());
                        let i64_type = LLVMInt64TypeInContext(context.get_context());
                        // let string_type_fields = vec![LLVMInt32TypeInContext(context.get_context()),
                        //               LLVMPointerType(LLVMInt8TypeInContext(context.get_context()), 0)];

                        // Values
                        let len = LLVMConstInt(i64_type, val.len() as u64, 0);

                        // Make a global string constant and assign the value:
                        let const_str_var = LLVMAddGlobal(context.get_module(), array_type1, c_str_ptr("str"));
                        let mut chars = Vec::new();
                        for chr in val.bytes() {
                            chars.push(LLVMConstInt(i8_type, chr as u64, 0));
                        }

                        let const_str_array = LLVMConstArray(i8_type, chars.as_ptr() as *mut _, chars.len() as u32);
                        LLVMSetInitializer(const_str_var, const_str_array);
                        LLVMSetGlobalConstant(const_str_var, 1);

                        let args = vec![LLVMConstInt(i32_type, 0, 0), LLVMConstInt(i32_type, 0, 0)];
                        let allocated_str_ptr = LLVMBuildAlloca(context.get_builder(), i8_ptr_type, c_str_ptr("a"));
                        let mallocated_ptr = LLVMBuildMalloc(context.get_builder(), i8_type, c_str_ptr("m"));

                        LLVMSetTailCall(mallocated_ptr, 0);
                        LLVMBuildStore(context.get_builder(), mallocated_ptr, allocated_str_ptr);

                        let element_ptr = LLVMBuildGEP(context.get_builder(), const_str_var, args.as_ptr() as *mut _, 2, c_str_ptr(""));
                        LLVMBuildStore(context.get_builder(), element_ptr, allocated_str_ptr);

                        let loaded_ptr = LLVMBuildLoad(context.get_builder(), allocated_str_ptr, c_str_ptr("l"));
                        let struct_fields = vec![LLVMGetUndef(i8_ptr_type), len];
                        let const_struct = LLVMConstStructInContext(context.get_context(), struct_fields.as_ptr() as *mut _, 2, 0);

                        Some(LLVMBuildInsertValue(context.get_builder(), const_struct, loaded_ptr, 0, c_str_ptr("i")))
                    },
                    &Literals::I32Num(ref val) => {
                        let ty = LLVMInt32TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 1))
                    },
                    &Literals::I64Num(ref val) => {
                        let ty = LLVMInt64TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 1))
                    },
                    &Literals::U32Num(ref val) => {
                        let ty = LLVMInt32TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 0))
                    },
                    &Literals::U64Num(ref val) => {
                        let ty = LLVMInt64TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val, 0))
                    },
                    &Literals::F32Num(ref val) => {
                        let ty = LLVMFloatTypeInContext(context.get_context());
                        Some(LLVMConstReal(ty, *val as f64))
                    },
                    &Literals::F64Num(ref val) => {
                        let ty = LLVMDoubleTypeInContext(context.get_context());
                        Some(LLVMConstReal(ty, *val))
                    },
                    &Literals::Bool(ref val) => {
                        let ty = LLVMInt1TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 0))
                    },
                    _ => {
                        println!("Error: Codegen unimplemented for {:?}", literal_type);
                        None
                    }
                }
            },
            Expr::FnCall(ref name, ref args) => {
                let function = LLVMGetNamedFunction(context.module, c_str_ptr(name));

                if function.is_null() {
                    // TODO: Add standardized error message writing?
                    println!("Error: Function {} not found.", name);
                    return None;
                }

                let arg_count = LLVMCountParams(function) as usize;

                if arg_count != args.len() {
                    println!("Error: Function {} requires {} argument(s), {} given.", name, arg_count, args.len());
                    return None;
                }

                let mut arg_values = Vec::new();

                for arg in args {
                    match arg.gen_code(context) {
                        Some(value) => arg_values.push(value),
                        None => {
                            println!("Fatal Error: Argument {:?} codegen failed!", arg);
                            return None
                        }
                    }
                }

                // Void functions don't get saved return values
                let ret_var = if LLVMGetReturnType(LLVMGetElementType(LLVMTypeOf(function))) == LLVMVoidTypeInContext(context.context) {
                    c_str_ptr("")
                } else {
                    let mut tmp = name.to_string();
                    tmp.push_str("tmp");

                    c_str_ptr(&tmp)
                };

                Some(LLVMBuildCall(context.builder, function, arg_values.as_ptr() as *mut _, arg_values.len() as u32, ret_var))
            },
            Expr::UnaryOp(ref op, ref expr) => {
                match *op {
                    // I think Negate would be easier to handle by replacing it with multiply * -1 in the parser
                    UnaryOp::Negate => panic!("Codegen error: Negation not supported in codegen."),
                    UnaryOp::Not => match expr.gen_code(context) {
                        Some(val) => Some(LLVMBuildNot(context.get_builder(), val, c_str_ptr("nottmp"))),
                        None => None
                    }
                }
            },
            // Expr::VarDecl(ref const_bool, ref typ, ref name, ref expr) => {
            //     panic!("Codegen error: unimplemented variable declaration");
            // },
            Expr::NoOp => None,
            _ => None
        }
    }
}

// Helper function
pub fn c_str_ptr(rust_str: &str) -> *const i8 {
    match CString::new(rust_str.as_bytes()) {
        Ok(string) => string,
        Err(err) => panic!(err)
    }.as_ptr()
}
<commit_msg>Added LLVM initializing functions for codegen.<commit_after>extern crate llvm_sys;

use std::collections::HashMap;
use std::ffi::CString;
use self::llvm_sys::core::*;
use self::llvm_sys::analysis::*;
use self::llvm_sys::execution_engine::*;
use self::llvm_sys::prelude::*;
use self::llvm_sys::target::*;
use syntax::ast::op::*;
use syntax::ast::expr::*;
use syntax::ast::literals::*;

// Struct to keep track of data needed to build IR
pub struct Context {
    context: LLVMContextRef,
    module: LLVMModuleRef,
    builder: LLVMBuilderRef,
    execution_engine: LLVMExecutionEngineRef,
    named_values: HashMap<String, LLVMValueRef>,
}

impl Context {
    #![allow(unused_mut)]
    #![allow(unused_variables)]
    pub unsafe fn new(module_name: &str) -> Context {
        LLVM_InitializeNativeTarget();
        LLVM_InitializeNativeAsmPrinter();
        LLVM_InitializeNativeAsmParser();

        let context = LLVMContextCreate();
        let module = LLVMModuleCreateWithNameInContext(c_str_ptr(module_name), context);
        let builder = LLVMCreateBuilderInContext(context);
        let named_values = HashMap::new();
        let mut execution_engine = 0 as LLVMExecutionEngineRef;
        let mut error_msg = 0 as *mut i8;

        // LLVMCreateExecutionEngineForModule(&mut execution_engine, module, &mut error_msg);
        // assert!(execution_engine != 0 as LLVMExecutionEngineRef, "Failed to initialize the execution engine.");

        Context {
            context: context,
            module: module,
            builder: builder,
            execution_engine: execution_engine,
            named_values: named_values,
        }
    }

    // Dump the IR to stdout
    pub unsafe fn dump(&self) {
        LLVMDumpModule(self.module);
    }

    // Verifies that the llvm code is valid. Optionally prints
    // the error message, else abort.
    pub unsafe fn verify(&self) {
        let action = LLVMVerifierFailureAction::LLVMPrintMessageAction;
        let msg = vec![c_str_ptr("")];

        LLVMVerifyModule(self.module, action, msg.as_ptr() as *mut _);
        LLVMDisposeMessage(msg[0] as *mut _);
    }

    pub unsafe fn run(&self) -> u64 {
        let main = LLVMGetNamedFunction(self.module, c_str_ptr("main"));
        let result = LLVMRunFunction(self.execution_engine, main, 0, 0 as *mut LLVMGenericValueRef);

        LLVMGenericValueToInt(result, 1)
    }

    // Struct getters
    pub fn get_context(&self) -> LLVMContextRef {
        self.context
    }

    pub fn get_module(&self) -> LLVMModuleRef {
        self.module
    }

    pub fn get_builder(&self) -> LLVMBuilderRef {
        self.builder
    }

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

impl Drop for Context {
    fn drop(&mut self) {
        unsafe {
            LLVMDisposeExecutionEngine(self.execution_engine);
            LLVMDisposeBuilder(self.builder);
            LLVMDisposeModule(self.module);
            LLVMContextDispose(self.context);
        }
    }
}

pub trait CodeGen {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef>;
}

impl CodeGen for ExprWrapper {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef> {
        self.get_expr().gen_code(context)
    }
}

impl CodeGen for Expr {
    unsafe fn gen_code(&self, context: &mut Context) -> Option<LLVMValueRef> {
        match *self {
            Expr::Block(ref vec) => {
                let mut gen = None;

                for expr in vec {
                    gen = expr.gen_code(context);
                }

                gen
            },
            Expr::Ident(ref name) => {
                match context.named_values.get(name) {
                    Some(val) => Some(*val),
                    None => {
                        println!("Error: Unknown variable named {}", name);

                        None
                    }
                }
            },
            Expr::Literal(ref literal_type) => {
                match literal_type {
                    &Literals::UTF8String(ref val) => {
                        // Types
                        let array_type1 = LLVMArrayType(LLVMInt8TypeInContext(context.get_context()), val.len() as u32);
                        // let string_struct_type = LLVMGetNamedGlobal(context.get_module(), c_str_ptr("struct.string"));
                        // if string_struct_type.is_null() {
                        //     println!("TMP Error: Cannot find builtin string type!");
                        // }
                        let i8_type = LLVMInt8TypeInContext(context.get_context());
                        let i8_ptr_type = LLVMPointerType(i8_type, 0);
                        let i32_type = LLVMInt32TypeInContext(context.get_context());
                        let i64_type = LLVMInt64TypeInContext(context.get_context());
                        // let string_type_fields = vec![LLVMInt32TypeInContext(context.get_context()),
                        //               LLVMPointerType(LLVMInt8TypeInContext(context.get_context()), 0)];

                        // Values
                        let len = LLVMConstInt(i64_type, val.len() as u64, 0);

                        // Make a global string constant and assign the value:
                        let const_str_var = LLVMAddGlobal(context.get_module(), array_type1, c_str_ptr("str"));
                        let mut chars = Vec::new();
                        for chr in val.bytes() {
                            chars.push(LLVMConstInt(i8_type, chr as u64, 0));
                        }

                        let const_str_array = LLVMConstArray(i8_type, chars.as_ptr() as *mut _, chars.len() as u32);
                        LLVMSetInitializer(const_str_var, const_str_array);
                        LLVMSetGlobalConstant(const_str_var, 1);

                        let args = vec![LLVMConstInt(i32_type, 0, 0), LLVMConstInt(i32_type, 0, 0)];
                        let allocated_str_ptr = LLVMBuildAlloca(context.get_builder(), i8_ptr_type, c_str_ptr("a"));
                        let mallocated_ptr = LLVMBuildMalloc(context.get_builder(), i8_type, c_str_ptr("m"));

                        LLVMSetTailCall(mallocated_ptr, 0);
                        LLVMBuildStore(context.get_builder(), mallocated_ptr, allocated_str_ptr);

                        let element_ptr = LLVMBuildGEP(context.get_builder(), const_str_var, args.as_ptr() as *mut _, 2, c_str_ptr(""));
                        LLVMBuildStore(context.get_builder(), element_ptr, allocated_str_ptr);

                        let loaded_ptr = LLVMBuildLoad(context.get_builder(), allocated_str_ptr, c_str_ptr("l"));
                        let struct_fields = vec![LLVMGetUndef(i8_ptr_type), len];
                        let const_struct = LLVMConstStructInContext(context.get_context(), struct_fields.as_ptr() as *mut _, 2, 0);

                        Some(LLVMBuildInsertValue(context.get_builder(), const_struct, loaded_ptr, 0, c_str_ptr("i")))
                    },
                    &Literals::I32Num(ref val) => {
                        let ty = LLVMInt32TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 1))
                    },
                    &Literals::I64Num(ref val) => {
                        let ty = LLVMInt64TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 1))
                    },
                    &Literals::U32Num(ref val) => {
                        let ty = LLVMInt32TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 0))
                    },
                    &Literals::U64Num(ref val) => {
                        let ty = LLVMInt64TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val, 0))
                    },
                    &Literals::F32Num(ref val) => {
                        let ty = LLVMFloatTypeInContext(context.get_context());
                        Some(LLVMConstReal(ty, *val as f64))
                    },
                    &Literals::F64Num(ref val) => {
                        let ty = LLVMDoubleTypeInContext(context.get_context());
                        Some(LLVMConstReal(ty, *val))
                    },
                    &Literals::Bool(ref val) => {
                        let ty = LLVMInt1TypeInContext(context.get_context());
                        Some(LLVMConstInt(ty, *val as u64, 0))
                    },
                    _ => {
                        println!("Error: Codegen unimplemented for {:?}", literal_type);
                        None
                    }
                }
            },
            Expr::FnCall(ref name, ref args) => {
                let function = LLVMGetNamedFunction(context.module, c_str_ptr(name));

                if function.is_null() {
                    // TODO: Add standardized error message writing?
                    println!("Error: Function {} not found.", name);
                    return None;
                }

                let arg_count = LLVMCountParams(function) as usize;

                if arg_count != args.len() {
                    println!("Error: Function {} requires {} argument(s), {} given.", name, arg_count, args.len());
                    return None;
                }

                let mut arg_values = Vec::new();

                for arg in args {
                    match arg.gen_code(context) {
                        Some(value) => arg_values.push(value),
                        None => {
                            println!("Fatal Error: Argument {:?} codegen failed!", arg);
                            return None
                        }
                    }
                }

                // Void functions don't get saved return values
                let ret_var = if LLVMGetReturnType(LLVMGetElementType(LLVMTypeOf(function))) == LLVMVoidTypeInContext(context.context) {
                    c_str_ptr("")
                } else {
                    let mut tmp = name.to_string();
                    tmp.push_str("tmp");

                    c_str_ptr(&tmp)
                };

                Some(LLVMBuildCall(context.builder, function, arg_values.as_ptr() as *mut _, arg_values.len() as u32, ret_var))
            },
            Expr::UnaryOp(ref op, ref expr) => {
                match *op {
                    // I think Negate would be easier to handle by replacing it with multiply * -1 in the parser
                    UnaryOp::Negate => panic!("Codegen error: Negation not supported in codegen."),
                    UnaryOp::Not => match expr.gen_code(context) {
                        Some(val) => Some(LLVMBuildNot(context.get_builder(), val, c_str_ptr("nottmp"))),
                        None => None
                    }
                }
            },
            // Expr::VarDecl(ref const_bool, ref typ, ref name, ref expr) => {
            //     panic!("Codegen error: unimplemented variable declaration");
            // },
            Expr::NoOp => None,
            _ => None
        }
    }
}

// Helper function
pub fn c_str_ptr(rust_str: &str) -> *const i8 {
    match CString::new(rust_str.as_bytes()) {
        Ok(string) => string,
        Err(err) => panic!(err)
    }.as_ptr()
}
<|endoftext|>


<commit_before>///! This binary aims to make it simple to test a template locally: it serves the assets and the
///! template from the local directory, and receives the PDF from the callback endpoint.

extern crate futures;
extern crate papers;
extern crate tokio_core;
extern crate tera;
#[macro_use]
extern crate serde_json as json;

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

use papers::prelude::*;

fn render(document_spec: DocumentSpec) {
    let DocumentSpec { variables, .. } = document_spec;
    let template_string = ::std::fs::File::open("template.tex.tera")
        .expect("could not open template.tex.tera")
        .bytes()
        .collect::<Result<Vec<u8>, _>>()
        .unwrap();
    let template_string = String::from_utf8(template_string).unwrap();
    let rendered_template = tera::Tera::one_off(&template_string, &variables, false)
        .expect("failed to render the template");
    let mut rendered_template_file =
        ::std::fs::File::create("rendered.tex").expect("could not create rendered.tex");
    rendered_template_file
        .write_all(rendered_template.as_bytes())
        .unwrap();
    let output = ::std::process::Command::new("xelatex")
        .arg("-interaction=nonstopmode")
        .arg("-file-line-error")
        .arg("-shell-restricted")
        .arg("rendered.tex")
        .output()
        .expect("latex error")
        .stdout;
    println!("{}", String::from_utf8(output).unwrap());
}

fn main() {
    let variables: json::Value = if let Ok(file) = File::open("variables.json") {
        let bytes: Vec<u8> = file.bytes().collect::<Result<Vec<u8>, _>>().unwrap();
        json::from_slice(&bytes).expect("variables.json is not valid JSON")
    } else {
        json!({})
    };

    let document_spec = DocumentSpec {
        assets_urls: vec![],
        callback_url: PapersUri("unreachable".parse().unwrap()),
        output_filename: "unreachable".to_string(),
        template_url: PapersUri("unreachable".parse().unwrap()),
        variables: variables,
    };

    render(document_spec)
}
<commit_msg>✨ Make papers-local exit with same code as the latex process<commit_after>///! This binary aims to make it simple to test a template locally: it serves the assets and the
///! template from the local directory, and receives the PDF from the callback endpoint.

extern crate papers;
extern crate tera;
#[macro_use]
extern crate serde_json as json;

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

use papers::prelude::*;

fn render(document_spec: DocumentSpec) -> ::std::process::ExitStatus {
    let DocumentSpec { variables, .. } = document_spec;
    let template_string = ::std::fs::File::open("template.tex.tera")
        .expect("could not open template.tex.tera")
        .bytes()
        .collect::<Result<Vec<u8>, _>>()
        .unwrap();
    let template_string = String::from_utf8(template_string).unwrap();
    let rendered_template = tera::Tera::one_off(&template_string, &variables, false)
        .expect("failed to render the template");
    let mut rendered_template_file =
        ::std::fs::File::create("rendered.tex").expect("could not create rendered.tex");
    rendered_template_file
        .write_all(rendered_template.as_bytes())
        .unwrap();
    let outcome = ::std::process::Command::new("xelatex")
        .arg("-interaction=nonstopmode")
        .arg("-file-line-error")
        .arg("-shell-restricted")
        .arg("rendered.tex")
        .output()
        .expect("latex error");
    let output = outcome.stdout;
    println!("{}", String::from_utf8(output).unwrap());
    outcome.status
}

fn main() {
    let variables: json::Value = if let Ok(file) = File::open("variables.json") {
        let bytes: Vec<u8> = file.bytes().collect::<Result<Vec<u8>, _>>().unwrap();
        json::from_slice(&bytes).expect("variables.json is not valid JSON")
    } else {
        json!({})
    };

    let document_spec = DocumentSpec {
        assets_urls: vec![],
        callback_url: PapersUri("unreachable".parse().unwrap()),
        output_filename: "unreachable".to_string(),
        template_url: PapersUri("unreachable".parse().unwrap()),
        variables: variables,
    };

    let exit_status = render(document_spec);
    ::std::process::exit(exit_status.code().unwrap_or(1));
}
<|endoftext|>


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

#[derive(Debug, Clone)]
pub struct Provider {
    pub name: &'static str,
    pub authorize_url: &'static str,
    pub token_url: &'static str,
}

type Providers = HashMap<&'static str, Provider>;

pub fn known_providers() -> Providers {
    let mut providers: Providers = HashMap::with_capacity(3);
    providers.insert("gandi",
                     Provider {
                         name: "Gandi",
                         authorize_url: "https://id.gandi.net/authorize",
                         token_url: "https://id.gandi.net/token",
                     });
    providers.insert("github",
                     Provider {
                         name: "Github",
                         authorize_url: "https://github.com/login/oauth/authorize",
                         token_url: "https://github.com/login/oauth/access_token",
                     });
    providers.insert("google",
                     Provider {
                         name: "Google",
                         authorize_url: "https://accounts.google.com/o/oauth2/v2/auth",
                         token_url: "https://www.googleapis.com/oauth2/v4/token",
                     });
    providers
}

pub fn get_provider(name: &str) -> Option<Provider> {
    let name = name.to_lowercase();
    match known_providers().get(name.as_str()) {
        Some(provider) => Some(provider.clone()),
        None => None,
    }
}<commit_msg>Add tests for provider helpers<commit_after>use std::collections::HashMap;

#[derive(Debug, Clone)]
pub struct Provider {
    pub name: &'static str,
    pub authorize_url: &'static str,
    pub token_url: &'static str,
}

type Providers = HashMap<&'static str, Provider>;

fn known_providers() -> Providers {
    let mut providers: Providers = HashMap::with_capacity(3);
    providers.insert("gandi",
                     Provider {
                         name: "Gandi",
                         authorize_url: "https://id.gandi.net/authorize",
                         token_url: "https://id.gandi.net/token",
                     });
    providers.insert("github",
                     Provider {
                         name: "Github",
                         authorize_url: "https://github.com/login/oauth/authorize",
                         token_url: "https://github.com/login/oauth/access_token",
                     });
    providers.insert("google",
                     Provider {
                         name: "Google",
                         authorize_url: "https://accounts.google.com/o/oauth2/v2/auth",
                         token_url: "https://www.googleapis.com/oauth2/v4/token",
                     });
    providers
}

pub fn get_provider(name: &str) -> Option<Provider> {
    let name = name.to_lowercase();
    match known_providers().get(name.as_str()) {
        Some(provider) => Some(provider.clone()),
        None => None,
    }
}

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

    #[test]
    fn test_get_provier_known_provider() {
        let provider = get_provider("GANDI");
        assert_eq!(provider.is_some(), true);
        let provider = provider.unwrap();
        assert_eq!(provider.name, "Gandi");
    }

    #[test]
    fn test_get_provier_unknown_provider() {
        let provider = get_provider("NXPROVIDER");
        assert_eq!(provider.is_none(), true);
    }

}<|endoftext|>


<commit_before>use std::fmt::Show;
use regex::Regex;
use http::method::Method;
use iron::{Middleware, Request, Response, Status, Continue, Unwind, Error};

pub mod params;
mod glob;

/// `Router` provides an interface for creating complex routes as middleware
/// for the Iron framework.
#[deriving(Clone)]
pub struct Router {
    routes: Vec<Route>
}

struct Route {
    method: Method,
    glob: String,
    matches: Regex,
    handler: Box<Middleware + Send>,
    params: Vec<String>
}

impl Clone for Route {
    fn clone(&self) -> Route {
        Route {
            method: self.method.clone(),
            glob: self.glob.clone(),
            matches: self.matches.clone(),
            handler: self.handler.clone_box(),
            params: self.params.clone()
        }
    }
}

impl Router {
    /// `new` constructs a new, blank `Router`.
    pub fn new() -> Router { Router { routes: Vec::new() } }
    /// Add a new route to a `Router`, matching both a method and glob pattern.
    ///
    /// `route` supports express-style glob patterns: `*` for a single wildcard
    /// segment, `**` for any-number of wildcard segments, and `:param` for
    /// matching storing that segment of the request url in the `Params`
    /// object, which is stored on an Alloy.
    ///
    /// For instance, to route `Get` requests on any route matching
    /// `/users/:userid/:friend` and store `userid` and `friend` in
    /// the exposed Params object:
    ///
    /// ```rust
    /// router.route(
    ///     ::http::method::Get,
    ///     "/users/:userid/:friend".to_string(),
    ///     controller
    /// ```
    ///
    /// The controller provided to route can be any `Middleware`, which allows
    /// extreme flexibility when handling routes. For instance, you could provide
    /// a `Chain`, a `Middleware`, which contains an authorization middleware and
    /// a controller function, so that you can confirm that the request is
    /// authorized for this route before handling it.
    pub fn route<M: Middleware + Send>(&mut self, method: Method, glob: String,
                                       params: Vec<String>, handler: M) {
        self.routes.push(Route {
            method: method,
            glob: glob.clone(),
            matches: glob::deglob(glob),
            handler: box handler,
            params: params
        });
    }
}

impl Middleware for Router {
    fn enter(&mut self, req: &mut Request, res: &mut Response) -> Status {
        let url_path = "/".to_string().append(match req.url.path() {
            Some(paths) => paths.connect("/"),
            None => return Continue
        }.as_slice());

        for route in self.routes.mut_iter() {
            if route.method == req.method && route.matches.is_match(url_path.as_slice()) {
                req.alloy.insert::<params::Params>(
                    params::Params::new(
                        url_path.as_slice(),
                        route.matches.clone(),
                        route.params.clone().move_iter()
                    )
                );
                let mut handler_status = route.handler.enter(req, res);

                match handler_status {
                    Error(ref mut e) => {
                        let error: &mut Show = *e;
                        let _ = route.handler.on_error(req, res, error);
                    },
                    _ => {
                        let _ = route.handler.exit(req, res);
                    }
                };

                return match handler_status {
                    Continue => Unwind,
                    otherwise => otherwise
                }
            }
        }

        Continue
    }
}

<commit_msg>(fix) ignore failing doctest<commit_after>use std::fmt::Show;
use regex::Regex;
use http::method::Method;
use iron::{Middleware, Request, Response, Status, Continue, Unwind, Error};

pub mod params;
mod glob;

/// `Router` provides an interface for creating complex routes as middleware
/// for the Iron framework.
#[deriving(Clone)]
pub struct Router {
    routes: Vec<Route>
}

struct Route {
    method: Method,
    glob: String,
    matches: Regex,
    handler: Box<Middleware + Send>,
    params: Vec<String>
}

impl Clone for Route {
    fn clone(&self) -> Route {
        Route {
            method: self.method.clone(),
            glob: self.glob.clone(),
            matches: self.matches.clone(),
            handler: self.handler.clone_box(),
            params: self.params.clone()
        }
    }
}

impl Router {
    /// `new` constructs a new, blank `Router`.
    pub fn new() -> Router { Router { routes: Vec::new() } }
    /// Add a new route to a `Router`, matching both a method and glob pattern.
    ///
    /// `route` supports express-style glob patterns: `*` for a single wildcard
    /// segment, `**` for any-number of wildcard segments, and `:param` for
    /// matching storing that segment of the request url in the `Params`
    /// object, which is stored on an Alloy.
    ///
    /// For instance, to route `Get` requests on any route matching
    /// `/users/:userid/:friend` and store `userid` and `friend` in
    /// the exposed Params object:
    ///
    /// ```ignore
    /// router.route(
    ///     ::http::method::Get,
    ///     "/users/:userid/:friend".to_string(),
    ///     controller);
    /// ```
    ///
    /// The controller provided to route can be any `Middleware`, which allows
    /// extreme flexibility when handling routes. For instance, you could provide
    /// a `Chain`, a `Middleware`, which contains an authorization middleware and
    /// a controller function, so that you can confirm that the request is
    /// authorized for this route before handling it.
    pub fn route<M: Middleware + Send>(&mut self, method: Method, glob: String,
                                       params: Vec<String>, handler: M) {
        self.routes.push(Route {
            method: method,
            glob: glob.clone(),
            matches: glob::deglob(glob),
            handler: box handler,
            params: params
        });
    }
}

impl Middleware for Router {
    fn enter(&mut self, req: &mut Request, res: &mut Response) -> Status {
        let url_path = "/".to_string().append(match req.url.path() {
            Some(paths) => paths.connect("/"),
            None => return Continue
        }.as_slice());

        for route in self.routes.mut_iter() {
            if route.method == req.method && route.matches.is_match(url_path.as_slice()) {
                req.alloy.insert::<params::Params>(
                    params::Params::new(
                        url_path.as_slice(),
                        route.matches.clone(),
                        route.params.clone().move_iter()
                    )
                );
                let mut handler_status = route.handler.enter(req, res);

                match handler_status {
                    Error(ref mut e) => {
                        let error: &mut Show = *e;
                        let _ = route.handler.on_error(req, res, error);
                    },
                    _ => {
                        let _ = route.handler.exit(req, res);
                    }
                };

                return match handler_status {
                    Continue => Unwind,
                    otherwise => otherwise
                }
            }
        }

        Continue
    }
}

<|endoftext|>


<commit_before>use std::io;
use lamport_sigs::{PrivateKey, PublicKey, LamportSignatureData};
use ring::digest::{Algorithm, Context};
use merkle::{MerkleTree, Proof, Hashable};
use std::io::{Error, ErrorKind};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
/// A wrapper struct around a Lamport public key that implements Hashable.
pub struct MerklePublicKey {
    /// The wrapped Lamport public key.
    pub key: PublicKey,
}

impl MerklePublicKey {
    /// Convenience method to wrap a Lamport `PublicKey` into a `MerklePublicKey`
    pub fn new(pk: PublicKey) -> MerklePublicKey {
        MerklePublicKey{
            key: pk
        }
    }
}

impl Hashable for MerklePublicKey {
    fn update_context(&self, context: &mut Context) {
         context.update(&self.key.to_bytes());
    }
}

impl Into<Vec<u8>> for MerklePublicKey {
    fn into(self) -> Vec<u8> {
        self.key.to_bytes()
    }
}

/// A type alias defining a Merkle signature. That includes both the Lamport leaf signature and inclusion proof.
pub type MerkleSignature = (LamportSignatureData, Proof<MerklePublicKey>);
/// A type alias defining Merkle signed data. That includes the data being signed along with the signature.
pub type MerkleSignedData<T> = (Vec<T>, MerkleSignature);

fn new_err(reason: &str) -> Error {
    Error::new(ErrorKind::Other, format!("A signature could not be produced because {}", reason))
}

/// Signs the entries of the data vector
pub fn sign_data_vec<T>(data: &Vec<T>, algorithm: &'static Algorithm) -> io::Result<Vec<MerkleSignature>>
        where T: AsRef<[u8]> {

    let mut leaf_keys = (0..data.len())
        .map(|_| PrivateKey::new(algorithm))
        .collect::<Vec<_>>();

    debug_assert!(data.len() == leaf_keys.len());

    let leaf_pub_keys = leaf_keys.iter()
        .map(|priv_key| priv_key.public_key())
        .collect::<Vec<_>>();

    let wrapped_leafs = leaf_pub_keys.clone().into_iter().map(|pk| MerklePublicKey::new(pk)).collect::<Vec<_>>();

    let tree = MerkleTree::from_vec(algorithm, wrapped_leafs);

    let proofs_opt = leaf_pub_keys.into_iter()
        .map(|pub_key| tree.gen_proof(MerklePublicKey::new(pub_key)))
        .collect::<Option<Vec<_>>>();

    let signatures_opt = leaf_keys.iter_mut()
        .zip(data.iter())
        .map(|(mut priv_key, data)| priv_key.sign(data.as_ref()))
        .collect::<Result<Vec<_>, _>>();

    match (signatures_opt, proofs_opt) {
        (_, None) =>
            Err(new_err("an issue occured while generating the inclusion proofs.")),

        (Err(err), _) =>
            Err(new_err(&format!("an issue occured while signing the data: {}", err))),

        (Ok(signatures), Some(proofs)) =>
            Ok(signatures.into_iter().zip(proofs).collect())
    }
}

/// Verifies the signature of the data. Returns an error if data couldn't be verified.
pub fn verify_data_vec_signature<T>(data: T, signature: &MerkleSignature, root_hash: &Vec<u8>) -> io::Result<()>
        where T: Into<Vec<u8>> {

    let (ref sig, ref proof) = *signature;

    let valid_root = proof.validate(root_hash);
    let data_vec   = data.into();

    let valid_sig  = proof.value.key.verify_signature(sig, data_vec.as_slice());

    if !valid_root {
        return Err(Error::new(ErrorKind::Other,
                              "The inclusion proof failed to validate."));
    }

    if !valid_sig {
        return Err(Error::new(ErrorKind::Other,
                              "The signature could not be properly verified."));
    }

    Ok(())
}
<commit_msg>Simplify error generation code.<commit_after>use std::io;
use lamport_sigs::{PrivateKey, PublicKey, LamportSignatureData};
use ring::digest::{Algorithm, Context};
use merkle::{MerkleTree, Proof, Hashable};
use std::io::{Error, ErrorKind};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
/// A wrapper struct around a Lamport public key that implements Hashable.
pub struct MerklePublicKey {
    /// The wrapped Lamport public key.
    pub key: PublicKey,
}

impl MerklePublicKey {
    /// Convenience method to wrap a Lamport `PublicKey` into a `MerklePublicKey`
    pub fn new(pk: PublicKey) -> MerklePublicKey {
        MerklePublicKey{
            key: pk
        }
    }
}

impl Hashable for MerklePublicKey {
    fn update_context(&self, context: &mut Context) {
         context.update(&self.key.to_bytes());
    }
}

impl Into<Vec<u8>> for MerklePublicKey {
    fn into(self) -> Vec<u8> {
        self.key.to_bytes()
    }
}

/// A type alias defining a Merkle signature. That includes both the Lamport leaf signature and inclusion proof.
pub type MerkleSignature = (LamportSignatureData, Proof<MerklePublicKey>);

/// A type alias defining Merkle signed data. That includes the data being signed along with the signature.
pub type MerkleSignedData<T> = (Vec<T>, MerkleSignature);

fn signing_error(reason: &str) -> Error {
    Error::new(ErrorKind::Other, format!("A signature could not be produced because {}", reason))
}

/// Signs the entries of the data vector
pub fn sign_data_vec<T>(data: &Vec<T>, algorithm: &'static Algorithm) -> io::Result<Vec<MerkleSignature>>
        where T: AsRef<[u8]> {

    let mut leaf_keys = (0..data.len())
        .map(|_| PrivateKey::new(algorithm))
        .collect::<Vec<_>>();

    debug_assert!(data.len() == leaf_keys.len());

    let leaf_pub_keys = leaf_keys.iter()
        .map(|priv_key| priv_key.public_key())
        .collect::<Vec<_>>();

    let wrapped_leafs = leaf_pub_keys.clone().into_iter()
        .map(|pk| MerklePublicKey::new(pk))
        .collect::<Vec<_>>();

    let tree = MerkleTree::from_vec(algorithm, wrapped_leafs);

    let proofs_opt = leaf_pub_keys.into_iter()
        .map(|pub_key| tree.gen_proof(MerklePublicKey::new(pub_key)))
        .collect::<Option<Vec<_>>>();

    let signatures_opt = leaf_keys.iter_mut()
        .zip(data.iter())
        .map(|(mut priv_key, data)| priv_key.sign(data.as_ref()))
        .collect::<Result<Vec<_>, _>>();

    match (signatures_opt, proofs_opt) {
        (_, None) =>
            Err(signing_error("an issue occured while generating the inclusion proofs.")),

        (Err(err), _) =>
            Err(signing_error(&format!("an issue occured while signing the data: {}", err))),

        (Ok(signatures), Some(proofs)) =>
            Ok(signatures.into_iter().zip(proofs).collect())
    }
}

fn verif_error(reason: &str) -> Error {
    Error::new(ErrorKind::Other, reason)
}

/// Verifies the signature of the data. Returns an error if data couldn't be verified.
pub fn verify_data_vec_signature<T>(data: T, signature: &MerkleSignature, root_hash: &Vec<u8>) -> io::Result<()>
        where T: Into<Vec<u8>> {

    let (ref sig, ref proof) = *signature;

    let valid_root = proof.validate(root_hash);
    let data_vec   = data.into();

    let valid_sig  = proof.value.key.verify_signature(sig, data_vec.as_slice());

    if !valid_root {
        return Err(verif_error("The inclusion proof failed to validate."));
    }

    if !valid_sig {
        return Err(verif_error("The signature could not be properly verified."));
    }

    Ok(())
}
<|endoftext|>


<commit_before>use {Poll, Async, Future};
use sink::Sink;

/// Future for the `Sink::flush` combinator, which polls the sink until all data
/// has been flushed.
#[derive(Debug)]
#[must_use = "futures do nothing unless polled"]
pub struct Flush<S> {
    sink: Option<S>,
}

pub fn new<S: Sink>(sink: S) -> Flush<S> {
    Flush { sink: Some(sink) }
}

impl<S: Sink> Flush<S> {
    /// Get a shared reference to the inner sink.
    pub fn get_ref(&self) -> &S {
        self.sink.as_ref().expect("Attempted `Flush::get_ref` after the flush completed")
    }

    /// Get a mutable reference to the inner sink.
    pub fn get_mut(&mut self) -> &mut S {
        self.sink.as_mut().expect("Attempted `Flush::get_mut` after the flush completed")
    }
}

impl<S: Sink> Future for Flush<S> {
    type Item = S;
    type Error = S::SinkError;

    fn poll(&mut self) -> Poll<S, S::SinkError> {
        let mut sink = self.sink.take().expect("Attempted to poll Flush after it completed");
        if sink.poll_complete()?.is_ready() {
            Ok(Async::Ready(sink))
        } else {
            self.sink = Some(sink);
            Ok(Async::NotReady)
        }
    }
}
<commit_msg>Add `Flush::into_inner` method<commit_after>use {Poll, Async, Future};
use sink::Sink;

/// Future for the `Sink::flush` combinator, which polls the sink until all data
/// has been flushed.
#[derive(Debug)]
#[must_use = "futures do nothing unless polled"]
pub struct Flush<S> {
    sink: Option<S>,
}

pub fn new<S: Sink>(sink: S) -> Flush<S> {
    Flush { sink: Some(sink) }
}

impl<S: Sink> Flush<S> {
    /// Get a shared reference to the inner sink.
    pub fn get_ref(&self) -> &S {
        self.sink.as_ref().expect("Attempted `Flush::get_ref` after the flush completed")
    }

    /// Get a mutable reference to the inner sink.
    pub fn get_mut(&mut self) -> &mut S {
        self.sink.as_mut().expect("Attempted `Flush::get_mut` after the flush completed")
    }

    /// Consume the `Flush` and return the inner sink.
    pub fn into_inner(self) -> S {
        self.sink.expect("Attempted `Flush::into_inner` after the flush completed")
    }
}

impl<S: Sink> Future for Flush<S> {
    type Item = S;
    type Error = S::SinkError;

    fn poll(&mut self) -> Poll<S, S::SinkError> {
        let mut sink = self.sink.take().expect("Attempted to poll Flush after it completed");
        if sink.poll_complete()?.is_ready() {
            Ok(Async::Ready(sink))
        } else {
            self.sink = Some(sink);
            Ok(Async::NotReady)
        }
    }
}
<|endoftext|>


<commit_before>use std::{cmp, fmt, ptr};
use std::os::raw::c_int;
use std::os::unix::io::RawFd;
use std::collections::HashMap;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::time::Duration;

use libc::{self, time_t};

use {io, event, Ready, PollOpt, Token, Event};
use sys::cvt;
use sys::io::set_cloexec;

/// Each Selector has a globally unique(ish) ID associated with it. This ID
/// gets tracked by `TcpStream`, `TcpListener`, etc... when they are first
/// registered with the `Selector`. If a type that is previously associated with
/// a `Selector` attempts to register itself with a different `Selector`, the
/// operation will return with an error. This matches windows behavior.
static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;

macro_rules! kevent {
    ($id: expr, $filter: expr, $flags: expr, $data: expr) => {
        libc::kevent {
            ident: $id as ::libc::uintptr_t,
            filter: $filter,
            flags: $flags,
            fflags: 0,
            data: 0,
            udata: $data as *mut _,
        }
    }
}

pub struct Selector {
    id: usize,
    kq: RawFd,
}

impl Selector {
    pub fn new() -> io::Result<Selector> {
        // offset by 1 to avoid choosing 0 as the id of a selector
        let id = NEXT_ID.fetch_add(1, Ordering::Relaxed) + 1;
        let kq = unsafe { try!(cvt(libc::kqueue())) };
        drop(set_cloexec(kq));

        Ok(Selector {
            id: id,
            kq: kq,
        })
    }

    pub fn id(&self) -> usize {
        self.id
    }

    pub fn select(&self, evts: &mut Events, awakener: Token, timeout: Option<Duration>) -> io::Result<bool> {
        let timeout = timeout.map(|to| {
            libc::timespec {
                tv_sec: cmp::min(to.as_secs(), time_t::max_value() as u64) as time_t,
                tv_nsec: to.subsec_nanos() as libc::c_long,
            }
        });
        let timeout = timeout.as_ref().map(|s| s as *const _).unwrap_or(ptr::null_mut());

        unsafe {
            let cnt = try!(cvt(libc::kevent(self.kq,
                                            ptr::null(),
                                            0,
                                            evts.sys_events.0.as_mut_ptr(),
            // FIXME: needs a saturating cast here.
                                            evts.sys_events.0.capacity() as c_int,
                                            timeout)));
            evts.sys_events.0.set_len(cnt as usize);
            Ok(evts.coalesce(awakener))
        }
    }

    pub fn register(&self, fd: RawFd, token: Token, interests: Ready, opts: PollOpt) -> io::Result<()> {
        trace!("registering; token={:?}; interests={:?}", token, interests);

        let flags = if opts.contains(PollOpt::edge()) { libc::EV_CLEAR } else { 0 } |
                    if opts.contains(PollOpt::oneshot()) { libc::EV_ONESHOT } else { 0 } |
                    libc::EV_RECEIPT;

        unsafe {
            let r = if interests.contains(Ready::readable()) { libc::EV_ADD } else { libc::EV_DELETE };
            let w = if interests.contains(Ready::writable()) { libc::EV_ADD } else { libc::EV_DELETE };
            let mut changes = [
                kevent!(fd, libc::EVFILT_READ, flags | r, usize::from(token)),
                kevent!(fd, libc::EVFILT_WRITE, flags | w, usize::from(token)),
            ];
            try!(cvt(libc::kevent(self.kq, changes.as_ptr(), changes.len() as c_int,
                                           changes.as_mut_ptr(), changes.len() as c_int,
                                           ::std::ptr::null())));
            for change in changes.iter() {
                debug_assert_eq!(change.flags & libc::EV_ERROR, libc::EV_ERROR);
                if change.data != 0 {
                    // there’s some error, but we want to ignore ENOENT error for EV_DELETE
                    let orig_flags = if change.filter == libc::EVFILT_READ { r } else { w };
                    if !(change.data as i32 == libc::ENOENT && orig_flags & libc::EV_DELETE != 0) {
                        return Err(::std::io::Error::from_raw_os_error(change.data as i32));
                    }
                }
            }
            Ok(())
        }
    }

    pub fn reregister(&self, fd: RawFd, token: Token, interests: Ready, opts: PollOpt) -> io::Result<()> {
        // Just need to call register here since EV_ADD is a mod if already
        // registered
        self.register(fd, token, interests, opts)
    }

    pub fn deregister(&self, fd: RawFd) -> io::Result<()> {
        unsafe {
            // EV_RECEIPT is a nice way to apply changes and get back per-event results while not
            // draining the actual changes.
            let filter = libc::EV_DELETE | libc::EV_RECEIPT;
            let mut changes = [
                kevent!(fd, libc::EVFILT_READ, filter, ptr::null_mut()),
                kevent!(fd, libc::EVFILT_WRITE, filter, ptr::null_mut()),
            ];
            try!(cvt(libc::kevent(self.kq, changes.as_ptr(), changes.len() as c_int,
                                           changes.as_mut_ptr(), changes.len() as c_int,
                                           ::std::ptr::null())).map(|_| ()));
            if changes[0].data as i32 == libc::ENOENT && changes[1].data as i32 == libc::ENOENT {
                return Err(::std::io::Error::from_raw_os_error(changes[0].data as i32));
            }
            for change in changes.iter() {
                debug_assert_eq!(libc::EV_ERROR & change.flags, libc::EV_ERROR);
                if change.data != 0 && change.data as i32 != libc::ENOENT {
                    return Err(::std::io::Error::from_raw_os_error(changes[0].data as i32));
                }
            }
            Ok(())
        }
    }
}

impl fmt::Debug for Selector {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Selector")
            .field("id", &self.id)
            .field("kq", &self.kq)
            .finish()
    }
}

impl Drop for Selector {
    fn drop(&mut self) {
        unsafe {
            let _ = libc::close(self.kq);
        }
    }
}

pub struct Events {
    sys_events: KeventList,
    events: Vec<Event>,
    event_map: HashMap<Token, usize>,
}

struct KeventList(Vec<libc::kevent>);

unsafe impl Send for KeventList {}
unsafe impl Sync for KeventList {}

impl Events {
    pub fn with_capacity(cap: usize) -> Events {
        Events {
            sys_events: KeventList(Vec::with_capacity(cap)),
            events: Vec::with_capacity(cap),
            event_map: HashMap::with_capacity(cap)
        }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.events.len()
    }

    #[inline]
    pub fn capacity(&self) -> usize {
        self.events.capacity()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.events.is_empty()
    }

    pub fn get(&self, idx: usize) -> Option<Event> {
        self.events.get(idx).map(|e| *e)
    }

    fn coalesce(&mut self, awakener: Token) -> bool {
        let mut ret = false;
        self.events.clear();
        self.event_map.clear();

        for e in self.sys_events.0.iter() {
            let token = Token(e.udata as usize);
            let len = self.events.len();

            if token == awakener {
                // TODO: Should this return an error if event is an error. It
                // is not critical as spurious wakeups are permitted.
                ret = true;
                continue;
            }

            let idx = *self.event_map.entry(token)
                .or_insert(len);

            if idx == len {
                // New entry, insert the default
                self.events.push(Event::new(Ready::empty(), token));

            }

            if e.flags & libc::EV_ERROR != 0 {
                event::kind_mut(&mut self.events[idx]).insert(Ready::error());
            }

            if e.filter == libc::EVFILT_READ {
                event::kind_mut(&mut self.events[idx]).insert(Ready::readable());
            } else if e.filter == libc::EVFILT_WRITE {
                event::kind_mut(&mut self.events[idx]).insert(Ready::writable());
            }

            if e.flags & libc::EV_EOF != 0 {
                event::kind_mut(&mut self.events[idx]).insert(Ready::hup());

                // When the read end of the socket is closed, EV_EOF is set on
                // flags, and fflags contains the error if there is one.
                if e.fflags != 0 {
                    event::kind_mut(&mut self.events[idx]).insert(Ready::error());
                }
            }
        }

        ret
    }

    pub fn push_event(&mut self, event: Event) {
        self.events.push(event);
    }
}

impl fmt::Debug for Events {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Events {{ len: {} }}", self.sys_events.0.len())
    }
}
<commit_msg>kqueue: Ignore EPIPE coming out of<commit_after>use std::{cmp, fmt, ptr};
use std::os::raw::c_int;
use std::os::unix::io::RawFd;
use std::collections::HashMap;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use std::time::Duration;

use libc::{self, time_t};

use {io, event, Ready, PollOpt, Token, Event};
use sys::cvt;
use sys::io::set_cloexec;

/// Each Selector has a globally unique(ish) ID associated with it. This ID
/// gets tracked by `TcpStream`, `TcpListener`, etc... when they are first
/// registered with the `Selector`. If a type that is previously associated with
/// a `Selector` attempts to register itself with a different `Selector`, the
/// operation will return with an error. This matches windows behavior.
static NEXT_ID: AtomicUsize = ATOMIC_USIZE_INIT;

macro_rules! kevent {
    ($id: expr, $filter: expr, $flags: expr, $data: expr) => {
        libc::kevent {
            ident: $id as ::libc::uintptr_t,
            filter: $filter,
            flags: $flags,
            fflags: 0,
            data: 0,
            udata: $data as *mut _,
        }
    }
}

pub struct Selector {
    id: usize,
    kq: RawFd,
}

impl Selector {
    pub fn new() -> io::Result<Selector> {
        // offset by 1 to avoid choosing 0 as the id of a selector
        let id = NEXT_ID.fetch_add(1, Ordering::Relaxed) + 1;
        let kq = unsafe { try!(cvt(libc::kqueue())) };
        drop(set_cloexec(kq));

        Ok(Selector {
            id: id,
            kq: kq,
        })
    }

    pub fn id(&self) -> usize {
        self.id
    }

    pub fn select(&self, evts: &mut Events, awakener: Token, timeout: Option<Duration>) -> io::Result<bool> {
        let timeout = timeout.map(|to| {
            libc::timespec {
                tv_sec: cmp::min(to.as_secs(), time_t::max_value() as u64) as time_t,
                tv_nsec: to.subsec_nanos() as libc::c_long,
            }
        });
        let timeout = timeout.as_ref().map(|s| s as *const _).unwrap_or(ptr::null_mut());

        unsafe {
            let cnt = try!(cvt(libc::kevent(self.kq,
                                            ptr::null(),
                                            0,
                                            evts.sys_events.0.as_mut_ptr(),
            // FIXME: needs a saturating cast here.
                                            evts.sys_events.0.capacity() as c_int,
                                            timeout)));
            evts.sys_events.0.set_len(cnt as usize);
            Ok(evts.coalesce(awakener))
        }
    }

    pub fn register(&self, fd: RawFd, token: Token, interests: Ready, opts: PollOpt) -> io::Result<()> {
        trace!("registering; token={:?}; interests={:?}", token, interests);

        let flags = if opts.contains(PollOpt::edge()) { libc::EV_CLEAR } else { 0 } |
                    if opts.contains(PollOpt::oneshot()) { libc::EV_ONESHOT } else { 0 } |
                    libc::EV_RECEIPT;

        unsafe {
            let r = if interests.contains(Ready::readable()) { libc::EV_ADD } else { libc::EV_DELETE };
            let w = if interests.contains(Ready::writable()) { libc::EV_ADD } else { libc::EV_DELETE };
            let mut changes = [
                kevent!(fd, libc::EVFILT_READ, flags | r, usize::from(token)),
                kevent!(fd, libc::EVFILT_WRITE, flags | w, usize::from(token)),
            ];
            try!(cvt(libc::kevent(self.kq, changes.as_ptr(), changes.len() as c_int,
                                           changes.as_mut_ptr(), changes.len() as c_int,
                                           ::std::ptr::null())));
            for change in changes.iter() {
                debug_assert_eq!(change.flags & libc::EV_ERROR, libc::EV_ERROR);
                /*
                if change.data != 0 {
                    // there’s some error, but we want to ignore ENOENT error for EV_DELETE
                    let orig_flags = if change.filter == libc::EVFILT_READ { r } else { w };
                    if !(change.data as i32 == libc::ENOENT && orig_flags & libc::EV_DELETE != 0) {
                        return Err(::std::io::Error::from_raw_os_error(change.data as i32));
                    }
                }
                */
                if change.data == 0 {
                    continue
                }

                if change.data as i32 == libc::EPIPE && change.filter == libc::EVFILT_WRITE {
                    continue
                }

                let orig_flags = if change.filter == libc::EVFILT_READ { r } else { w };
                if change.data as i32 == libc::ENOENT && orig_flags & libc::EV_DELETE != 0 {
                    continue
                }

                return Err(::std::io::Error::from_raw_os_error(change.data as i32));
            }
            Ok(())
        }
    }

    pub fn reregister(&self, fd: RawFd, token: Token, interests: Ready, opts: PollOpt) -> io::Result<()> {
        // Just need to call register here since EV_ADD is a mod if already
        // registered
        self.register(fd, token, interests, opts)
    }

    pub fn deregister(&self, fd: RawFd) -> io::Result<()> {
        unsafe {
            // EV_RECEIPT is a nice way to apply changes and get back per-event results while not
            // draining the actual changes.
            let filter = libc::EV_DELETE | libc::EV_RECEIPT;
            let mut changes = [
                kevent!(fd, libc::EVFILT_READ, filter, ptr::null_mut()),
                kevent!(fd, libc::EVFILT_WRITE, filter, ptr::null_mut()),
            ];
            try!(cvt(libc::kevent(self.kq, changes.as_ptr(), changes.len() as c_int,
                                           changes.as_mut_ptr(), changes.len() as c_int,
                                           ::std::ptr::null())).map(|_| ()));
            if changes[0].data as i32 == libc::ENOENT && changes[1].data as i32 == libc::ENOENT {
                return Err(::std::io::Error::from_raw_os_error(changes[0].data as i32));
            }
            for change in changes.iter() {
                debug_assert_eq!(libc::EV_ERROR & change.flags, libc::EV_ERROR);
                if change.data != 0 && change.data as i32 != libc::ENOENT {
                    return Err(::std::io::Error::from_raw_os_error(changes[0].data as i32));
                }
            }
            Ok(())
        }
    }
}

impl fmt::Debug for Selector {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("Selector")
            .field("id", &self.id)
            .field("kq", &self.kq)
            .finish()
    }
}

impl Drop for Selector {
    fn drop(&mut self) {
        unsafe {
            let _ = libc::close(self.kq);
        }
    }
}

pub struct Events {
    sys_events: KeventList,
    events: Vec<Event>,
    event_map: HashMap<Token, usize>,
}

struct KeventList(Vec<libc::kevent>);

unsafe impl Send for KeventList {}
unsafe impl Sync for KeventList {}

impl Events {
    pub fn with_capacity(cap: usize) -> Events {
        Events {
            sys_events: KeventList(Vec::with_capacity(cap)),
            events: Vec::with_capacity(cap),
            event_map: HashMap::with_capacity(cap)
        }
    }

    #[inline]
    pub fn len(&self) -> usize {
        self.events.len()
    }

    #[inline]
    pub fn capacity(&self) -> usize {
        self.events.capacity()
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.events.is_empty()
    }

    pub fn get(&self, idx: usize) -> Option<Event> {
        self.events.get(idx).map(|e| *e)
    }

    fn coalesce(&mut self, awakener: Token) -> bool {
        let mut ret = false;
        self.events.clear();
        self.event_map.clear();

        for e in self.sys_events.0.iter() {
            let token = Token(e.udata as usize);
            let len = self.events.len();

            if token == awakener {
                // TODO: Should this return an error if event is an error. It
                // is not critical as spurious wakeups are permitted.
                ret = true;
                continue;
            }

            let idx = *self.event_map.entry(token)
                .or_insert(len);

            if idx == len {
                // New entry, insert the default
                self.events.push(Event::new(Ready::empty(), token));

            }

            if e.flags & libc::EV_ERROR != 0 {
                event::kind_mut(&mut self.events[idx]).insert(Ready::error());
            }

            if e.filter == libc::EVFILT_READ {
                event::kind_mut(&mut self.events[idx]).insert(Ready::readable());
            } else if e.filter == libc::EVFILT_WRITE {
                event::kind_mut(&mut self.events[idx]).insert(Ready::writable());
            }

            if e.flags & libc::EV_EOF != 0 {
                event::kind_mut(&mut self.events[idx]).insert(Ready::hup());

                // When the read end of the socket is closed, EV_EOF is set on
                // flags, and fflags contains the error if there is one.
                if e.fflags != 0 {
                    event::kind_mut(&mut self.events[idx]).insert(Ready::error());
                }
            }
        }

        ret
    }

    pub fn push_event(&mut self, event: Event) {
        self.events.push(event);
    }
}

impl fmt::Debug for Events {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Events {{ len: {} }}", self.sys_events.0.len())
    }
}
<|endoftext|>


<commit_before>use byteorder::{ByteOrder, LE};
use std::marker::PhantomData;
use std::{iter, mem};

use crate::{accessor, buffer};

fn buffer_view_slice<'a, 's>(
    view: buffer::View<'a>,
    get_buffer_data: &dyn Fn(buffer::Buffer<'a>) -> Option<&'s [u8]>,
) -> Option<&'s [u8]> {
    let start = view.offset();
    let end = start + view.length();
    get_buffer_data(view.buffer())
        .map(|slice| slice.get(start..end))
        .flatten()
}

/// General iterator for an accessor.
#[derive(Clone, Debug)]
pub enum Iter<'a, T: Item> {
    /// Standard accessor iterator.
    Standard(ItemIter<'a, T>),

    /// Iterator for accessor with sparse values.
    Sparse(SparseIter<'a, T>),
}

impl<'a, T: Item> Iterator for Iter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            Iter::Standard(ref mut iter) => iter.next(),
            Iter::Sparse(ref mut iter) => iter.next(),
        }
    }

    fn nth(&mut self, nth: usize) -> Option<Self::Item> {
        match self {
            Iter::Standard(ref mut iter) => iter.nth(nth),
            Iter::Sparse(ref mut iter) => iter.nth(nth),
        }
    }

    fn last(self) -> Option<Self::Item> {
        match self {
            Iter::Standard(iter) => iter.last(),
            Iter::Sparse(iter) => iter.last(),
        }
    }

    fn count(self) -> usize {
        match self {
            Iter::Standard(iter) => iter.count(),
            Iter::Sparse(iter) => iter.count(),
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        match self {
            Iter::Standard(ref iter) => iter.size_hint(),
            Iter::Sparse(ref iter) => iter.size_hint(),
        }
    }
}

impl<'a, T: Item> ExactSizeIterator for Iter<'a, T> {}

/// Iterator over indices of sparse accessor.
#[derive(Clone, Debug)]
pub enum SparseIndicesIter<'a> {
    /// 8-bit indices.
    U8(ItemIter<'a, u8>),
    /// 16-bit indices.
    U16(ItemIter<'a, u16>),
    /// 32-bit indices.
    U32(ItemIter<'a, u32>),
}

impl<'a> Iterator for SparseIndicesIter<'a> {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        match *self {
            SparseIndicesIter::U8(ref mut iter) => iter.next().map(|x| x as u32),
            SparseIndicesIter::U16(ref mut iter) => iter.next().map(|x| x as u32),
            SparseIndicesIter::U32(ref mut iter) => iter.next(),
        }
    }
}

/// Iterates over a sparse accessor.
#[derive(Clone, Debug)]
pub struct SparseIter<'a, T: Item> {
    /// Base value iterator.
    ///
    /// This can be `None` if the base buffer view is not set. In this case the base values are all zero.
    base: Option<ItemIter<'a, T>>,

    /// Sparse indices iterator.
    indices: iter::Peekable<SparseIndicesIter<'a>>,

    /// Sparse values iterator.
    values: ItemIter<'a, T>,

    /// Iterator counter.
    counter: u32,
}

impl<'a, T: Item> SparseIter<'a, T> {
    /// Constructor.
    ///
    /// Here `base` is allowed to be `None` when the base buffer view is not explicitly specified.
    pub fn new(
        base: Option<ItemIter<'a, T>>,
        indices: SparseIndicesIter<'a>,
        values: ItemIter<'a, T>,
    ) -> Self {
        SparseIter {
            base,
            indices: indices.peekable(),
            values,
            counter: 0,
        }
    }
}

impl<'a, T: Item> Iterator for SparseIter<'a, T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let mut next_value = self
            .base
            .as_mut()
            .map(|iter| iter.next())
            .unwrap_or_else(|| Some(T::zero()))?;

        let next_sparse_index = self.indices.peek();
        if let Some(index) = next_sparse_index {
            if *index == self.counter {
                self.indices.next(); // advance
                next_value = self.values.next().unwrap();
            }
        }

        self.counter += 1;

        Some(next_value)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let hint = self.values.len() - self.counter as usize;
        (hint, Some(hint))
    }
}

impl<'a, T: Item> ExactSizeIterator for SparseIter<'a, T> {}

/// Represents items that can be read by an [`Accessor`].
///
/// [`Accessor`]: struct.Accessor.html
pub trait Item {
    /// Create an object of this type from a byte slice.
    fn from_slice(slice: &[u8]) -> Self;
    /// Create an object of this type that represents a zero value.
    fn zero() -> Self;
}

/// Visits the items in an [`Accessor`].
///
/// [`Accessor`]: struct.Accessor.html
#[derive(Copy, Clone, Debug)]
pub struct ItemIter<'a, T: Item> {
    stride: usize,
    data: &'a [u8],
    _phantom: PhantomData<T>,
}

impl Item for i8 {
    fn from_slice(slice: &[u8]) -> Self {
        slice[0] as i8
    }
    fn zero() -> Self {
        0
    }
}

impl Item for i16 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_i16(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u8 {
    fn from_slice(slice: &[u8]) -> Self {
        slice[0]
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u16 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_u16(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u32 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_u32(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for f32 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_f32(slice)
    }
    fn zero() -> Self {
        0.0
    }
}

impl<T: Item + Copy> Item for [T; 2] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 2 * mem::size_of::<T>());
        [
            T::from_slice(slice),
            T::from_slice(&slice[mem::size_of::<T>()..]),
        ]
    }
    fn zero() -> Self {
        [T::zero(); 2]
    }
}

impl<T: Item + Copy> Item for [T; 3] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 3 * mem::size_of::<T>());
        [
            T::from_slice(slice),
            T::from_slice(&slice[mem::size_of::<T>()..]),
            T::from_slice(&slice[2 * mem::size_of::<T>()..]),
        ]
    }
    fn zero() -> Self {
        [T::zero(); 3]
    }
}

impl<T: Item + Copy> Item for [T; 4] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 4 * mem::size_of::<T>());
        [
            T::from_slice(slice),
            T::from_slice(&slice[mem::size_of::<T>()..]),
            T::from_slice(&slice[2 * mem::size_of::<T>()..]),
            T::from_slice(&slice[3 * mem::size_of::<T>()..]),
        ]
    }
    fn zero() -> Self {
        [T::zero(); 4]
    }
}

impl<'a, T: Item> ItemIter<'a, T> {
    /// Constructor.
    pub fn new(slice: &'a [u8], stride: usize) -> Self {
        ItemIter {
            data: slice,
            stride,
            _phantom: PhantomData,
        }
    }
}

impl<'a, 's, T: Item> Iter<'s, T> {
    /// Constructor.
    pub fn new<F>(accessor: super::Accessor<'a>, get_buffer_data: F) -> Option<Iter<'s, T>>
    where
        F: Clone + Fn(buffer::Buffer<'a>) -> Option<&'s [u8]>,
    {
        match accessor.sparse() {
            Some(sparse) => {
                // Using `if let` here instead of map to preserve the early return behavior.
                let base_iter = if let Some(view) = accessor.view() {
                    let stride = view.stride().unwrap_or(mem::size_of::<T>());

                    let start = accessor.offset();
                    let end = start + stride * (accessor.count() - 1) + mem::size_of::<T>();
                    let subslice = buffer_view_slice(view, &get_buffer_data)
                        .and_then(|slice| slice.get(start..end))?;

                    Some(ItemIter::new(subslice, stride))
                } else {
                    None
                };

                let indices = sparse.indices();
                let values = sparse.values();
                let sparse_count = sparse.count() as usize;

                let index_iter = {
                    let view = indices.view();
                    let index_size = indices.index_type().size();
                    let stride = view.stride().unwrap_or(index_size);

                    let start = indices.offset() as usize;
                    let end = start + stride * (sparse_count - 1) + index_size;
                    let subslice = buffer_view_slice(view, &get_buffer_data)
                        .and_then(|slice| slice.get(start..end))?;

                    match indices.index_type() {
                        accessor::sparse::IndexType::U8 => {
                            SparseIndicesIter::U8(ItemIter::new(subslice, stride))
                        }
                        accessor::sparse::IndexType::U16 => {
                            SparseIndicesIter::U16(ItemIter::new(subslice, stride))
                        }
                        accessor::sparse::IndexType::U32 => {
                            SparseIndicesIter::U32(ItemIter::new(subslice, stride))
                        }
                    }
                };

                let value_iter = {
                    let view = values.view();
                    let stride = view.stride().unwrap_or(mem::size_of::<T>());

                    let start = values.offset() as usize;
                    let end = start + stride * (sparse_count - 1) + mem::size_of::<T>();
                    let subslice = buffer_view_slice(view, &get_buffer_data)
                        .and_then(|slice| slice.get(start..end))?;

                    ItemIter::new(subslice, stride)
                };

                Some(Iter::Sparse(SparseIter::new(
                    base_iter, index_iter, value_iter,
                )))
            }
            None => {
                debug_assert_eq!(mem::size_of::<T>(), accessor.size());
                debug_assert!(mem::size_of::<T>() > 0);

                accessor.view().and_then(|view| {
                    let stride = view.stride().unwrap_or(mem::size_of::<T>());
                    debug_assert!(
                        stride >= mem::size_of::<T>(),
                        "Mismatch in stride, expected at least {} stride but found {}",
                        mem::size_of::<T>(),
                        stride
                    );

                    let start = accessor.offset();
                    let end = start + stride * (accessor.count() - 1) + mem::size_of::<T>();
                    let subslice = buffer_view_slice(view, &get_buffer_data)
                        .and_then(|slice| slice.get(start..end))?;

                    Some(Iter::Standard(ItemIter {
                        stride,
                        data: subslice,
                        _phantom: PhantomData,
                    }))
                })
            }
        }
    }
}

impl<'a, T: Item> ExactSizeIterator for ItemIter<'a, T> {}
impl<'a, T: Item> Iterator for ItemIter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        let stride = if self.data.len() >= self.stride {
            Some(self.stride)
        } else if self.data.len() >= mem::size_of::<T>() {
            Some(mem::size_of::<T>())
        } else {
            None
        };
        if let Some(stride) = stride {
            let (val, data) = self.data.split_at(stride);
            let val = T::from_slice(val);
            self.data = data;
            Some(val)
        } else {
            None
        }
    }

    fn nth(&mut self, nth: usize) -> Option<Self::Item> {
        if let Some(val_data) = self.data.get(nth * self.stride..) {
            if val_data.len() >= mem::size_of::<T>() {
                let val = T::from_slice(val_data);
                self.data = &val_data[self.stride.min(val_data.len())..];
                Some(val)
            } else {
                None
            }
        } else {
            None
        }
    }

    fn last(self) -> Option<Self::Item> {
        if self.data.len() >= mem::size_of::<T>() {
            self.data
                .get((self.data.len() - 1) / self.stride * self.stride..)
                .map(T::from_slice)
        } else {
            None
        }
    }

    fn count(self) -> usize {
        self.size_hint().0
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let hint = self.data.len() / self.stride
            + (self.data.len() % self.stride >= mem::size_of::<T>()) as usize;
        (hint, Some(hint))
    }
}
<commit_msg>Simplify `buffer_view_slice`<commit_after>use byteorder::{ByteOrder, LE};
use std::marker::PhantomData;
use std::{iter, mem};

use crate::{accessor, buffer};

fn buffer_view_slice<'a, 's>(
    view: buffer::View<'a>,
    get_buffer_data: &dyn Fn(buffer::Buffer<'a>) -> Option<&'s [u8]>,
) -> Option<&'s [u8]> {
    let start = view.offset();
    let end = start + view.length();
    get_buffer_data(view.buffer()).and_then(|slice| slice.get(start..end))
}

/// General iterator for an accessor.
#[derive(Clone, Debug)]
pub enum Iter<'a, T: Item> {
    /// Standard accessor iterator.
    Standard(ItemIter<'a, T>),

    /// Iterator for accessor with sparse values.
    Sparse(SparseIter<'a, T>),
}

impl<'a, T: Item> Iterator for Iter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            Iter::Standard(ref mut iter) => iter.next(),
            Iter::Sparse(ref mut iter) => iter.next(),
        }
    }

    fn nth(&mut self, nth: usize) -> Option<Self::Item> {
        match self {
            Iter::Standard(ref mut iter) => iter.nth(nth),
            Iter::Sparse(ref mut iter) => iter.nth(nth),
        }
    }

    fn last(self) -> Option<Self::Item> {
        match self {
            Iter::Standard(iter) => iter.last(),
            Iter::Sparse(iter) => iter.last(),
        }
    }

    fn count(self) -> usize {
        match self {
            Iter::Standard(iter) => iter.count(),
            Iter::Sparse(iter) => iter.count(),
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        match self {
            Iter::Standard(ref iter) => iter.size_hint(),
            Iter::Sparse(ref iter) => iter.size_hint(),
        }
    }
}

impl<'a, T: Item> ExactSizeIterator for Iter<'a, T> {}

/// Iterator over indices of sparse accessor.
#[derive(Clone, Debug)]
pub enum SparseIndicesIter<'a> {
    /// 8-bit indices.
    U8(ItemIter<'a, u8>),
    /// 16-bit indices.
    U16(ItemIter<'a, u16>),
    /// 32-bit indices.
    U32(ItemIter<'a, u32>),
}

impl<'a> Iterator for SparseIndicesIter<'a> {
    type Item = u32;
    fn next(&mut self) -> Option<Self::Item> {
        match *self {
            SparseIndicesIter::U8(ref mut iter) => iter.next().map(|x| x as u32),
            SparseIndicesIter::U16(ref mut iter) => iter.next().map(|x| x as u32),
            SparseIndicesIter::U32(ref mut iter) => iter.next(),
        }
    }
}

/// Iterates over a sparse accessor.
#[derive(Clone, Debug)]
pub struct SparseIter<'a, T: Item> {
    /// Base value iterator.
    ///
    /// This can be `None` if the base buffer view is not set. In this case the base values are all zero.
    base: Option<ItemIter<'a, T>>,

    /// Sparse indices iterator.
    indices: iter::Peekable<SparseIndicesIter<'a>>,

    /// Sparse values iterator.
    values: ItemIter<'a, T>,

    /// Iterator counter.
    counter: u32,
}

impl<'a, T: Item> SparseIter<'a, T> {
    /// Constructor.
    ///
    /// Here `base` is allowed to be `None` when the base buffer view is not explicitly specified.
    pub fn new(
        base: Option<ItemIter<'a, T>>,
        indices: SparseIndicesIter<'a>,
        values: ItemIter<'a, T>,
    ) -> Self {
        SparseIter {
            base,
            indices: indices.peekable(),
            values,
            counter: 0,
        }
    }
}

impl<'a, T: Item> Iterator for SparseIter<'a, T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        let mut next_value = self
            .base
            .as_mut()
            .map(|iter| iter.next())
            .unwrap_or_else(|| Some(T::zero()))?;

        let next_sparse_index = self.indices.peek();
        if let Some(index) = next_sparse_index {
            if *index == self.counter {
                self.indices.next(); // advance
                next_value = self.values.next().unwrap();
            }
        }

        self.counter += 1;

        Some(next_value)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let hint = self.values.len() - self.counter as usize;
        (hint, Some(hint))
    }
}

impl<'a, T: Item> ExactSizeIterator for SparseIter<'a, T> {}

/// Represents items that can be read by an [`Accessor`].
///
/// [`Accessor`]: struct.Accessor.html
pub trait Item {
    /// Create an object of this type from a byte slice.
    fn from_slice(slice: &[u8]) -> Self;
    /// Create an object of this type that represents a zero value.
    fn zero() -> Self;
}

/// Visits the items in an [`Accessor`].
///
/// [`Accessor`]: struct.Accessor.html
#[derive(Copy, Clone, Debug)]
pub struct ItemIter<'a, T: Item> {
    stride: usize,
    data: &'a [u8],
    _phantom: PhantomData<T>,
}

impl Item for i8 {
    fn from_slice(slice: &[u8]) -> Self {
        slice[0] as i8
    }
    fn zero() -> Self {
        0
    }
}

impl Item for i16 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_i16(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u8 {
    fn from_slice(slice: &[u8]) -> Self {
        slice[0]
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u16 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_u16(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for u32 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_u32(slice)
    }
    fn zero() -> Self {
        0
    }
}

impl Item for f32 {
    fn from_slice(slice: &[u8]) -> Self {
        LE::read_f32(slice)
    }
    fn zero() -> Self {
        0.0
    }
}

impl<T: Item + Copy> Item for [T; 2] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 2 * mem::size_of::<T>());
        [
            T::from_slice(slice),
            T::from_slice(&slice[mem::size_of::<T>()..]),
        ]
    }
    fn zero() -> Self {
        [T::zero(); 2]
    }
}

impl<T: Item + Copy> Item for [T; 3] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 3 * mem::size_of::<T>());
        [
            T::from_slice(slice),
            T::from_slice(&slice[mem::size_of::<T>()..]),
            T::from_slice(&slice[2 * mem::size_of::<T>()..]),
        ]
    }
    fn zero() -> Self {
        [T::zero(); 3]
    }
}

impl<T: Item + Copy> Item for [T; 4] {
    fn from_slice(slice: &[u8]) -> Self {
        assert!(slice.len() >= 4 * mem::size_of::<T>());
        [
            T::from_slice(slice),
            T::from_slice(&slice[mem::size_of::<T>()..]),
            T::from_slice(&slice[2 * mem::size_of::<T>()..]),
            T::from_slice(&slice[3 * mem::size_of::<T>()..]),
        ]
    }
    fn zero() -> Self {
        [T::zero(); 4]
    }
}

impl<'a, T: Item> ItemIter<'a, T> {
    /// Constructor.
    pub fn new(slice: &'a [u8], stride: usize) -> Self {
        ItemIter {
            data: slice,
            stride,
            _phantom: PhantomData,
        }
    }
}

impl<'a, 's, T: Item> Iter<'s, T> {
    /// Constructor.
    pub fn new<F>(accessor: super::Accessor<'a>, get_buffer_data: F) -> Option<Iter<'s, T>>
    where
        F: Clone + Fn(buffer::Buffer<'a>) -> Option<&'s [u8]>,
    {
        match accessor.sparse() {
            Some(sparse) => {
                // Using `if let` here instead of map to preserve the early return behavior.
                let base_iter = if let Some(view) = accessor.view() {
                    let stride = view.stride().unwrap_or(mem::size_of::<T>());

                    let start = accessor.offset();
                    let end = start + stride * (accessor.count() - 1) + mem::size_of::<T>();
                    let subslice = buffer_view_slice(view, &get_buffer_data)
                        .and_then(|slice| slice.get(start..end))?;

                    Some(ItemIter::new(subslice, stride))
                } else {
                    None
                };

                let indices = sparse.indices();
                let values = sparse.values();
                let sparse_count = sparse.count() as usize;

                let index_iter = {
                    let view = indices.view();
                    let index_size = indices.index_type().size();
                    let stride = view.stride().unwrap_or(index_size);

                    let start = indices.offset() as usize;
                    let end = start + stride * (sparse_count - 1) + index_size;
                    let subslice = buffer_view_slice(view, &get_buffer_data)
                        .and_then(|slice| slice.get(start..end))?;

                    match indices.index_type() {
                        accessor::sparse::IndexType::U8 => {
                            SparseIndicesIter::U8(ItemIter::new(subslice, stride))
                        }
                        accessor::sparse::IndexType::U16 => {
                            SparseIndicesIter::U16(ItemIter::new(subslice, stride))
                        }
                        accessor::sparse::IndexType::U32 => {
                            SparseIndicesIter::U32(ItemIter::new(subslice, stride))
                        }
                    }
                };

                let value_iter = {
                    let view = values.view();
                    let stride = view.stride().unwrap_or(mem::size_of::<T>());

                    let start = values.offset() as usize;
                    let end = start + stride * (sparse_count - 1) + mem::size_of::<T>();
                    let subslice = buffer_view_slice(view, &get_buffer_data)
                        .and_then(|slice| slice.get(start..end))?;

                    ItemIter::new(subslice, stride)
                };

                Some(Iter::Sparse(SparseIter::new(
                    base_iter, index_iter, value_iter,
                )))
            }
            None => {
                debug_assert_eq!(mem::size_of::<T>(), accessor.size());
                debug_assert!(mem::size_of::<T>() > 0);

                accessor.view().and_then(|view| {
                    let stride = view.stride().unwrap_or(mem::size_of::<T>());
                    debug_assert!(
                        stride >= mem::size_of::<T>(),
                        "Mismatch in stride, expected at least {} stride but found {}",
                        mem::size_of::<T>(),
                        stride
                    );

                    let start = accessor.offset();
                    let end = start + stride * (accessor.count() - 1) + mem::size_of::<T>();
                    let subslice = buffer_view_slice(view, &get_buffer_data)
                        .and_then(|slice| slice.get(start..end))?;

                    Some(Iter::Standard(ItemIter {
                        stride,
                        data: subslice,
                        _phantom: PhantomData,
                    }))
                })
            }
        }
    }
}

impl<'a, T: Item> ExactSizeIterator for ItemIter<'a, T> {}
impl<'a, T: Item> Iterator for ItemIter<'a, T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        let stride = if self.data.len() >= self.stride {
            Some(self.stride)
        } else if self.data.len() >= mem::size_of::<T>() {
            Some(mem::size_of::<T>())
        } else {
            None
        };
        if let Some(stride) = stride {
            let (val, data) = self.data.split_at(stride);
            let val = T::from_slice(val);
            self.data = data;
            Some(val)
        } else {
            None
        }
    }

    fn nth(&mut self, nth: usize) -> Option<Self::Item> {
        if let Some(val_data) = self.data.get(nth * self.stride..) {
            if val_data.len() >= mem::size_of::<T>() {
                let val = T::from_slice(val_data);
                self.data = &val_data[self.stride.min(val_data.len())..];
                Some(val)
            } else {
                None
            }
        } else {
            None
        }
    }

    fn last(self) -> Option<Self::Item> {
        if self.data.len() >= mem::size_of::<T>() {
            self.data
                .get((self.data.len() - 1) / self.stride * self.stride..)
                .map(T::from_slice)
        } else {
            None
        }
    }

    fn count(self) -> usize {
        self.size_hint().0
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        let hint = self.data.len() / self.stride
            + (self.data.len() % self.stride >= mem::size_of::<T>()) as usize;
        (hint, Some(hint))
    }
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

pub mod startup;

// TODO: Have a more specific error type.
type Error = Box<dyn std::error::Error>;

pub trait Request {
    type Proto: prost::Message + Default;
    fn from_proto(proto: Self::Proto) -> Self;
}

pub trait Response {
    const RDF_NAME: Option<&'static str>;
    type Proto: prost::Message + Default;
    fn into_proto(self) -> Self::Proto;
}

impl Request for () {

    type Proto = ();

    fn from_proto(_: ()) {
    }
}

impl Response for () {

    const RDF_NAME: Option<&'static str> = None;

    type Proto = ();

    fn into_proto(self) {
    }
}
<commit_msg>Remove a useless type.<commit_after>// Copyright 2020 Google LLC
//
// Use of this source code is governed by an MIT-style license that can be found
// in the LICENSE file or at https://opensource.org/licenses/MIT.

pub mod startup;

pub trait Request {
    type Proto: prost::Message + Default;
    fn from_proto(proto: Self::Proto) -> Self;
}

pub trait Response {
    const RDF_NAME: Option<&'static str>;
    type Proto: prost::Message + Default;
    fn into_proto(self) -> Self::Proto;
}

impl Request for () {

    type Proto = ();

    fn from_proto(_: ()) {
    }
}

impl Response for () {

    const RDF_NAME: Option<&'static str> = None;

    type Proto = ();

    fn into_proto(self) {
    }
}
<|endoftext|>