<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! `x86_64` architecture-specific implementation.
// pub mod cpu;
pub mod drivers;
pub mod interrupts;

#[path = "../x86_all/bda.rs"] pub mod bda;
#[path = "../x86_all/multiboot2.rs"] pub mod multiboot2;

pub const ARCH_BITS: u8 = 64;

extern {
    // TODO: It would be really nice if there was a less ugly way of doing
    // this... (read: after the Revolution when we add memory regions to the
    // heap programmatically.)
    #[link_name = "heap_base_addr"]
    #[linkage = "external"]
    pub static HEAP_BASE: *mut u8;
    #[link_name = "heap_top_addr"]
    #[linkage = "external"]
    pub static HEAP_TOP: *mut u8;
    // Of course, we will still need to export the kernel stack addresses like
    // this, but it would be nice if they could be, i dont know, not mut u8s
    // pointers, like God intended.
    #[link_name = "stack_base"]
    pub static STACK_BASE: *mut u8;
    #[link_name = "stack_top"]
    pub static STACK_TOP: *mut u8;
}

use memory::PAddr;

/// Trampoline to ensure we have a correct stack frame for calling [`arch_init`]
///
/// I have no idea why this works, but it does.
///
/// [`arch_init`]: fn.arch_init
#[naked]
#[no_mangle]
pub unsafe extern "C" fn long_mode_init() {
    asm!("movabsq $$(stack_top), %rsp");
    asm!("mov ax, 0
          mov ss, ax
          mov ds, ax
          mov es, ax
          mov fs, ax
          mov gs, ax
          call arch_init"
        :::: "intel");

}

/// Entry point for architecture-specific kernel init
///
/// This expects to be passed the address of a valid
/// Multiboot 2 info struct. It's the bootloader's responsibility to ensure
/// that this is passed in the correct register as expected by the calling
/// convention (`edi` on x86). If this isn't there, you can expect to have a
/// bad problem and not go to space today.
#[no_mangle]
pub extern "C" fn arch_init(multiboot_addr: PAddr) {
    use cpu::{control_regs, msr};
    use elf;
    use params::{InitParams, mem};

    kinfoln!(dots: " . ", "Beginning `arch_init()` for x86_64");

    ::io::term::CONSOLE.lock().clear();
    ::logger::initialize()
        .expect("Could not initialize logger!");

    // -- Unpack multiboot tag ------------------------------------------------
    kinfoln!( dots: " . "
            , "trying to unpack multiboot info at {:#p}"
            , multiboot_addr);

    // try to interpret the structure at the multiboot address as a multiboot
    // info struct. if it's invalid, fail.
    let boot_info
        = unsafe { multiboot2::Info::from(multiboot_addr)
                    .expect("Could not unpack multiboot2 information!") };

    // Extract ELF sections tag from the multiboot info
    let elf_sections_tag
        = boot_info.elf_sections()
                   .expect("ELF sections tag required!");

    kinfoln!(dots: " . ", "Detecting kernel ELF sections:");

    // Extract kernel ELF sections from  multiboot info
    let mut n_elf_sections = 0;

    let kernel_begin
        = elf_sections_tag.sections()
            // .filter(|s| s.is_allocated())
            .map(|s| {
                kinfoln!( dots: " . . ", "{}", s );
                kinfoln!( dots: " . . . ", "flags: [ {:?} ]", s.flags());
                s.address() })
            .min()
            .expect("Could not find kernel start section!\
                    \nSomething is deeply wrong.");

    let kernel_end
        = elf_sections_tag.sections()
            // .filter(|s| s.is_allocated())
            .map(|s| { n_elf_sections += 1; s.end_address() })
            .max()
            .expect("Could not find kernel end section!\
                    \nSomething is deeply wrong.");

    kinfoln!( dots: " . ", "Detected {} kernel ELF sections.", n_elf_sections);
    kinfoln!( dots: " . . ", "Kernel begins at {:#p} and ends at {:#p}."
            , kernel_begin, kernel_end );

    let multiboot_end = multiboot_addr + boot_info.length as u64;

    kinfoln!( dots: " . . ", "Multiboot info begins at {:#x} and ends at {:#x}."
            , multiboot_addr, multiboot_end);

    let mut params = InitParams { kernel_base: kernel_begin
                            , kernel_top: kernel_end
                            , multiboot_start: Some(multiboot_addr)
                            , multiboot_end: Some(multiboot_end)
                            , heap_base: unsafe { PAddr::from(HEAP_BASE) }
                            , heap_top: unsafe { PAddr::from(HEAP_TOP) }
                            , stack_base: unsafe { PAddr::from(STACK_BASE) }
                            , stack_top: unsafe { PAddr::from(STACK_TOP) }
                            , elf_sections: Some(elf_sections_tag.sections())
                            , ..Default::default()
                        };

    // Extract the memory map tag from the multiboot info
    let mem_map = boot_info.mem_map()
                           .expect("Memory map tag required!");

    kinfoln!(dots: " . ", "Detected memory areas:");
    for area in mem_map {
        kinfoln!( dots: " . . ", "{}", area);
        let a: mem::Area = area.into();
        if a.is_usable == true { params.mem_map.push(a); }
    }

     //-- enable flags needed for paging ------------------------------------
     unsafe {
        //  control_regs::cr0::enable_write_protect(true);
        //  kinfoln!(dots: " . ", "Page write protect ENABED" );

        let efer = msr::read(msr::IA32_EFER);
        trace!("EFER = {:#x}", efer);
        msr::write(msr::IA32_EFER, efer | (1 << 11));
        let efer = msr::read(msr::IA32_EFER);
        trace!("EFER = {:#x}", efer);
        kinfoln!(dots: " . ", "Page no execute bit ENABLED");
     }

    kinfoln!(dots: " . ", "Transferring to `kernel_init()`.");
    ::kernel_init(&params);
}
<commit_msg>fix(arch::x86_64): use PAddr debug formatter<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (eliza@elizas.website)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! `x86_64` architecture-specific implementation.
// pub mod cpu;
pub mod drivers;
pub mod interrupts;

#[path = "../x86_all/bda.rs"] pub mod bda;
#[path = "../x86_all/multiboot2.rs"] pub mod multiboot2;

pub const ARCH_BITS: u8 = 64;

extern {
    // TODO: It would be really nice if there was a less ugly way of doing
    // this... (read: after the Revolution when we add memory regions to the
    // heap programmatically.)
    #[link_name = "heap_base_addr"]
    #[linkage = "external"]
    pub static HEAP_BASE: *mut u8;
    #[link_name = "heap_top_addr"]
    #[linkage = "external"]
    pub static HEAP_TOP: *mut u8;
    // Of course, we will still need to export the kernel stack addresses like
    // this, but it would be nice if they could be, i dont know, not mut u8s
    // pointers, like God intended.
    #[link_name = "stack_base"]
    pub static STACK_BASE: *mut u8;
    #[link_name = "stack_top"]
    pub static STACK_TOP: *mut u8;
}

use memory::PAddr;

/// Trampoline to ensure we have a correct stack frame for calling [`arch_init`]
///
/// I have no idea why this works, but it does.
///
/// [`arch_init`]: fn.arch_init
#[naked]
#[no_mangle]
pub unsafe extern "C" fn long_mode_init() {
    asm!("movabsq $$(stack_top), %rsp");
    asm!("mov ax, 0
          mov ss, ax
          mov ds, ax
          mov es, ax
          mov fs, ax
          mov gs, ax
          call arch_init"
        :::: "intel");

}

/// Entry point for architecture-specific kernel init
///
/// This expects to be passed the address of a valid
/// Multiboot 2 info struct. It's the bootloader's responsibility to ensure
/// that this is passed in the correct register as expected by the calling
/// convention (`edi` on x86). If this isn't there, you can expect to have a
/// bad problem and not go to space today.
#[no_mangle]
pub extern "C" fn arch_init(multiboot_addr: PAddr) {
    use cpu::{control_regs, msr};
    use params::{InitParams, mem};

    kinfoln!(dots: " . ", "Beginning `arch_init()` for x86_64");

    ::io::term::CONSOLE.lock().clear();
    ::logger::initialize()
        .expect("Could not initialize logger!");

    // -- Unpack multiboot tag ------------------------------------------------
    kinfoln!( dots: " . "
            , "trying to unpack multiboot info at {:?}"
            , multiboot_addr);

    // try to interpret the structure at the multiboot address as a multiboot
    // info struct. if it's invalid, fail.
    let boot_info
        = unsafe { multiboot2::Info::from(multiboot_addr)
                    .expect("Could not unpack multiboot2 information!") };

    // Extract ELF sections tag from the multiboot info
    let elf_sections_tag
        = boot_info.elf_sections()
                   .expect("ELF sections tag required!");

    kinfoln!(dots: " . ", "Detecting kernel ELF sections:");

    // Extract kernel ELF sections from  multiboot info
    let mut n_elf_sections = 0;

    let kernel_begin
        = elf_sections_tag.sections()
            // .filter(|s| s.is_allocated())
            .map(|s| {
                kinfoln!( dots: " . . ", "{}", s );
                kinfoln!( dots: " . . . ", "flags: [ {:?} ]", s.flags());
                s.address() })
            .min()
            .expect("Could not find kernel start section!\
                    \nSomething is deeply wrong.");

    let kernel_end
        = elf_sections_tag.sections()
            // .filter(|s| s.is_allocated())
            .map(|s| { n_elf_sections += 1; s.end_address() })
            .max()
            .expect("Could not find kernel end section!\
                    \nSomething is deeply wrong.");

    kinfoln!( dots: " . ", "Detected {} kernel ELF sections.", n_elf_sections);
    kinfoln!( dots: " . . ", "Kernel begins at {:#p} and ends at {:#p}."
            , kernel_begin, kernel_end );

    let multiboot_end = multiboot_addr + boot_info.length as u64;

    kinfoln!( dots: " . . ", "Multiboot info begins at {:#x} and ends at {:#x}."
            , multiboot_addr, multiboot_end);

    let mut params = InitParams { kernel_base: kernel_begin
                            , kernel_top: kernel_end
                            , multiboot_start: Some(multiboot_addr)
                            , multiboot_end: Some(multiboot_end)
                            , heap_base: unsafe { PAddr::from(HEAP_BASE) }
                            , heap_top: unsafe { PAddr::from(HEAP_TOP) }
                            , stack_base: unsafe { PAddr::from(STACK_BASE) }
                            , stack_top: unsafe { PAddr::from(STACK_TOP) }
                            , elf_sections: Some(elf_sections_tag.sections())
                            , ..Default::default()
                        };

    // Extract the memory map tag from the multiboot info
    let mem_map = boot_info.mem_map()
                           .expect("Memory map tag required!");

    kinfoln!(dots: " . ", "Detected memory areas:");
    for area in mem_map {
        kinfoln!( dots: " . . ", "{}", area);
        let a: mem::Area = area.into();
        if a.is_usable == true { params.mem_map.push(a); }
    }

     //-- enable flags needed for paging ------------------------------------
     unsafe {
        //  control_regs::cr0::enable_write_protect(true);
        //  kinfoln!(dots: " . ", "Page write protect ENABED" );

        let efer = msr::read(msr::IA32_EFER);
        trace!("EFER = {:#x}", efer);
        msr::write(msr::IA32_EFER, efer | (1 << 11));
        let efer = msr::read(msr::IA32_EFER);
        trace!("EFER = {:#x}", efer);
        kinfoln!(dots: " . ", "Page no execute bit ENABLED");
     }

    kinfoln!(dots: " . ", "Transferring to `kernel_init()`.");
    ::kernel_init(&params);
}
<|endoftext|>


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

//! Memory management functions. The base functions align to a pointer-width, so they shouldn't
//! be used for anything that requires an alignment greater than that.

use std::rt::heap;
use std::mem;
use std::intrinsics::abort;
use std::io::{self, Write};
use std::ptr;

pub unsafe fn allocate_bytes(size: usize) -> *mut u8 {
    let ret = heap::allocate(size, mem::align_of::<usize>());
    if ret.is_null() {
        let _ = writeln!(io::stderr(), "Failed to allocate memory (size={})", size);
        abort();
    }
    ret
}

pub unsafe fn allocate<T>(n: usize) -> *mut T {
    allocate_bytes(n * mem::size_of::<T>()) as *mut T
}

pub unsafe fn reallocate(old: *mut u8, old_size: usize, new_size: usize) -> *mut u8 {
    let ret = heap::reallocate(old, old_size, new_size, mem::align_of::<usize>());
    if ret.is_null() {
        let _ = writeln!(io::stderr(), "Failed to reallocate memory (old size={}, new size={})",
                         old_size, new_size);
        abort();
    }
    ret
}

pub unsafe fn deallocate(ptr: *mut u8, size: usize) {
    heap::deallocate(ptr, size, mem::align_of::<usize>());
}

/// Allocate for temporary storage. Ensures that the allocations are
/// freed when the structure drops
pub struct TmpAllocator {
    mark: *mut Marker
}

struct Marker {
    next: *mut Marker,
    size: usize
}

impl TmpAllocator {
    pub fn new() -> TmpAllocator {
        TmpAllocator {
            mark: ptr::null_mut()
        }
    }

    pub unsafe fn allocate_bytes(&mut self, size: usize) -> *mut u8 {
        let total_size = size + mem::size_of::<Marker>();
        let ptr = allocate_bytes(size);

        let mark = ptr as *mut Marker;
        (*mark).size = total_size;
        (*mark).next = self.mark;

        self.mark = mark;

        ptr.offset(mem::size_of::<Marker>() as isize)
    }

    /// Allocate space for n instances of `T`
    pub unsafe fn allocate<T>(&mut self, n: usize) -> *mut T {
        self.allocate_bytes(n * mem::size_of::<T>()) as *mut T
    }

    /// Allocates space for n1+n2 instances of `T` and returns a pair of pointers.
    pub unsafe fn allocate_2<T>(&mut self, n1: usize, n2: usize) -> (*mut T, *mut T) {
        let x = self.allocate(n1 + n2);
        let y = x.offset(n1 as isize);
        (x, y)
    }
}

impl Drop for TmpAllocator {
    fn drop(&mut self) {
        unsafe {
            let mut next;
            let mut mark = self.mark;
            while !mark.is_null() {
                next = (*mark).next;
                let size = (*mark).size;
                deallocate(mark as *mut u8, size);
                mark = next;
            }
        }
    }
}
<commit_msg>Fix temporary allocator<commit_after>// Copyright 2015 The Ramp Developers
//
//    Licensed under the Apache License, Version 2.0 (the "License");
//    you may not use this file except in compliance with the License.
//    You may obtain a copy of the License at
//
//        http://www.apache.org/licenses/LICENSE-2.0
//
//    Unless required by applicable law or agreed to in writing, software
//    distributed under the License is distributed on an "AS IS" BASIS,
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//    See the License for the specific language governing permissions and
//    limitations under the License.

//! Memory management functions. The base functions align to a pointer-width, so they shouldn't
//! be used for anything that requires an alignment greater than that.

use std::rt::heap;
use std::mem;
use std::intrinsics::abort;
use std::io::{self, Write};
use std::ptr;

pub unsafe fn allocate_bytes(size: usize) -> *mut u8 {
    let ret = heap::allocate(size, mem::align_of::<usize>());
    if ret.is_null() {
        let _ = writeln!(io::stderr(), "Failed to allocate memory (size={})", size);
        abort();
    }
    ptr::write_bytes(ret, 0, size);
    ret
}

pub unsafe fn allocate<T>(n: usize) -> *mut T {
    allocate_bytes(n * mem::size_of::<T>()) as *mut T
}

pub unsafe fn reallocate(old: *mut u8, old_size: usize, new_size: usize) -> *mut u8 {
    let ret = heap::reallocate(old, old_size, new_size, mem::align_of::<usize>());
    if ret.is_null() {
        let _ = writeln!(io::stderr(), "Failed to reallocate memory (old size={}, new size={})",
                         old_size, new_size);
        abort();
    }
    if old_size < new_size {
        ptr::write_bytes(ret.offset(old_size as isize), 0, new_size - old_size);
    }
    ret
}

pub unsafe fn deallocate(ptr: *mut u8, size: usize) {
    heap::deallocate(ptr, size, mem::align_of::<usize>());
}

/// Allocate for temporary storage. Ensures that the allocations are
/// freed when the structure drops
pub struct TmpAllocator {
    mark: *mut Marker
}

struct Marker {
    next: *mut Marker,
    size: usize
}

impl TmpAllocator {
    pub fn new() -> TmpAllocator {
        TmpAllocator {
            mark: ptr::null_mut()
        }
    }

    pub unsafe fn allocate_bytes(&mut self, size: usize) -> *mut u8 {
        let size = size + mem::size_of::<Marker>();
        let ptr = allocate_bytes(size);

        let mark = ptr as *mut Marker;
        (*mark).size = size;
        (*mark).next = self.mark;

        self.mark = mark;

        ptr.offset(mem::size_of::<Marker>() as isize)
    }

    /// Allocate space for n instances of `T`
    pub unsafe fn allocate<T>(&mut self, n: usize) -> *mut T {
        self.allocate_bytes(n * mem::size_of::<T>()) as *mut T
    }

    /// Allocates space for n1+n2 instances of `T` and returns a pair of pointers.
    pub unsafe fn allocate_2<T>(&mut self, n1: usize, n2: usize) -> (*mut T, *mut T) {
        let x = self.allocate(n1 + n2);
        let y = x.offset(n1 as isize);
        (x, y)
    }
}

impl Drop for TmpAllocator {
    fn drop(&mut self) {
        unsafe {
            let mut next;
            let mut mark = self.mark;
            while !mark.is_null() {
                next = (*mark).next;
                let size = (*mark).size;
                deallocate(mark as *mut u8, size);
                mark = next;
            }
        }
    }
}
<|endoftext|>


<commit_before>// ==== Memory Map =====
const RAM_BEG: u16 = 0x0000;
const RAM_SIZE: usize = 0x0800;
const RAM_END: u16 = 0x07ff;

const RAM_MIRROR_ONE_BEG: u16 = 0x0800;
const RAM_MIRROR_ONE_SIZE: u16 = 0x0800;
const RAM_MIRROR_ONE_END: u16 = 0x0fff;

const RAM_MIRROR_TWO_BEG: u16 = 0x1000;
const RAM_MIRROR_TWO_SIZE: u16 = 0x0800;
const RAM_MIRROR_TWO_END: u16 = 0x17ff;

const RAM_MIRROR_THREE_BEG: u16 = 0x1800;
const RAM_MIRROR_THREE_SIZE: u16 = 0x0800;
const RAM_MIRROR_THREE_END: u16 = 0x1fff;

const PPU_REGS_BEG: u16 = 0x2000;
const PPU_REGS_SIZE: u16 = 0x0008;
const PPU_REGS_END: u16 = 0x2007;

const PPU_MIRRORS_BEG: u16 = 0x2008;
const PPU_MIRRORS_SIZE: u16 = 0x1ff8;
const PPU_MIRRORS_END: u16 = 0x3fff;

const APU_REGS_BEG: u16 =

pub struct Memory {
    ram: Box<[u8]>,

    cart_rom: Box<[u8]>,
}

impl Memory {
    pub fn new(cart_rom: &Vec<u8>) -> Memory {
        Memory {
            ram: vec![0u8; RAM_SIZE].into_boxed_slice(),

            // once the size of the cartridge is known, it shouldn't change
            cart_rom: vec![0u8; cart_rom.len()].into_boxed_slice(),
        }
    }

    pub fn read_byte(address: PhysAddr) -> u8 {

    }

    pub fn write_byte() {}
}

fn map_addr(virt_addr: u16) -> PhysAddr {
    match virt_addr{

    }
}
<commit_msg>Start mem_map function<commit_after>// ==== Memory Map =====
const RAM_BEG: u16 = 0x0000;
const RAM_SIZE: usize = 0x0800;
const RAM_END: u16 = 0x07ff;

const RAM_MIRROR_ONE_BEG: u16 = 0x0800;
const RAM_MIRROR_ONE_SIZE: u16 = 0x0800;
const RAM_MIRROR_ONE_END: u16 = 0x0fff;

const RAM_MIRROR_TWO_BEG: u16 = 0x1000;
const RAM_MIRROR_TWO_SIZE: u16 = 0x0800;
const RAM_MIRROR_TWO_END: u16 = 0x17ff;

const RAM_MIRROR_THREE_BEG: u16 = 0x1800;
const RAM_MIRROR_THREE_SIZE: u16 = 0x0800;
const RAM_MIRROR_THREE_END: u16 = 0x1fff;

const PPU_REGS_BEG: u16 = 0x2000;
const PPU_REGS_SIZE: u16 = 0x0008;
const PPU_REGS_END: u16 = 0x2007;

const PPU_MIRRORS_BEG: u16 = 0x2008;
const PPU_MIRRORS_SIZE: u16 = 0x1ff8;
const PPU_MIRRORS_END: u16 = 0x3fff;

const APU_REGS_BEG: u16 = 0x4000;
const APU_REGS_SIZE: u16 = 0x0020;
const APU_REGS_END: u16 = 0x401f;

const CARTRIDGE_SPACE_BEG: u16 = 0x4020;
const CARTRIDGE_SPACE_SIZE: u16 = 0xBFE0;
const CARTRIDGE_SPACE_END: u16 = 0xffff;

pub struct Memory {
    ram: Box<[u8]>,

    cart_rom: Box<[u8]>,
}

impl Memory {
    pub fn new(cart_rom: &Vec<u8>) -> Memory {
        Memory {
            ram: vec![0u8; RAM_SIZE].into_boxed_slice(),

            // once the size of the cartridge is known, it shouldn't change
            cart_rom: vec![0u8; cart_rom.len()].into_boxed_slice(),
        }
    }

    pub fn read_word(address: PhysAddr) -> u8 {
    }

    pub fn write_word() {}
}

fn map_addr(virt_addr: u16) -> PhysAddr {
    match virt_addr{
        _ => panic!("Unrecognized Physical Address {:#x}", virt_addr),
    }
}

pub enum PhysAddr {
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Averages/Arithmetic_mean

fn mean(list: &[f64]) -> f64 {
   let mut sum: f64 = 0.0;
   for &i in list.iter() {
      sum += i;
   }

   let list_len = list.len();
   if list_len == 0 {
      fail!("Expected a non-empty list")
   }
   else {
      sum / (list_len as f64)
   }
}

fn main() {
   let input = ~[3.0, 1.0, 4.0, 1.0, 5.0, 9.0];
   let result = mean(input);

   // 3.833333
   println!("{}", result);
}
<commit_msg>Improved arithmetic_mean and added tests<commit_after>// Implements http://rosettacode.org/wiki/Averages/Arithmetic_mean

fn mean(list: &[f64]) -> Option<f64> {
    match list.len() {
        0 => None,
        n => {
            let sum = list.iter().fold(0 as f64, |acc, &x| acc + x);
            Some(sum / n as f64)
        }
    }
}

fn main() {
    let input = vec!(3.0, 1.0, 4.0, 1.0, 5.0, 9.0);

    // This should be 3.833333
    let mean = mean(input.as_slice()).unwrap();
    println!("{}", mean);
}

#[test]
fn simple_test() {
    let vector = vec!(1.0, 2.0, 3.0, 4.0, 5.0);
    assert!(mean(vector.as_slice()).unwrap() == 3.0);
}

#[test]
fn mean_empty_list() {
    let empty_vec = vec!();
    assert!(mean(empty_vec.as_slice()).is_none());
}<|endoftext|>


<commit_before>pub(crate) mod device;
pub(self) mod surface;
pub(self) mod error;
pub(self) mod session;
mod render;

pub use device::{DrmDevice, DrmSource, DeviceHandler, device_bind, Planes};
pub use surface::DrmSurface;
pub use error::Error as DrmError;
pub use session::DrmDeviceObserver;
pub use render::{DrmRenderSurface, Error as DrmRenderError};<commit_msg>drm: Fixup missing reexport<commit_after>pub(crate) mod device;
pub(self) mod surface;
pub(self) mod error;
pub(self) mod session;
mod render;

pub use device::{DrmDevice, DrmSource, DeviceHandler, device_bind, Planes, DevPath};
pub use surface::DrmSurface;
pub use error::Error as DrmError;
pub use session::DrmDeviceObserver;
pub use render::{DrmRenderSurface, Error as DrmRenderError};<|endoftext|>


<commit_before>

native "rust" mod rustrt {
    fn rust_list_files(str path) -> vec[str];
    fn rust_list_files_ivec(str path) -> @str[];
    fn rust_file_is_dir(str path) -> int;
}

fn list_dir(str path) -> str[] { ret *rustrt::rust_list_files(path + "*"); }

fn path_is_absolute(str p) -> bool {
    ret str::char_at(p, 0u) == '/'
        || (str::char_at(p, 1u) == ':' && str::char_at(p, 2u) == '\\');
}

/* FIXME: win32 path handling actually accepts '/' or '\' and has subtly
 * different semantics for each. Since we build on mingw, we are usually
 * dealing with /-separated paths. But the whole interface to splitting and
 * joining pathnames needs a bit more abstraction on win32. Possibly a vec or
 * tag type.
 */
const char path_sep = '/';

const char alt_path_sep = '\\';
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>stdlib: Use the right upcall in win32_fs. Maybe puts out burning tinderbox?<commit_after>

native "rust" mod rustrt {
    fn rust_list_files(str path) -> vec[str];
    fn rust_list_files_ivec(str path) -> @str[];
    fn rust_file_is_dir(str path) -> int;
}

fn list_dir(str path) -> str[] {
    ret *rustrt::rust_list_files_ivec(path + "*");
}

fn path_is_absolute(str p) -> bool {
    ret str::char_at(p, 0u) == '/'
        || (str::char_at(p, 1u) == ':' && str::char_at(p, 2u) == '\\');
}

/* FIXME: win32 path handling actually accepts '/' or '\' and has subtly
 * different semantics for each. Since we build on mingw, we are usually
 * dealing with /-separated paths. But the whole interface to splitting and
 * joining pathnames needs a bit more abstraction on win32. Possibly a vec or
 * tag type.
 */
const char path_sep = '/';

const char alt_path_sep = '\\';
// Local Variables:
// mode: rust;
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>//! A minimal representation of payload information

#[derive(Debug, RustcEncodable, RustcDecodable, Default)]
pub struct Payload {
  pub sender: Sender,
  pub organization: Option<Organization>,
  pub repository: Option<Repository>
}

#[derive(Debug, Default, RustcEncodable, RustcDecodable)]
pub struct Sender {
  pub login: String
}

#[derive(Debug, Default, RustcEncodable, RustcDecodable)]
pub struct Organization {
  pub login: String
}

#[derive(Debug, Default, RustcEncodable, RustcDecodable)]
pub struct Repository {
  pub name: String,
  pub full_name: String,
  pub organization: Organization
}
<commit_msg>reps dont need to be encodable, organization is not always provided with repo<commit_after>//! A minimal representation of payload information

#[derive(Debug, RustcDecodable, Default)]
pub struct Ping {
  pub hook: Payload
}

#[derive(Debug, RustcDecodable, Default)]
pub struct Payload {
  pub sender: Sender,
  pub organization: Option<Organization>,
  pub repository: Option<Repository>
}

#[derive(Debug, Default, RustcDecodable)]
pub struct Sender {
  pub login: String
}

#[derive(Debug, Default, RustcDecodable)]
pub struct Organization {
  pub login: String
}

#[derive(Debug, Default, RustcDecodable)]
pub struct Repository {
  pub name: String,
  pub full_name: String,
  pub organization: Option<Organization>
}
<|endoftext|>


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

use cast;
use iterator::Iterator;
use libc;
use ops::Drop;
use option::{Option, Some, None};
use ptr::RawPtr;
use ptr;
use str::StrSlice;
use vec::ImmutableVector;

/// The representation of a C String.
///
/// This structure wraps a `*libc::c_char`, and will automatically free the
/// memory it is pointing to when it goes out of scope.
pub struct CString {
    priv buf: *libc::c_char,
    priv owns_buffer_: bool,
}

impl CString {
    /// Create a C String from a pointer.
    pub fn new(buf: *libc::c_char, owns_buffer: bool) -> CString {
        CString { buf: buf, owns_buffer_: owns_buffer }
    }

    /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
    pub unsafe fn unwrap(self) -> *libc::c_char {
        let mut c_str = self;
        c_str.owns_buffer_ = false;
        c_str.buf
    }

    /// Calls a closure with a reference to the underlying `*libc::c_char`.
    ///
    /// # Failure
    ///
    /// Fails if the CString is null.
    pub fn with_ref<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
        if self.buf.is_null() { fail!("CString is null!"); }
        f(self.buf)
    }

    /// Calls a closure with a mutable reference to the underlying `*libc::c_char`.
    ///
    /// # Failure
    ///
    /// Fails if the CString is null.
    pub fn with_mut_ref<T>(&mut self, f: &fn(*mut libc::c_char) -> T) -> T {
        if self.buf.is_null() { fail!("CString is null!"); }
        f(unsafe { cast::transmute_mut_unsafe(self.buf) })
    }

    /// Returns true if the CString is a null.
    pub fn is_null(&self) -> bool {
        self.buf.is_null()
    }

    /// Returns true if the CString is not null.
    pub fn is_not_null(&self) -> bool {
        self.buf.is_not_null()
    }

    /// Returns whether or not the `CString` owns the buffer.
    pub fn owns_buffer(&self) -> bool {
        self.owns_buffer_
    }

    /// Converts the CString into a `&[u8]` without copying.
    ///
    /// # Failure
    ///
    /// Fails if the CString is null.
    pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
        if self.buf.is_null() { fail!("CString is null!"); }
        unsafe {
            let len = libc::strlen(self.buf) as uint;
            cast::transmute((self.buf, len + 1))
        }
    }

    /// Return a CString iterator.
    fn iter<'a>(&'a self) -> CStringIterator<'a> {
        CStringIterator {
            ptr: self.buf,
            lifetime: unsafe { cast::transmute(self.buf) },
        }
    }
}

impl Drop for CString {
    fn drop(&self) {
        if self.owns_buffer_ {
            unsafe {
                libc::free(self.buf as *libc::c_void)
            }
        }
    }
}

/// A generic trait for converting a value to a CString.
pub trait ToCStr {
    /// Create a C String.
    fn to_c_str(&self) -> CString;
}

impl<'self> ToCStr for &'self str {
    #[inline]
    fn to_c_str(&self) -> CString {
        self.as_bytes().to_c_str()
    }
}

impl<'self> ToCStr for &'self [u8] {
    fn to_c_str(&self) -> CString {
        do self.as_imm_buf |self_buf, self_len| {
            unsafe {
                let buf = libc::malloc(self_len as u64 + 1) as *mut u8;
                if buf.is_null() {
                    fail!("failed to allocate memory!");
                }

                ptr::copy_memory(buf, self_buf, self_len);
                *ptr::mut_offset(buf, self_len as int) = 0;

                CString::new(buf as *libc::c_char, true)
            }
        }
    }
}

/// External iterator for a CString's bytes.
///
/// Use with the `std::iterator` module.
pub struct CStringIterator<'self> {
    priv ptr: *libc::c_char,
    priv lifetime: &'self libc::c_char, // FIXME: #5922
}

impl<'self> Iterator<libc::c_char> for CStringIterator<'self> {
    fn next(&mut self) -> Option<libc::c_char> {
        let ch = unsafe { *self.ptr };
        if ch == 0 {
            None
        } else {
            self.ptr = ptr::offset(self.ptr, 1);
            Some(ch)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use libc;
    use ptr;
    use option::{Some, None};

    #[test]
    fn test_to_c_str() {
        do "".to_c_str().with_ref |buf| {
            unsafe {
                assert_eq!(*ptr::offset(buf, 0), 0);
            }
        }

        do "hello".to_c_str().with_ref |buf| {
            unsafe {
                assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 5), 0);
            }
        }
    }

    #[test]
    fn test_is_null() {
        let c_str = CString::new(ptr::null(), false);
        assert!(c_str.is_null());
        assert!(!c_str.is_not_null());
    }

    #[test]
    fn test_unwrap() {
        let c_str = "hello".to_c_str();
        unsafe { libc::free(c_str.unwrap() as *libc::c_void) }
    }

    #[test]
    fn test_with_ref() {
        let c_str = "hello".to_c_str();
        let len = unsafe { c_str.with_ref(|buf| libc::strlen(buf)) };
        assert!(!c_str.is_null());
        assert!(c_str.is_not_null());
        assert_eq!(len, 5);
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_with_ref_empty_fail() {
        let c_str = unsafe { CString::new(ptr::null(), false) };
        c_str.with_ref(|_| ());
    }

    #[test]
    fn test_iterator() {
        let c_str = "".to_c_str();
        let mut iter = c_str.iter();
        assert_eq!(iter.next(), None);

        let c_str = "hello".to_c_str();
        let mut iter = c_str.iter();
        assert_eq!(iter.next(), Some('h' as libc::c_char));
        assert_eq!(iter.next(), Some('e' as libc::c_char));
        assert_eq!(iter.next(), Some('l' as libc::c_char));
        assert_eq!(iter.next(), Some('l' as libc::c_char));
        assert_eq!(iter.next(), Some('o' as libc::c_char));
        assert_eq!(iter.next(), None);
    }
}
<commit_msg>std: Make CString::new unsafe b/c it can mutate a *T ptr<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use cast;
use iterator::Iterator;
use libc;
use ops::Drop;
use option::{Option, Some, None};
use ptr::RawPtr;
use ptr;
use str::StrSlice;
use vec::ImmutableVector;

/// The representation of a C String.
///
/// This structure wraps a `*libc::c_char`, and will automatically free the
/// memory it is pointing to when it goes out of scope.
pub struct CString {
    priv buf: *libc::c_char,
    priv owns_buffer_: bool,
}

impl CString {
    /// Create a C String from a pointer.
    pub unsafe fn new(buf: *libc::c_char, owns_buffer: bool) -> CString {
        CString { buf: buf, owns_buffer_: owns_buffer }
    }

    /// Unwraps the wrapped `*libc::c_char` from the `CString` wrapper.
    pub unsafe fn unwrap(self) -> *libc::c_char {
        let mut c_str = self;
        c_str.owns_buffer_ = false;
        c_str.buf
    }

    /// Calls a closure with a reference to the underlying `*libc::c_char`.
    ///
    /// # Failure
    ///
    /// Fails if the CString is null.
    pub fn with_ref<T>(&self, f: &fn(*libc::c_char) -> T) -> T {
        if self.buf.is_null() { fail!("CString is null!"); }
        f(self.buf)
    }

    /// Calls a closure with a mutable reference to the underlying `*libc::c_char`.
    ///
    /// # Failure
    ///
    /// Fails if the CString is null.
    pub fn with_mut_ref<T>(&mut self, f: &fn(*mut libc::c_char) -> T) -> T {
        if self.buf.is_null() { fail!("CString is null!"); }
        f(unsafe { cast::transmute_mut_unsafe(self.buf) })
    }

    /// Returns true if the CString is a null.
    pub fn is_null(&self) -> bool {
        self.buf.is_null()
    }

    /// Returns true if the CString is not null.
    pub fn is_not_null(&self) -> bool {
        self.buf.is_not_null()
    }

    /// Returns whether or not the `CString` owns the buffer.
    pub fn owns_buffer(&self) -> bool {
        self.owns_buffer_
    }

    /// Converts the CString into a `&[u8]` without copying.
    ///
    /// # Failure
    ///
    /// Fails if the CString is null.
    pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
        if self.buf.is_null() { fail!("CString is null!"); }
        unsafe {
            let len = libc::strlen(self.buf) as uint;
            cast::transmute((self.buf, len + 1))
        }
    }

    /// Return a CString iterator.
    fn iter<'a>(&'a self) -> CStringIterator<'a> {
        CStringIterator {
            ptr: self.buf,
            lifetime: unsafe { cast::transmute(self.buf) },
        }
    }
}

impl Drop for CString {
    fn drop(&self) {
        if self.owns_buffer_ {
            unsafe {
                libc::free(self.buf as *libc::c_void)
            }
        }
    }
}

/// A generic trait for converting a value to a CString.
pub trait ToCStr {
    /// Create a C String.
    fn to_c_str(&self) -> CString;
}

impl<'self> ToCStr for &'self str {
    #[inline]
    fn to_c_str(&self) -> CString {
        self.as_bytes().to_c_str()
    }
}

impl<'self> ToCStr for &'self [u8] {
    fn to_c_str(&self) -> CString {
        do self.as_imm_buf |self_buf, self_len| {
            unsafe {
                let buf = libc::malloc(self_len as u64 + 1) as *mut u8;
                if buf.is_null() {
                    fail!("failed to allocate memory!");
                }

                ptr::copy_memory(buf, self_buf, self_len);
                *ptr::mut_offset(buf, self_len as int) = 0;

                CString::new(buf as *libc::c_char, true)
            }
        }
    }
}

/// External iterator for a CString's bytes.
///
/// Use with the `std::iterator` module.
pub struct CStringIterator<'self> {
    priv ptr: *libc::c_char,
    priv lifetime: &'self libc::c_char, // FIXME: #5922
}

impl<'self> Iterator<libc::c_char> for CStringIterator<'self> {
    fn next(&mut self) -> Option<libc::c_char> {
        let ch = unsafe { *self.ptr };
        if ch == 0 {
            None
        } else {
            self.ptr = ptr::offset(self.ptr, 1);
            Some(ch)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use libc;
    use ptr;
    use option::{Some, None};

    #[test]
    fn test_to_c_str() {
        do "".to_c_str().with_ref |buf| {
            unsafe {
                assert_eq!(*ptr::offset(buf, 0), 0);
            }
        }

        do "hello".to_c_str().with_ref |buf| {
            unsafe {
                assert_eq!(*ptr::offset(buf, 0), 'h' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 1), 'e' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 2), 'l' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 3), 'l' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 4), 'o' as libc::c_char);
                assert_eq!(*ptr::offset(buf, 5), 0);
            }
        }
    }

    #[test]
    fn test_is_null() {
        let c_str = unsafe { CString::new(ptr::null(), false) };
        assert!(c_str.is_null());
        assert!(!c_str.is_not_null());
    }

    #[test]
    fn test_unwrap() {
        let c_str = "hello".to_c_str();
        unsafe { libc::free(c_str.unwrap() as *libc::c_void) }
    }

    #[test]
    fn test_with_ref() {
        let c_str = "hello".to_c_str();
        let len = unsafe { c_str.with_ref(|buf| libc::strlen(buf)) };
        assert!(!c_str.is_null());
        assert!(c_str.is_not_null());
        assert_eq!(len, 5);
    }

    #[test]
    #[should_fail]
    #[ignore(cfg(windows))]
    fn test_with_ref_empty_fail() {
        let c_str = unsafe { CString::new(ptr::null(), false) };
        c_str.with_ref(|_| ());
    }

    #[test]
    fn test_iterator() {
        let c_str = "".to_c_str();
        let mut iter = c_str.iter();
        assert_eq!(iter.next(), None);

        let c_str = "hello".to_c_str();
        let mut iter = c_str.iter();
        assert_eq!(iter.next(), Some('h' as libc::c_char));
        assert_eq!(iter.next(), Some('e' as libc::c_char));
        assert_eq!(iter.next(), Some('l' as libc::c_char));
        assert_eq!(iter.next(), Some('l' as libc::c_char));
        assert_eq!(iter.next(), Some('o' as libc::c_char));
        assert_eq!(iter.next(), None);
    }
}
<|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;
#[macro_use]
extern crate mime;
extern crate multipart;
extern crate papers;
extern crate hyper;
extern crate tokio_core;
#[macro_use]
extern crate serde_json as json;

use papers::error::Error;
use papers::http::*;

use futures::future;
use futures::{Future, Sink, Stream};
use futures::sync::mpsc;
use hyper::server;
use hyper::client;
use papers::papers::*;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

/// This is a simple service that fills two roles:
///
/// - serves the local directory
/// - it receives the generated PDF on the /callback endpoint
struct LocalServer {
    sender: mpsc::Sender<()>,
}

impl LocalServer {
    pub fn new(sender: mpsc::Sender<()>) -> LocalServer {
        LocalServer {
            sender,
        }
    }
}

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

    fn call(&self, req: Self::Request) -> Self::Future {
        let path = req.path().to_string();
        let sender = self.sender.clone();
        match path.as_str() {
            "/callback" => {
                println!("Callback endpoint called");
                let headers = req.headers().clone();
                println!("Headers: {:?}", headers);
                Box::new(req.get_body_bytes().from_err().map(|bytes| {
                    println!("{} bytes received", bytes.len());
                    let mut multipart = multipart::server::Multipart::from_request(MultipartRequest(headers, bytes))
                        .expect("could not parse multipart");
                    {
                        let mut entry = multipart
                            .read_entry()
                            .expect("could not parse next field")
                            .expect("next field is empty");
                        if entry.name != "file" {
                            panic!("{:?} {:?}", entry.name, entry.data.as_text().unwrap())
                        } else {
                            let file = entry.data.as_file().unwrap();
                            let filename = file.filename.clone().unwrap();
                            let mut out = File::create(Path::new(&filename)).unwrap();
                            let bytes = file.bytes().collect::<Result<Vec<u8>, _>>().unwrap();
                            out.write_all(&bytes).unwrap()
                        }
                    }
                    multipart.save().with_dir(".");
                }).and_then(move |_| {
                    sender.send(()).map_err(|_| "Channel error".into())
                }).map(|_| {
                    server::Response::new()
                }).or_else(|err: Error| {
                    println!("Error on callback endpoint: {}", err);
                    future::ok(server::Response::new())
                }))
            },
            path => {
                let file_path = path.trim_left_matches('/');
                let file = File::open(Path::new(file_path)).expect(&format!("couln't read {}", path));
                let bytes: Vec<u8> = file.bytes().collect::<Result<Vec<u8>, _>>().unwrap();
                Box::new(future::ok(server::Response::new().with_body(bytes)))
            }
        }
    }
}

fn main() {
    let (sender, receiver) = mpsc::channel::<()>(5);

    std::thread::spawn(|| {
        papers::server::Server::new().with_port(8019).start();
    });

    std::thread::spawn(move || {
        hyper::server::Http::new()
            .bind(&"127.0.0.1:8733".parse().unwrap(), move || Ok(LocalServer::new(sender.clone())))
            .expect("could not bind to 127.0.0.1:8733")
            .run()
            .unwrap();
    });

    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 assets: Vec<PapersUri> = ::std::fs::read_dir(::std::path::Path::new("."))
        .unwrap()
        .map(|entry| entry.unwrap())
        .filter(|entry| entry.filename().to_str().unwrap() != "template.tex")
        .map(|entry| {
            let filename = entry.filename();
            let filename = filename.to_str().unwrap();
            PapersUri(format!("http://127.0.0.1:8733/{}", filename).parse().unwrap())
        })
        .collect();

    let document_spec = DocumentSpec {
        assets_urls: assets,
        callback_url: PapersUri("http://127.0.0.1:8733/callback".parse().unwrap()),
        output_filename: "out.pdf".to_string(),
        template_url: PapersUri("http://127.0.0.1:8733/template.tex".parse().unwrap()),
        variables: variables,
    };

    let mut core = tokio_core::reactor::Core::new().unwrap();
    let client = hyper::Client::new(&core.handle());
    let req = client::Request::new(
            hyper::Method::Post,
            "http://127.0.0.1:8019/submit".parse().unwrap()
        ).with_body( json::to_string(&document_spec).unwrap().into() )
        .with_header(hyper::header::ContentType(mime!(Application/Json)));
    let work = client.request(req).then(|_| receiver.into_future());
    core.run(work).unwrap();
}
<commit_msg>🐛 Fix read_dir call<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 futures;
#[macro_use]
extern crate mime;
extern crate multipart;
extern crate papers;
extern crate hyper;
extern crate tokio_core;
#[macro_use]
extern crate serde_json as json;

use papers::error::Error;
use papers::http::*;

use futures::future;
use futures::{Future, Sink, Stream};
use futures::sync::mpsc;
use hyper::server;
use hyper::client;
use papers::papers::*;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;

/// This is a simple service that fills two roles:
///
/// - serves the local directory
/// - it receives the generated PDF on the /callback endpoint
struct LocalServer {
    sender: mpsc::Sender<()>,
}

impl LocalServer {
    pub fn new(sender: mpsc::Sender<()>) -> LocalServer {
        LocalServer {
            sender,
        }
    }
}

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

    fn call(&self, req: Self::Request) -> Self::Future {
        let path = req.path().to_string();
        let sender = self.sender.clone();
        match path.as_str() {
            "/callback" => {
                println!("Callback endpoint called");
                let headers = req.headers().clone();
                println!("Headers: {:?}", headers);
                Box::new(req.get_body_bytes().from_err().map(|bytes| {
                    println!("{} bytes received", bytes.len());
                    let mut multipart = multipart::server::Multipart::from_request(MultipartRequest(headers, bytes))
                        .expect("could not parse multipart");
                    {
                        let mut entry = multipart
                            .read_entry()
                            .expect("could not parse next field")
                            .expect("next field is empty");
                        if entry.name != "file" {
                            panic!("{:?} {:?}", entry.name, entry.data.as_text().unwrap())
                        } else {
                            let file = entry.data.as_file().unwrap();
                            let filename = file.filename.clone().unwrap();
                            let mut out = File::create(Path::new(&filename)).unwrap();
                            let bytes = file.bytes().collect::<Result<Vec<u8>, _>>().unwrap();
                            out.write_all(&bytes).unwrap()
                        }
                    }
                    multipart.save().with_dir(".");
                }).and_then(move |_| {
                    sender.send(()).map_err(|_| "Channel error".into())
                }).map(|_| {
                    server::Response::new()
                }).or_else(|err: Error| {
                    println!("Error on callback endpoint: {}", err);
                    future::ok(server::Response::new())
                }))
            },
            path => {
                let file_path = path.trim_left_matches('/');
                let file = File::open(Path::new(file_path)).expect(&format!("couln't read {}", path));
                let bytes: Vec<u8> = file.bytes().collect::<Result<Vec<u8>, _>>().unwrap();
                Box::new(future::ok(server::Response::new().with_body(bytes)))
            }
        }
    }
}

fn main() {
    let (sender, receiver) = mpsc::channel::<()>(5);

    std::thread::spawn(|| {
        papers::server::Server::new().with_port(8019).start();
    });

    std::thread::spawn(move || {
        hyper::server::Http::new()
            .bind(&"127.0.0.1:8733".parse().unwrap(), move || Ok(LocalServer::new(sender.clone())))
            .expect("could not bind to 127.0.0.1:8733")
            .run()
            .unwrap();
    });

    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 assets: Vec<PapersUri> = ::std::fs::read_dir(::std::path::Path::new("."))
        .unwrap()
        .map(|entry| entry.unwrap())
        .filter(|entry| entry.file_name().to_str().unwrap() != "template.tex")
        .map(|entry| {
            let filename = entry.file_name();
            let filename = filename.to_str().unwrap();
            PapersUri(format!("http://127.0.0.1:8733/{}", filename).parse().unwrap())
        })
        .collect();

    let document_spec = DocumentSpec {
        assets_urls: assets,
        callback_url: PapersUri("http://127.0.0.1:8733/callback".parse().unwrap()),
        output_filename: "out.pdf".to_string(),
        template_url: PapersUri("http://127.0.0.1:8733/template.tex".parse().unwrap()),
        variables: variables,
    };

    let mut core = tokio_core::reactor::Core::new().unwrap();
    let client = hyper::Client::new(&core.handle());
    let req = client::Request::new(
            hyper::Method::Post,
            "http://127.0.0.1:8019/submit".parse().unwrap()
        ).with_body( json::to_string(&document_spec).unwrap().into() )
        .with_header(hyper::header::ContentType(mime!(Application/Json)));
    let work = client.request(req).then(|_| receiver.into_future());
    core.run(work).unwrap();
}
<|endoftext|>


<commit_before>extern crate c_ares_sys;
extern crate libc;

use std::ffi::CStr;
use std::fmt;
use std::marker::PhantomData;
use std::ptr;
use std::slice;
use std::str;

use error::AresError ;
use utils::ares_error;

/// The result of a successful SOA lookup.
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct SOAResult {
    soa_reply: *mut c_ares_sys::Struct_ares_soa_reply,
    phantom: PhantomData<c_ares_sys::Struct_ares_soa_reply>,
}

impl SOAResult {
    /// Obtain an `SOAResult` from the response to an SOA lookup.
    pub fn parse_from(data: &[u8]) -> Result<SOAResult, AresError> {
        let mut soa_reply: *mut c_ares_sys::Struct_ares_soa_reply =
            ptr::null_mut();
        let parse_status = unsafe {
            c_ares_sys::ares_parse_soa_reply(
                data.as_ptr(),
                data.len() as libc::c_int,
                &mut soa_reply)
        };
        if parse_status != c_ares_sys::ARES_SUCCESS {
            Err(ares_error(parse_status))
        } else {
            let result = SOAResult::new(soa_reply);
            Ok(result)
        }
    }

    fn new(soa_reply: *mut c_ares_sys::Struct_ares_soa_reply) -> SOAResult {
        SOAResult {
            soa_reply: soa_reply,
            phantom: PhantomData,
        }
    }

    /// Returns the name server from this `SOAResult`.
    pub fn name_server(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr((*self.soa_reply).nsname);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }

    /// Returns the hostmaster from this `SOAResult`.
    pub fn hostmaster(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr((*self.soa_reply).hostmaster);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }

    /// Returns the serial number from this `SOAResult`.
    pub fn serial(&self) -> u32 {
        unsafe { (*self.soa_reply).serial }
    }

    /// Returns the refresh time from this `SOAResult`.
    pub fn refresh(&self) -> u32 {
        unsafe { (*self.soa_reply).refresh }
    }

    /// Returns the retry time from this `SOAResult`.
    pub fn retry(&self) -> u32 {
        unsafe { (*self.soa_reply).retry }
    }

    /// Returns the expire time from this `SOAResult`.
    pub fn expire(&self) -> u32 {
        unsafe { (*self.soa_reply).expire }
    }

    /// Returns the minimum time-to-live from this `SOAResult`.
    pub fn min_ttl(&self) -> u32 {
        unsafe { (*self.soa_reply).minttl }
    }
}

impl fmt::Display for SOAResult {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "Name server: {}, ", self.name_server()));
        try!(write!(fmt, "Hostmaster: {}, ", self.hostmaster()));
        try!(write!(fmt, "Serial: {}, ", self.serial()));
        try!(write!(fmt, "Refresh: {}, ", self.refresh()));
        try!(write!(fmt, "Retry: {}, ", self.retry()));
        try!(write!(fmt, "Expire: {}, ", self.expire()));
        try!(write!(fmt, "Minimum time-to-live: {}", self.min_ttl()));
        Ok(())
    }
}

impl Drop for SOAResult {
    fn drop(&mut self) {
        unsafe {
            c_ares_sys::ares_free_data(self.soa_reply as *mut libc::c_void);
        }
    }
}

unsafe impl Send for SOAResult { }
unsafe impl Sync for SOAResult { }

pub unsafe extern "C" fn query_soa_callback<F>(
    arg: *mut libc::c_void,
    status: libc::c_int,
    _timeouts: libc::c_int,
    abuf: *mut libc::c_uchar,
    alen: libc::c_int)
    where F: FnOnce(Result<SOAResult, AresError>) + 'static {
    let result = if status != c_ares_sys::ARES_SUCCESS {
        Err(ares_error(status))
    } else {
        let data = slice::from_raw_parts(abuf, alen as usize);
        SOAResult::parse_from(data)
    };
    let handler = Box::from_raw(arg as *mut F);
    handler(result);
}
<commit_msg>Whitespace<commit_after>extern crate c_ares_sys;
extern crate libc;

use std::ffi::CStr;
use std::fmt;
use std::marker::PhantomData;
use std::ptr;
use std::slice;
use std::str;

use error::AresError;
use utils::ares_error;

/// The result of a successful SOA lookup.
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct SOAResult {
    soa_reply: *mut c_ares_sys::Struct_ares_soa_reply,
    phantom: PhantomData<c_ares_sys::Struct_ares_soa_reply>,
}

impl SOAResult {
    /// Obtain an `SOAResult` from the response to an SOA lookup.
    pub fn parse_from(data: &[u8]) -> Result<SOAResult, AresError> {
        let mut soa_reply: *mut c_ares_sys::Struct_ares_soa_reply =
            ptr::null_mut();
        let parse_status = unsafe {
            c_ares_sys::ares_parse_soa_reply(
                data.as_ptr(),
                data.len() as libc::c_int,
                &mut soa_reply)
        };
        if parse_status != c_ares_sys::ARES_SUCCESS {
            Err(ares_error(parse_status))
        } else {
            let result = SOAResult::new(soa_reply);
            Ok(result)
        }
    }

    fn new(soa_reply: *mut c_ares_sys::Struct_ares_soa_reply) -> SOAResult {
        SOAResult {
            soa_reply: soa_reply,
            phantom: PhantomData,
        }
    }

    /// Returns the name server from this `SOAResult`.
    pub fn name_server(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr((*self.soa_reply).nsname);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }

    /// Returns the hostmaster from this `SOAResult`.
    pub fn hostmaster(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr((*self.soa_reply).hostmaster);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }

    /// Returns the serial number from this `SOAResult`.
    pub fn serial(&self) -> u32 {
        unsafe { (*self.soa_reply).serial }
    }

    /// Returns the refresh time from this `SOAResult`.
    pub fn refresh(&self) -> u32 {
        unsafe { (*self.soa_reply).refresh }
    }

    /// Returns the retry time from this `SOAResult`.
    pub fn retry(&self) -> u32 {
        unsafe { (*self.soa_reply).retry }
    }

    /// Returns the expire time from this `SOAResult`.
    pub fn expire(&self) -> u32 {
        unsafe { (*self.soa_reply).expire }
    }

    /// Returns the minimum time-to-live from this `SOAResult`.
    pub fn min_ttl(&self) -> u32 {
        unsafe { (*self.soa_reply).minttl }
    }
}

impl fmt::Display for SOAResult {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "Name server: {}, ", self.name_server()));
        try!(write!(fmt, "Hostmaster: {}, ", self.hostmaster()));
        try!(write!(fmt, "Serial: {}, ", self.serial()));
        try!(write!(fmt, "Refresh: {}, ", self.refresh()));
        try!(write!(fmt, "Retry: {}, ", self.retry()));
        try!(write!(fmt, "Expire: {}, ", self.expire()));
        try!(write!(fmt, "Minimum time-to-live: {}", self.min_ttl()));
        Ok(())
    }
}

impl Drop for SOAResult {
    fn drop(&mut self) {
        unsafe {
            c_ares_sys::ares_free_data(self.soa_reply as *mut libc::c_void);
        }
    }
}

unsafe impl Send for SOAResult { }
unsafe impl Sync for SOAResult { }

pub unsafe extern "C" fn query_soa_callback<F>(
    arg: *mut libc::c_void,
    status: libc::c_int,
    _timeouts: libc::c_int,
    abuf: *mut libc::c_uchar,
    alen: libc::c_int)
    where F: FnOnce(Result<SOAResult, AresError>) + 'static {
    let result = if status != c_ares_sys::ARES_SUCCESS {
        Err(ares_error(status))
    } else {
        let data = slice::from_raw_parts(abuf, alen as usize);
        SOAResult::parse_from(data)
    };
    let handler = Box::from_raw(arg as *mut F);
    handler(result);
}
<|endoftext|>


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

use eutil::fptr_is_null;
use libc::{size_t, c_int, c_ushort,c_void};
use libc::types::os::arch::c95::wchar_t;
use mem::{new0,newarray0,delete,deletearray};
use std::mem;
use std::ptr;
use std::slice;
use std::string;
use std::str;
use types::{cef_string_utf16_t, cef_string_utf8_t, cef_string_wide_t};
use types::{cef_string_userfree_utf16_t, cef_string_userfree_utf8_t, cef_string_userfree_wide_t};

//cef_string

#[no_mangle]
extern "C" fn string_wide_dtor(str: *mut wchar_t) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
extern "C" fn string_utf8_dtor(str: *mut u8) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
extern "C" fn string_utf16_dtor(str: *mut c_ushort) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_free(cs: *mut cef_string_userfree_wide_t) {
   cef_string_wide_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_free(cs: *mut cef_string_userfree_utf8_t) {
   cef_string_utf8_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_free(cs: *mut cef_string_userfree_utf16_t) {
   cef_string_utf16_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_clear(cs: *mut cef_string_utf8_t) {
    unsafe {
        if !fptr_is_null(mem::transmute((*cs).dtor)) {
            let dtor = (*cs).dtor;
            dtor((*cs).str);
        }
        (*cs).length = 0;
        (*cs).str = 0 as *mut u8;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_alloc() -> *mut cef_string_utf8_t {
    #![inline(never)]
    new0::<cef_string_utf8_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_set(src: *const u8, src_len: size_t, output: *mut cef_string_utf8_t, copy: c_int) -> c_int {
    cef_string_utf8_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<u8>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = string_utf8_dtor;
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice(src, src_len as uint, |result| {
            match str::from_utf8(result) {
                 Some(enc) => {
                      let conv = enc.utf16_units().collect::<Vec<u16>>();
                      cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1);
                      1
                 },
                 None => 0
            }
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_to_utf8(src: *const u16, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice(src, src_len as uint, |ustr| {
            match string::String::from_utf16(ustr) {
                Some(str) => {
                    cef_string_utf8_set(str.as_bytes().as_ptr(), str.len() as size_t, output, 1);
                    1 as c_int
                },
                None =>  0 as c_int
            }
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_clear(cs: *mut cef_string_utf16_t) {
    unsafe {
        if !fptr_is_null(mem::transmute((*cs).dtor)) {
            let dtor = (*cs).dtor;
            dtor((*cs).str);
        }
        (*cs).length = 0;
        (*cs).str = 0 as *mut c_ushort;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_alloc() -> *mut cef_string_utf16_t {
    #![inline(never)]
    new0::<cef_string_utf16_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_set(src: *const c_ushort, src_len: size_t, output: *mut cef_string_utf16_t, copy: c_int) -> c_int {
    cef_string_utf16_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<c_ushort>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = string_utf16_dtor;
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_wide_clear(cs: *mut cef_string_wide_t) {
    unsafe {
        if !fptr_is_null(mem::transmute((*cs).dtor)) {
            let dtor = (*cs).dtor;
            dtor((*cs).str);
        }
        (*cs).length = 0;
        (*cs).str = 0 as *mut wchar_t;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_alloc() -> *mut cef_string_wide_t {
    #![inline(never)]
    new0::<cef_string_wide_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_wide_set(src: *const wchar_t, src_len: size_t, output: *mut cef_string_wide_t, copy: c_int) -> c_int {
    cef_string_wide_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<wchar_t>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = string_wide_dtor;
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}
<commit_msg>embedding: implement cef_string_utf16_cmp()<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use eutil::fptr_is_null;
use libc::{size_t, c_int, c_ushort,c_void};
use libc::types::os::arch::c95::wchar_t;
use mem::{new0,newarray0,delete,deletearray};
use std::mem;
use std::ptr;
use std::slice;
use std::string;
use std::str;
use types::{cef_string_utf16_t, cef_string_utf8_t, cef_string_wide_t};
use types::{cef_string_userfree_utf16_t, cef_string_userfree_utf8_t, cef_string_userfree_wide_t};

//cef_string

#[no_mangle]
extern "C" fn string_wide_dtor(str: *mut wchar_t) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
extern "C" fn string_utf8_dtor(str: *mut u8) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
extern "C" fn string_utf16_dtor(str: *mut c_ushort) {
  deletearray(str as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_free(cs: *mut cef_string_userfree_wide_t) {
   cef_string_wide_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_free(cs: *mut cef_string_userfree_utf8_t) {
   cef_string_utf8_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_free(cs: *mut cef_string_userfree_utf16_t) {
   cef_string_utf16_clear(cs);
   delete(cs as *mut c_void)
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_clear(cs: *mut cef_string_utf8_t) {
    unsafe {
        if !fptr_is_null(mem::transmute((*cs).dtor)) {
            let dtor = (*cs).dtor;
            dtor((*cs).str);
        }
        (*cs).length = 0;
        (*cs).str = 0 as *mut u8;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf8_alloc() -> *mut cef_string_utf8_t {
    #![inline(never)]
    new0::<cef_string_utf8_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_set(src: *const u8, src_len: size_t, output: *mut cef_string_utf8_t, copy: c_int) -> c_int {
    cef_string_utf8_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<u8>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = string_utf8_dtor;
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf8_to_utf16(src: *const u8, src_len: size_t, output: *mut cef_string_utf16_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice(src, src_len as uint, |result| {
            match str::from_utf8(result) {
                 Some(enc) => {
                      let conv = enc.utf16_units().collect::<Vec<u16>>();
                      cef_string_utf16_set(conv.as_ptr(), conv.len() as size_t, output, 1);
                      1
                 },
                 None => 0
            }
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_to_utf8(src: *const u16, src_len: size_t, output: *mut cef_string_utf8_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice(src, src_len as uint, |ustr| {
            match string::String::from_utf16(ustr) {
                Some(str) => {
                    cef_string_utf8_set(str.as_bytes().as_ptr(), str.len() as size_t, output, 1);
                    1 as c_int
                },
                None =>  0 as c_int
            }
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_clear(cs: *mut cef_string_utf16_t) {
    unsafe {
        if !fptr_is_null(mem::transmute((*cs).dtor)) {
            let dtor = (*cs).dtor;
            dtor((*cs).str);
        }
        (*cs).length = 0;
        (*cs).str = 0 as *mut c_ushort;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_utf16_alloc() -> *mut cef_string_utf16_t {
    #![inline(never)]
    new0::<cef_string_utf16_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_set(src: *const c_ushort, src_len: size_t, output: *mut cef_string_utf16_t, copy: c_int) -> c_int {
    cef_string_utf16_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<c_ushort>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = string_utf16_dtor;
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}

#[no_mangle]
pub extern "C" fn cef_string_utf16_cmp(a: *const cef_string_utf16_t, b: *const cef_string_utf16_t) -> c_int {
    unsafe {
       slice::raw::buf_as_slice(mem::transmute((*a).str), (*a).length as uint, |astr:&[u16]| {
            slice::raw::buf_as_slice(mem::transmute((*b).str), (*b).length as uint, |bstr:&[u16]| {
                  match astr.cmp(&bstr) {
                       Less => -1,
                       Equal => 0,
                       Greater => 1
                  }
            })
       })
    }
}

#[no_mangle]
pub extern "C" fn cef_string_wide_clear(cs: *mut cef_string_wide_t) {
    unsafe {
        if !fptr_is_null(mem::transmute((*cs).dtor)) {
            let dtor = (*cs).dtor;
            dtor((*cs).str);
        }
        (*cs).length = 0;
        (*cs).str = 0 as *mut wchar_t;
        (*cs).dtor = mem::transmute(0 as *const u8);
    }
}

#[no_mangle]
pub extern "C" fn cef_string_userfree_wide_alloc() -> *mut cef_string_wide_t {
    #![inline(never)]
    new0::<cef_string_wide_t>(1)
}

#[no_mangle]
pub extern "C" fn cef_string_wide_set(src: *const wchar_t, src_len: size_t, output: *mut cef_string_wide_t, copy: c_int) -> c_int {
    cef_string_wide_clear(output);
    unsafe {
       if copy != 0 {
           if !src.is_null() && src_len > 0 {
             (*output).str = newarray0::<wchar_t>(src_len + 1);
             if (*output).str.is_null() {
                 return 0;
             }

             ptr::copy_memory((*output).str, src, src_len as uint);
             (*output).length = src_len;
             (*output).dtor = string_wide_dtor;
           }
       } else {
         (*output).str = mem::transmute(src);
         (*output).length = src_len;
         (*output).dtor = mem::transmute(0 as *const u8);
       }
    }
    return 1;
}
<|endoftext|>


<commit_before>// (C)opyleft 2013 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#[desc = "A fast Bloom filter implementation."];
#[license = "BSD"];
#[crate_id="bloomfilter#0.1"];
#[crate_type = "rlib"];
#[warn(non_camel_case_types, non_uppercase_statics, non_uppercase_statics, unnecessary_qualification, managed_heap_memory)];

extern crate collections;
extern crate extra;

use std::num;
use std::rand;
use std::rand::Rng;
use collections::bitv;

struct SipHashKey {
    k1: u64,
    k2: u64
}

impl SipHashKey {
    fn new_random() -> SipHashKey {
        let mut rng = rand::task_rng();
        SipHashKey {
            k1: rand::Rand::rand(& mut rng),
            k2: rand::Rand::rand(& mut rng)
        }
    }
}

/// Bloom filter structure
pub struct Bloom {
    priv bitmap: bitv::Bitv,
    priv bitmap_bits: u64,
    priv k_num: uint,
    priv skeys: [SipHashKey, ..2]
}

impl Bloom {

/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: uint, items_count: uint) -> Bloom {
        assert!(bitmap_size > 0u && items_count > 0u);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::new(bitmap_bits as uint, false);
        let skeys = [ SipHashKey::new_random(), SipHashKey::new_random() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            skeys: skeys
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: uint, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: uint, fp_p: f64) -> uint {
        assert!(items_count > 0u);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = num::ln(2.0f64);
        let log2_2 = log2 * log2;
        ((items_count as f64) * num::ln(fp_p) / (-8.0 * log2_2)).ceil() as uint
    }

/// Record the presence of an item.
    pub fn set<T: Hash>(& mut self, item: T) {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T: Hash>(&self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T: Hash>(&mut self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: uint) -> uint {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * num::ln(2.0f64).ceil()) as uint;
        num::max(k_num, 1)
    }

    fn bloom_hash<T: Hash>(&self, hashes: & mut [u64, ..2],
                  item: &T, k_i: uint) -> u64 {
        if k_i < 2 {
            let skey = self.skeys[k_i];
            let hash = (*item).hash_keyed(skey.k1, skey.k2);
            hashes[k_i] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<commit_msg>num::max => cmp::max<commit_after>// (C)opyleft 2013 Frank Denis

/*!
 * Bloom filter for Rust
 *
 * This is a simple but fast Bloom filter implementation, that requires only
 * 2 hash functions, generated with SipHash-2-4 using randomized keys.
 */

#[desc = "A fast Bloom filter implementation."];
#[license = "BSD"];
#[crate_id="bloomfilter#0.1"];
#[crate_type = "rlib"];
#[warn(non_camel_case_types, non_uppercase_statics, non_uppercase_statics, unnecessary_qualification, managed_heap_memory)];

extern crate collections;
extern crate extra;

use std::cmp;
use std::num;
use std::rand;
use std::rand::Rng;
use collections::bitv;

struct SipHashKey {
    k1: u64,
    k2: u64
}

impl SipHashKey {
    fn new_random() -> SipHashKey {
        let mut rng = rand::task_rng();
        SipHashKey {
            k1: rand::Rand::rand(& mut rng),
            k2: rand::Rand::rand(& mut rng)
        }
    }
}

/// Bloom filter structure
pub struct Bloom {
    priv bitmap: bitv::Bitv,
    priv bitmap_bits: u64,
    priv k_num: uint,
    priv skeys: [SipHashKey, ..2]
}

impl Bloom {

/// Create a new bloom filter structure.
/// bitmap_size is the size in bytes (not bits) that will be allocated in memory
/// items_count is an estimation of the maximum number of items to store.
    pub fn new(bitmap_size: uint, items_count: uint) -> Bloom {
        assert!(bitmap_size > 0u && items_count > 0u);
        let bitmap_bits = (bitmap_size as u64) * 8u64;
        let k_num = Bloom::optimal_k_num(bitmap_bits, items_count);
        let bitmap = bitv::Bitv::new(bitmap_bits as uint, false);
        let skeys = [ SipHashKey::new_random(), SipHashKey::new_random() ];
        Bloom {
            bitmap: bitmap,
            bitmap_bits: bitmap_bits,
            k_num: k_num,
            skeys: skeys
        }
    }

/// Create a new bloom filter structure.
/// items_count is an estimation of the maximum number of items to store.
/// fp_p is the wanted rate of false positives, in ]0.0, 1.0[
    pub fn new_for_fp_rate(items_count: uint, fp_p: f64) -> Bloom {
        let bitmap_size = Bloom::compute_bitmap_size(items_count, fp_p);
        Bloom::new(bitmap_size, items_count)
    }

/// Compute a recommended bitmap size for items_count items
/// and a fp_p rate of false positives.
/// fp_p obviously has to be within the ]0.0, 1.0[ range.
    pub fn compute_bitmap_size(items_count: uint, fp_p: f64) -> uint {
        assert!(items_count > 0u);
        assert!(fp_p > 0.0 && fp_p < 1.0);
        let log2 = num::ln(2.0f64);
        let log2_2 = log2 * log2;
        ((items_count as f64) * num::ln(fp_p) / (-8.0 * log2_2)).ceil() as uint
    }

/// Record the presence of an item.
    pub fn set<T: Hash>(& mut self, item: T) {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            self.bitmap.set(bit_offset, true);
        }
    }

/// Check if an item is present in the set.
/// There can be false positives, but no false negatives.
    pub fn check<T: Hash>(&self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                return false;
            }
        }
        true
    }

/// Record the presence of an item in the set,
/// and return the previous state of this item.
    pub fn check_and_set<T: Hash>(&mut self, item: T) -> bool {
        let mut hashes = [ 0u64, 0u64 ];
        let mut found = true;
        for k_i in range(0u, self.k_num) {
            let bit_offset = (self.bloom_hash(& mut hashes, &item, k_i)
                              % self.bitmap_bits) as uint;
            if self.bitmap.get(bit_offset) == false {
                found = false;
                self.bitmap.set(bit_offset, true);
            }
        }
        found
    }

    fn optimal_k_num(bitmap_bits: u64, items_count: uint) -> uint {
        let m = bitmap_bits as f64;
        let n = items_count as f64;
        let k_num = (m / n * num::ln(2.0f64).ceil()) as uint;
        cmp::max(k_num, 1)
    }

    fn bloom_hash<T: Hash>(&self, hashes: & mut [u64, ..2],
                  item: &T, k_i: uint) -> u64 {
        if k_i < 2 {
            let skey = self.skeys[k_i];
            let hash = (*item).hash_keyed(skey.k1, skey.k2);
            hashes[k_i] = hash;
            hash
        } else {
            hashes[0] + (((k_i as u64) * hashes[1]) % 0xffffffffffffffc5)
        }
    }
}

#[test]
fn bloom_test_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check(key) == false);
    bloom.set(&key);
    assert!(bloom.check(key.clone()) == true);
}

#[test]
fn bloom_test_check_and_set() {
    let mut bloom = Bloom::new(10, 80);
    let key = &rand::task_rng().gen_ascii_str(16u);
    assert!(bloom.check_and_set(key) == false);
    assert!(bloom.check_and_set(key.clone()) == true);
}
<|endoftext|>


<commit_before>#![feature(default_type_params)]

extern crate test;
extern crate time;
extern crate collections;

use collections::HashMap;
use std::hash::sip::SipHasher;
use std::os::args;
use test::black_box;
use time::precise_time_ns;

struct Eratostenes {
    count: u64,
    map: HashMap<u64, u64, SipHasher>,
}

impl Iterator<u64> for Eratostenes {
    fn next(&mut self) -> Option<u64> {
        loop {
            self.count += 1;
            let q = self.count;

            match self.map.pop(&q) {
                None => {
                    self.map.insert(q * q, q);

                    return Some(q);
                },
                Some(p) => {
                    let mut x = p + q;

                    while self.map.contains_key(&x) {
                        x += p;
                    }

                    self.map.insert(x, p);
                }
            }
        }
    }
}

fn eratostenes(capacity: uint) -> Eratostenes {
    Eratostenes {
        count: 1,
        map: HashMap::with_capacity(capacity),
    }
}

#[inline]
fn f() -> u64 {
    let target = 10000;
    eratostenes(target).nth(target).unwrap()
}

fn main() {
    match args().as_slice() {
        [_] => {
            println!("{}", f());
        },
        [_, ref iters] => {
            let iters: u64 = from_str(iters.as_slice()).unwrap();

            let start = precise_time_ns();
            for _ in range(0, iters) {
                black_box(f());
            }
            let end = precise_time_ns();

            println!("{}", end - start);
        },
        _ => unreachable!(),
    }
}
<commit_msg>007.rs: Use std::collections instead of the collections crate<commit_after>#![feature(default_type_params)]

extern crate test;
extern crate time;

use std::collections::HashMap;
use std::hash::sip::SipHasher;
use std::os::args;
use test::black_box;
use time::precise_time_ns;

struct Eratostenes {
    count: u64,
    map: HashMap<u64, u64, SipHasher>,
}

impl Iterator<u64> for Eratostenes {
    fn next(&mut self) -> Option<u64> {
        loop {
            self.count += 1;
            let q = self.count;

            match self.map.pop(&q) {
                None => {
                    self.map.insert(q * q, q);

                    return Some(q);
                },
                Some(p) => {
                    let mut x = p + q;

                    while self.map.contains_key(&x) {
                        x += p;
                    }

                    self.map.insert(x, p);
                }
            }
        }
    }
}

fn eratostenes(capacity: uint) -> Eratostenes {
    Eratostenes {
        count: 1,
        map: HashMap::with_capacity(capacity),
    }
}

#[inline]
fn f() -> u64 {
    let target = 10000;
    eratostenes(target).nth(target).unwrap()
}

fn main() {
    match args().as_slice() {
        [_] => {
            println!("{}", f());
        },
        [_, ref iters] => {
            let iters: u64 = from_str(iters.as_slice()).unwrap();

            let start = precise_time_ns();
            for _ in range(0, iters) {
                black_box(f());
            }
            let end = precise_time_ns();

            println!("{}", end - start);
        },
        _ => unreachable!(),
    }
}
<|endoftext|>