<commit_before>use baseline::codegen::CondCode;
use cpu::asm;
use cpu::arm64::asm::*;
use cpu::arm64::reg::*;
use cpu::{Mem, Reg};
use lexer::position::Position;
use masm::{MacroAssembler, Label};
use mem::ptr_width;
use object::IntArray;
use os::signal::Trap;
use ty::MachineMode;
use vtable::VTable;

impl MacroAssembler {
    pub fn prolog(&mut self, stacksize: i32) {
        self.emit_u32(asm::stp_pre(1, REG_FP, REG_LR, REG_SP, -2));
        self.emit_u32(asm::add_reg(1, REG_FP, REG_SP, REG_ZERO));

        if stacksize > 0 {
            let scratch = get_scratch();
            self.load_int_const(MachineMode::Ptr, scratch, stacksize);
            self.emit_u32(asm::sub_reg(1, REG_SP, REG_SP, scratch));
        }
    }

    pub fn epilog(&mut self, stacksize: i32) {
        if stacksize > 0 {
            let scratch = get_scratch();
            self.load_int_const(MachineMode::Ptr, scratch, stacksize);
            self.emit_u32(asm::add_reg(1, REG_SP, REG_SP, scratch));
        }

        self.emit_u32(asm::add_reg(1, REG_SP, REG_FP, REG_ZERO));
        self.emit_u32(asm::ldp_post(1, REG_FP, REG_LR, REG_SP, 2));
        self.emit_u32(asm::ret());
    }

    pub fn direct_call(&mut self, ptr: *const u8) {
        let disp = self.add_addr(ptr);
        let pos = self.pos() as i32;

        let scratch = get_scratch();

        self.load_constpool(REG_RESULT, disp + pos);
        self.emit_u32(asm::br(scratch));
    }

    pub fn indirect_call(&mut self, index: u32) {
        let obj = REG_PARAMS[0];

        // REG_RESULT = [obj] (load vtable)
        self.load_mem(MachineMode::Ptr, REG_RESULT, Mem::Base(obj, 0));

        // calculate offset of VTable entry
        let disp = VTable::offset_of_method_table() + (index as i32) * ptr_width();

        // load vtable entry
        self.load_mem(MachineMode::Ptr, REG_RESULT, Mem::Base(REG_RESULT, disp));

        // call *REG_RESULT
        self.emit_u32(asm::blr(REG_RESULT));
    }

    pub fn load_array_elem(&mut self, mode: MachineMode, dest: Reg, array: Reg, index: Reg) {
        assert!(mode == MachineMode::Int32);

        self.load_mem(mode,
                      dest,
                      Mem::Index(array, index, mode.size(), IntArray::offset_of_data()));
    }

    pub fn store_array_elem(&mut self, mode: MachineMode, array: Reg, index: Reg, value: Reg) {
        assert!(mode == MachineMode::Int32);

        self.store_mem(MachineMode::Int32,
                       Mem::Index(array, index, 4, IntArray::offset_of_data()),
                       value);
    }

    pub fn test_if_nil_bailout(&mut self, pos: Position, reg: Reg) {
        self.cmp_reg(MachineMode::Ptr, reg, reg);

        let lbl = self.create_label();
        self.jump_if(CondCode::Zero, lbl);
        self.emit_bailout(lbl, Trap::NIL, pos);
    }

    pub fn test_if_nil(&mut self, reg: Reg) -> Label {
        self.cmp_reg(MachineMode::Ptr, reg, reg);

        let lbl = self.create_label();
        self.jump_if(CondCode::Zero, lbl);

        lbl
    }

    pub fn set(&mut self, dest: Reg, op: CondCode) {
        self.emit_u32(asm::cmp_imm(0, dest, 0, 0));
        self.emit_u32(asm::cset(0, dest, CondCode::NotEqual.into()));
    }

    pub fn cmp_mem(&mut self, mode: MachineMode, mem: Mem, rhs: Reg) {
        let scratch = get_scratch();

        self.load_mem(mode, scratch, mem);
        self.cmp_reg(mode, scratch, rhs);
    }

    pub fn cmp_mem_imm(&mut self, mode: MachineMode, mem: Mem, imm: i32) {
        let (scratch1, scratch2) = get_scratch_registers();

        self.load_mem(mode, scratch1, mem);
        self.load_int_const(mode, scratch2, imm);

        self.cmp_reg(mode, scratch1, scratch2);
    }

    pub fn cmp_reg(&mut self, mode: MachineMode, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::cmp_shreg(size_flag(mode), lhs, rhs, Shift::LSL, 0));
    }

    pub fn test_and_jump_if(&mut self, cond: CondCode, reg: Reg, lbl: Label) {
        assert!(cond == CondCode::Zero || cond == CondCode::NonZero);

        unimplemented!();
    }

    pub fn jump_if(&mut self, cond: CondCode, lbl: Label) {
        unimplemented!();
    }

    pub fn jump(&mut self, lbl: Label) {
        unimplemented!();
    }

    pub fn int_div(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::sdiv(0, dest, lhs, rhs));
    }

    pub fn int_mod(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::sdiv(0, dest, lhs, rhs));
        self.emit_u32(asm::msub(0, dest, dest, rhs, lhs));
    }

    pub fn int_mul(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::mul(0, dest, lhs, rhs));
    }

    pub fn int_add(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::add_reg(0, dest, lhs, rhs));
    }

    pub fn int_sub(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::sub_reg(0, dest, lhs, rhs));
    }

    pub fn int_shl(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::lslv(0, dest, lhs, rhs));
    }

    pub fn int_or(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::orr_shreg(0, dest, lhs, rhs, Shift::LSL, 0));
    }

    pub fn int_and(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::and_shreg(0, dest, lhs, rhs, Shift::LSL, 0));
    }

    pub fn int_xor(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::eor_shreg(0, dest, lhs, rhs, Shift::LSL, 0));
    }

    pub fn check_index_out_of_bounds(&mut self, pos: Position, array: Reg, index: Reg, temp: Reg) {
        self.load_mem(MachineMode::Int32,
                      temp,
                      Mem::Base(array, IntArray::offset_of_length()));
        self.cmp_reg(MachineMode::Int32, index, temp);

        let lbl = self.create_label();
        self.jump_if(CondCode::UnsignedGreaterEq, lbl);
        self.emit_bailout(lbl, Trap::INDEX_OUT_OF_BOUNDS, pos);
    }

    pub fn load_nil(&mut self, dest: Reg) {
        self.emit_u32(add_imm(1, dest, REG_ZERO, 0, 0));
    }

    pub fn load_mem(&mut self, mode: MachineMode, dest: Reg, mem: Mem) {
        unimplemented!();
    }

    pub fn store_mem(&mut self, mode: MachineMode, mem: Mem, src: Reg) {
        unimplemented!();
    }

    pub fn copy_reg(&mut self, mode: MachineMode, dest: Reg, src: Reg) {
        self.emit_u32(orr_shreg(size_flag(mode), dest, REG_ZERO, src, Shift::LSL, 0));
    }

    pub fn load_constpool(&mut self, dest: Reg, disp: i32) {
        unimplemented!();
    }

    pub fn call_reg(&mut self, reg: Reg) {
        self.emit_u32(blr(reg));
    }

    pub fn debug(&mut self) {
        unimplemented!();
    }

    pub fn load_int_const(&mut self, mode: MachineMode, dest: Reg, imm: i32) {
        let sf = size_flag(mode);
        let register_size = match mode {
            MachineMode::Int8 => unimplemented!(),
            MachineMode::Int32 => 32,
            MachineMode::Ptr => 64,
        };
        let imm = imm as i64 as u64;

        if fits_movz(imm, register_size) {
            self.emit_u32(movz(sf, dest, imm as u32, shift_movz(imm)));

        } else if fits_movn(imm, register_size) {
            self.emit_u32(movn(sf, dest, imm as u32, shift_movn(imm)));

        } else {
            unimplemented!();
        }
    }

    pub fn load_true(&mut self, dest: Reg) {
        self.emit_u32(movz(0, dest, 1, 0));
    }

    pub fn load_false(&mut self, dest: Reg) {
        self.emit_u32(movz(0, dest, 0, 0));
    }

    pub fn int_neg(&mut self, dest: Reg, src: Reg) {
        self.emit_u32(sub_reg(0, dest, REG_ZERO, src));
    }

    pub fn int_not(&mut self, dest: Reg, src: Reg) {
        self.emit_u32(orn_shreg(0, dest, REG_ZERO, src, Shift::LSL, 0));
    }

    pub fn bool_not(&mut self, dest: Reg, src: Reg) {
        let scratch = get_scratch();

        self.emit_u32(movz(0, scratch, 1, 0));
        self.emit_u32(eor_shreg(0, dest, src, scratch, Shift::LSL, 0));
        self.emit_u32(uxtb(dest, dest));
    }

    pub fn trap(&mut self, trap: Trap) {
        unimplemented!();
    }
}

fn size_flag(mode: MachineMode) -> u32 {
    match mode {
        MachineMode::Int8 |
        MachineMode::Int32 => 0,
        MachineMode::Ptr => 1,
    }
}

fn get_scratch() -> Reg {
    SCRATCH[0]
}

fn get_scratch_registers() -> (Reg, Reg) {
    (SCRATCH[0], SCRATCH[1])
}
<commit_msg>arm64: implemented more instructions<commit_after>use baseline::codegen::CondCode;
use cpu::asm;
use cpu::asm::*;
use cpu::reg::*;
use cpu::{Mem, Reg};
use lexer::position::Position;
use masm::{MacroAssembler, Label};
use mem::ptr_width;
use object::IntArray;
use os::signal::Trap;
use ty::MachineMode;
use vtable::VTable;

impl MacroAssembler {
    pub fn prolog(&mut self, stacksize: i32) {
        self.emit_u32(asm::stp_pre(1, REG_FP, REG_LR, REG_SP, -2));
        self.emit_u32(asm::add_reg(1, REG_FP, REG_SP, REG_ZERO));

        if stacksize > 0 {
            let scratch = get_scratch();
            self.load_int_const(MachineMode::Ptr, scratch, stacksize);
            self.emit_u32(asm::sub_reg(1, REG_SP, REG_SP, scratch));
        }
    }

    pub fn epilog(&mut self, stacksize: i32) {
        if stacksize > 0 {
            let scratch = get_scratch();
            self.load_int_const(MachineMode::Ptr, scratch, stacksize);
            self.emit_u32(asm::add_reg(1, REG_SP, REG_SP, scratch));
        }

        self.emit_u32(asm::add_reg(1, REG_SP, REG_FP, REG_ZERO));
        self.emit_u32(asm::ldp_post(1, REG_FP, REG_LR, REG_SP, 2));
        self.emit_u32(asm::ret());
    }

    pub fn direct_call(&mut self, ptr: *const u8) {
        let disp = self.add_addr(ptr);
        let pos = self.pos() as i32;

        let scratch = get_scratch();

        self.load_constpool(REG_RESULT, disp + pos);
        self.emit_u32(asm::br(scratch));
    }

    pub fn indirect_call(&mut self, index: u32) {
        let obj = REG_PARAMS[0];

        // REG_RESULT = [obj] (load vtable)
        self.load_mem(MachineMode::Ptr, REG_RESULT, Mem::Base(obj, 0));

        // calculate offset of VTable entry
        let disp = VTable::offset_of_method_table() + (index as i32) * ptr_width();

        // load vtable entry
        self.load_mem(MachineMode::Ptr, REG_RESULT, Mem::Base(REG_RESULT, disp));

        // call *REG_RESULT
        self.emit_u32(asm::blr(REG_RESULT));
    }

    pub fn load_array_elem(&mut self, mode: MachineMode, dest: Reg, array: Reg, index: Reg) {
        assert!(mode == MachineMode::Int32);

        self.load_mem(mode,
                      dest,
                      Mem::Index(array, index, mode.size(), IntArray::offset_of_data()));
    }

    pub fn store_array_elem(&mut self, mode: MachineMode, array: Reg, index: Reg, value: Reg) {
        assert!(mode == MachineMode::Int32);

        self.store_mem(MachineMode::Int32,
                       Mem::Index(array, index, 4, IntArray::offset_of_data()),
                       value);
    }

    pub fn test_if_nil_bailout(&mut self, pos: Position, reg: Reg) {
        self.cmp_reg(MachineMode::Ptr, reg, reg);

        let lbl = self.create_label();
        self.jump_if(CondCode::Zero, lbl);
        self.emit_bailout(lbl, Trap::NIL, pos);
    }

    pub fn test_if_nil(&mut self, reg: Reg) -> Label {
        self.cmp_reg(MachineMode::Ptr, reg, reg);

        let lbl = self.create_label();
        self.jump_if(CondCode::Zero, lbl);

        lbl
    }

    pub fn set(&mut self, dest: Reg, op: CondCode) {
        self.emit_u32(asm::cmp_imm(0, dest, 0, 0));
        self.emit_u32(asm::cset(0, dest, CondCode::NotEqual.into()));
    }

    pub fn cmp_mem(&mut self, mode: MachineMode, mem: Mem, rhs: Reg) {
        let scratch = get_scratch();

        self.load_mem(mode, scratch, mem);
        self.cmp_reg(mode, scratch, rhs);
    }

    pub fn cmp_mem_imm(&mut self, mode: MachineMode, mem: Mem, imm: i32) {
        let (scratch1, scratch2) = get_scratch_registers();

        self.load_mem(mode, scratch1, mem);
        self.load_int_const(mode, scratch2, imm);

        self.cmp_reg(mode, scratch1, scratch2);
    }

    pub fn cmp_reg(&mut self, mode: MachineMode, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::cmp_shreg(size_flag(mode), lhs, rhs, Shift::LSL, 0));
    }

    pub fn test_and_jump_if(&mut self, cond: CondCode, reg: Reg, lbl: Label) {
        assert!(cond == CondCode::Zero || cond == CondCode::NonZero);

        unimplemented!();
    }

    pub fn jump_if(&mut self, cond: CondCode, lbl: Label) {
        unimplemented!();
    }

    pub fn jump(&mut self, lbl: Label) {
        unimplemented!();
    }

    pub fn int_div(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::sdiv(0, dest, lhs, rhs));
    }

    pub fn int_mod(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::sdiv(0, dest, lhs, rhs));
        self.emit_u32(asm::msub(0, dest, dest, rhs, lhs));
    }

    pub fn int_mul(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::mul(0, dest, lhs, rhs));
    }

    pub fn int_add(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::add_reg(0, dest, lhs, rhs));
    }

    pub fn int_sub(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::sub_reg(0, dest, lhs, rhs));
    }

    pub fn int_shl(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::lslv(0, dest, lhs, rhs));
    }

    pub fn int_or(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::orr_shreg(0, dest, lhs, rhs, Shift::LSL, 0));
    }

    pub fn int_and(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::and_shreg(0, dest, lhs, rhs, Shift::LSL, 0));
    }

    pub fn int_xor(&mut self, dest: Reg, lhs: Reg, rhs: Reg) {
        self.emit_u32(asm::eor_shreg(0, dest, lhs, rhs, Shift::LSL, 0));
    }

    pub fn check_index_out_of_bounds(&mut self, pos: Position, array: Reg, index: Reg, temp: Reg) {
        self.load_mem(MachineMode::Int32,
                      temp,
                      Mem::Base(array, IntArray::offset_of_length()));
        self.cmp_reg(MachineMode::Int32, index, temp);

        let lbl = self.create_label();
        self.jump_if(CondCode::UnsignedGreaterEq, lbl);
        self.emit_bailout(lbl, Trap::INDEX_OUT_OF_BOUNDS, pos);
    }

    pub fn load_nil(&mut self, dest: Reg) {
        self.emit_u32(add_imm(1, dest, REG_ZERO, 0, 0));
    }

    pub fn load_mem(&mut self, mode: MachineMode, dest: Reg, mem: Mem) {
        match mem {
            Mem::Local(offset) => {
                let scratch = get_scratch();
                self.load_int_const(MachineMode::Ptr, scratch, offset);

                let inst = match mode {
                    MachineMode::Int8 =>
                        asm::ldrb_ind(dest, REG_FP, scratch, LdStExtend::UXTW, 0),
                    MachineMode::Int32 =>
                        asm::ldrw_ind(dest, REG_FP, scratch, LdStExtend::LSL, 0),
                    MachineMode::Ptr =>
                        asm::ldrx_ind(dest, REG_FP, scratch, LdStExtend::LSL, 0),
                };

                self.emit_u32(inst);
            }

            Mem::Base(base, disp) => {
                let scratch = get_scratch();
                self.load_int_const(MachineMode::Ptr, scratch, disp);

                let inst = match mode {
                    MachineMode::Int8 =>
                        asm::ldrb_ind(dest, base, scratch, LdStExtend::UXTW, 0),
                    MachineMode::Int32 =>
                        asm::ldrw_ind(dest, base, scratch, LdStExtend::LSL, 0),
                    MachineMode::Ptr =>
                        asm::ldrx_ind(dest, base, scratch, LdStExtend::LSL, 0),
                };

                self.emit_u32(inst);
            }

            Mem::Index(base, index, scale, disp) => {
                assert!(mode.size() == scale);

                let scratch = get_scratch();
                self.load_int_const(MachineMode::Ptr, scratch, disp);
                self.emit_u32(asm::add_reg(1, scratch, scratch, base));

                let inst = match mode {
                    MachineMode::Int8 =>
                        asm::ldrb_ind(dest, scratch, index, LdStExtend::UXTW, 0),
                    MachineMode::Int32 =>
                        asm::ldrw_ind(dest, scratch, index, LdStExtend::LSL, 1),
                    MachineMode::Ptr =>
                        asm::ldrx_ind(dest, scratch, index, LdStExtend::LSL, 1),
                };

                self.emit_u32(inst);
            }
        }
    }

    pub fn store_mem(&mut self, mode: MachineMode, mem: Mem, src: Reg) {
        match mem {
            Mem::Local(offset) => {
                let scratch = get_scratch();
                self.load_int_const(MachineMode::Ptr, scratch, offset);

                let inst = match mode {
                    MachineMode::Int8 =>
                        asm::strb_ind(src, REG_FP, scratch, LdStExtend::UXTW, 0),
                    MachineMode::Int32 =>
                        asm::strw_ind(src, REG_FP, scratch, LdStExtend::LSL, 0),
                    MachineMode::Ptr =>
                        asm::strx_ind(src, REG_FP, scratch, LdStExtend::LSL, 0),
                };

                self.emit_u32(inst);
            }

            Mem::Base(base, disp) => {
                let scratch = get_scratch();
                self.load_int_const(MachineMode::Ptr, scratch, disp);

                let inst = match mode {
                    MachineMode::Int8 =>
                        asm::strb_ind(src, base, scratch, LdStExtend::UXTW, 0),
                    MachineMode::Int32 =>
                        asm::strw_ind(src, base, scratch, LdStExtend::LSL, 0),
                    MachineMode::Ptr =>
                        asm::strx_ind(src, base, scratch, LdStExtend::LSL, 0),
                };

                self.emit_u32(inst);
            }

            Mem::Index(base, index, scale, disp) => {
                assert!(mode.size() == scale);

                let scratch = get_scratch();
                self.load_int_const(MachineMode::Ptr, scratch, disp);
                self.emit_u32(asm::add_reg(1, scratch, scratch, base));

                let inst = match mode {
                    MachineMode::Int8 =>
                        asm::strb_ind(src, scratch, index, LdStExtend::UXTW, 0),
                    MachineMode::Int32 =>
                        asm::strw_ind(src, scratch, index, LdStExtend::LSL, 1),
                    MachineMode::Ptr =>
                        asm::strx_ind(src, scratch, index, LdStExtend::LSL, 1),
                };

                self.emit_u32(inst);
            }
        }
    }

    pub fn copy_reg(&mut self, mode: MachineMode, dest: Reg, src: Reg) {
        self.emit_u32(orr_shreg(size_flag(mode), dest, REG_ZERO, src, Shift::LSL, 0));
    }

    pub fn load_constpool(&mut self, dest: Reg, disp: i32) {
        self.emit_u32(asm::adr(dest, -disp));
    }

    pub fn call_reg(&mut self, reg: Reg) {
        self.emit_u32(asm::blr(reg));
    }

    pub fn debug(&mut self) {
        unimplemented!();
    }

    pub fn load_int_const(&mut self, mode: MachineMode, dest: Reg, imm: i32) {
        let sf = size_flag(mode);
        let register_size = match mode {
            MachineMode::Int8 => unimplemented!(),
            MachineMode::Int32 => 32,
            MachineMode::Ptr => 64,
        };
        let imm = imm as i64 as u64;

        if fits_movz(imm, register_size) {
            self.emit_u32(movz(sf, dest, imm as u32, shift_movz(imm)));

        } else if fits_movn(imm, register_size) {
            self.emit_u32(movn(sf, dest, imm as u32, shift_movn(imm)));

        } else {
            unimplemented!();
        }
    }

    pub fn load_true(&mut self, dest: Reg) {
        self.emit_u32(movz(0, dest, 1, 0));
    }

    pub fn load_false(&mut self, dest: Reg) {
        self.emit_u32(movz(0, dest, 0, 0));
    }

    pub fn int_neg(&mut self, dest: Reg, src: Reg) {
        self.emit_u32(sub_reg(0, dest, REG_ZERO, src));
    }

    pub fn int_not(&mut self, dest: Reg, src: Reg) {
        self.emit_u32(orn_shreg(0, dest, REG_ZERO, src, Shift::LSL, 0));
    }

    pub fn bool_not(&mut self, dest: Reg, src: Reg) {
        let scratch = get_scratch();

        self.emit_u32(movz(0, scratch, 1, 0));
        self.emit_u32(eor_shreg(0, dest, src, scratch, Shift::LSL, 0));
        self.emit_u32(uxtb(dest, dest));
    }

    pub fn trap(&mut self, trap: Trap) {
        unimplemented!();
    }
}

fn size_flag(mode: MachineMode) -> u32 {
    match mode {
        MachineMode::Int8 |
        MachineMode::Int32 => 0,
        MachineMode::Ptr => 1,
    }
}

fn get_scratch() -> Reg {
    SCRATCH[0]
}

fn get_scratch_registers() -> (Reg, Reg) {
    (SCRATCH[0], SCRATCH[1])
}
<|endoftext|>


<commit_before><commit_msg>Implement error conversion<commit_after><|endoftext|>


<commit_before>//! Traits for working with JavaScript objects.
//!
//! This module defines the [`Object`](Object) trait, which is implemented
//! by all object types in the [JavaScript type hierarchy][hierarchy]. This
//! trait provides key operations in the semantics of JavaScript objects,
//! such as getting and setting an object's properties.
//!
//! ## Property Keys
//!
//! Object properties are accessed by a _property key_, which in JavaScript
//! can be a string or [symbol][symbol]. (Neon does not yet have support for
//! symbols.) For convenience, the [`PropertyKey`](PropertyKey) trait allows
//! Neon programs to use various Rust string types, as well as numeric types,
//! as keys when accessing object properties, converting the keys to strings
//! as necessary:
//!
//! ```
//! # #[cfg(feature = "napi-1")] {
//! # use neon::prelude::*;
//! fn set_and_check<'a>(
//!     cx: &mut impl Context<'a>,
//!     obj: Handle<'a, JsObject>
//! ) -> JsResult<'a, JsValue> {
//!     let value = cx.string("hello!");
//!     // set property "17" with integer shorthand
//!     obj.set(cx, 17, value)?;
//!     // get property "17" with string shorthand
//!     // returns the same value ("hello!")
//!     obj.get(cx, "17")
//! }
//! # }
//! ```
//!
//! [hierarchy]: crate::types#the-javascript-type-hierarchy
//! [symbol]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

#[cfg(feature = "legacy-runtime")]
pub(crate) mod class;

#[cfg(feature = "legacy-runtime")]
pub use self::class::{Class, ClassDescriptor};
pub use self::traits::*;

#[cfg(feature = "legacy-runtime")]
mod traits {
    use crate::context::Context;
    use crate::handle::{Handle, Managed};
    use crate::result::{JsResult, NeonResult, Throw};
    use crate::types::utf8::Utf8;
    use crate::types::{build, JsArray, JsValue, Value};
    use neon_runtime::raw;

    /// A property key in a JavaScript object.
    pub trait PropertyKey {
        unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool;
        unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool;
    }

    impl PropertyKey for u32 {
        unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool {
            neon_runtime::object::get_index(out, obj, self)
        }

        unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool {
            neon_runtime::object::set_index(out, obj, self, val)
        }
    }

    impl<'a, K: Value> PropertyKey for Handle<'a, K> {
        unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool {
            neon_runtime::object::get(out, obj, self.to_raw())
        }

        unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool {
            neon_runtime::object::set(out, obj, self.to_raw(), val)
        }
    }

    impl<'a> PropertyKey for &'a str {
        unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool {
            let (ptr, len) = Utf8::from(self).into_small_unwrap().lower();
            neon_runtime::object::get_string(out, obj, ptr, len)
        }

        unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool {
            let (ptr, len) = Utf8::from(self).into_small_unwrap().lower();
            neon_runtime::object::set_string(out, obj, ptr, len, val)
        }
    }

    /// The trait of all object types.
    pub trait Object: Value {
        fn get<'a, V: Value, C: Context<'a>, K: PropertyKey>(
            &self,
            cx: &mut C,
            key: K,
        ) -> NeonResult<Handle<'a, V>> {
            let v: Handle<JsValue> =
                build(cx.env(), |out| unsafe { key.get_from(out, self.to_raw()) })?;
            v.downcast_or_throw(cx)
        }

        fn get_own_property_names<'a, C: Context<'a>>(&self, cx: &mut C) -> JsResult<'a, JsArray> {
            let env = cx.env();
            build(env, |out| unsafe {
                neon_runtime::object::get_own_property_names(out, env.to_raw(), self.to_raw())
            })
        }

        fn set<'a, C: Context<'a>, K: PropertyKey, W: Value>(
            &self,
            _: &mut C,
            key: K,
            val: Handle<W>,
        ) -> NeonResult<bool> {
            let mut result = false;
            if unsafe { key.set_from(&mut result, self.to_raw(), val.to_raw()) } {
                Ok(result)
            } else {
                Err(Throw::new())
            }
        }
    }

    /// The trait of types that can be a function's `this` binding.
    pub unsafe trait This: Managed {
        #[allow(clippy::wrong_self_convention)]
        fn as_this(h: raw::Local) -> Self;
    }
}

#[cfg(feature = "napi-1")]
mod traits {
    use crate::context::internal::Env;
    use crate::context::Context;
    use crate::handle::{Handle, Managed, Root};
    use crate::result::{NeonResult, Throw};
    use crate::types::utf8::Utf8;
    use crate::types::{build, JsUndefined, JsValue, Value};
    use neon_runtime::raw;

    #[cfg(feature = "napi-6")]
    use crate::result::JsResult;
    #[cfg(feature = "napi-6")]
    use crate::types::JsArray;

    /// A property key in a JavaScript object.
    pub trait PropertyKey {
        unsafe fn get_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut raw::Local,
            obj: raw::Local,
        ) -> bool;

        unsafe fn set_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut bool,
            obj: raw::Local,
            val: raw::Local,
        ) -> bool;
    }

    impl PropertyKey for u32 {
        unsafe fn get_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut raw::Local,
            obj: raw::Local,
        ) -> bool {
            neon_runtime::object::get_index(out, cx.env().to_raw(), obj, self)
        }

        unsafe fn set_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut bool,
            obj: raw::Local,
            val: raw::Local,
        ) -> bool {
            neon_runtime::object::set_index(out, cx.env().to_raw(), obj, self, val)
        }
    }

    impl<'a, K: Value> PropertyKey for Handle<'a, K> {
        unsafe fn get_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut raw::Local,
            obj: raw::Local,
        ) -> bool {
            let env = cx.env().to_raw();

            neon_runtime::object::get(out, env, obj, self.to_raw())
        }

        unsafe fn set_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut bool,
            obj: raw::Local,
            val: raw::Local,
        ) -> bool {
            let env = cx.env().to_raw();

            neon_runtime::object::set(out, env, obj, self.to_raw(), val)
        }
    }

    impl<'a> PropertyKey for &'a str {
        unsafe fn get_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut raw::Local,
            obj: raw::Local,
        ) -> bool {
            let (ptr, len) = Utf8::from(self).into_small_unwrap().lower();
            let env = cx.env().to_raw();

            neon_runtime::object::get_string(env, out, obj, ptr, len)
        }

        unsafe fn set_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut bool,
            obj: raw::Local,
            val: raw::Local,
        ) -> bool {
            let (ptr, len) = Utf8::from(self).into_small_unwrap().lower();
            let env = cx.env().to_raw();

            neon_runtime::object::set_string(env, out, obj, ptr, len, val)
        }
    }

    /// The trait of all object types.
    pub trait Object: Value {
        fn get_opt<'a, V: Value, C: Context<'a>, K: PropertyKey>(
            &self,
            cx: &mut C,
            key: K,
        ) -> NeonResult<Option<Handle<'a, V>>> {
            let v = self.get_value(cx, key)?;

            if v.is_a::<JsUndefined, _>(cx) {
                return Ok(None);
            }

            v.downcast_or_throw(cx).map(Some)
        }

        fn get_value<'a, C: Context<'a>, K: PropertyKey>(
            &self,
            cx: &mut C,
            key: K,
        ) -> NeonResult<Handle<'a, JsValue>> {
            build(cx.env(), |out| unsafe {
                key.get_from(cx, out, self.to_raw())
            })
        }

        fn get<'a, V: Value, C: Context<'a>, K: PropertyKey>(
            &self,
            cx: &mut C,
            key: K,
        ) -> NeonResult<Handle<'a, V>> {
            self.get_value(cx, key)?.downcast_or_throw(cx)
        }

        #[cfg(feature = "napi-6")]
        #[cfg_attr(docsrs, doc(cfg(feature = "napi-6")))]
        fn get_own_property_names<'a, C: Context<'a>>(&self, cx: &mut C) -> JsResult<'a, JsArray> {
            let env = cx.env();

            build(cx.env(), |out| unsafe {
                neon_runtime::object::get_own_property_names(out, env.to_raw(), self.to_raw())
            })
        }

        fn set<'a, C: Context<'a>, K: PropertyKey, W: Value>(
            &self,
            cx: &mut C,
            key: K,
            val: Handle<W>,
        ) -> NeonResult<bool> {
            let mut result = false;
            if unsafe { key.set_from(cx, &mut result, self.to_raw(), val.to_raw()) } {
                Ok(result)
            } else {
                Err(Throw::new())
            }
        }

        fn root<'a, C: Context<'a>>(&self, cx: &mut C) -> Root<Self> {
            Root::new(cx, self)
        }
    }

    /// The trait of types that can be a function's `this` binding.
    pub unsafe trait This: Managed {
        #[allow(clippy::wrong_self_convention)]
        fn as_this(env: Env, h: raw::Local) -> Self;
    }
}
<commit_msg>Doc comments<commit_after>//! Traits for working with JavaScript objects.
//!
//! This module defines the [`Object`](Object) trait, which is implemented
//! by all object types in the [JavaScript type hierarchy][hierarchy]. This
//! trait provides key operations in the semantics of JavaScript objects,
//! such as getting and setting an object's properties.
//!
//! ## Property Keys
//!
//! Object properties are accessed by a _property key_, which in JavaScript
//! can be a string or [symbol][symbol]. (Neon does not yet have support for
//! symbols.) For convenience, the [`PropertyKey`](PropertyKey) trait allows
//! Neon programs to use various Rust string types, as well as numeric types,
//! as keys when accessing object properties, converting the keys to strings
//! as necessary:
//!
//! ```
//! # #[cfg(feature = "napi-1")] {
//! # use neon::prelude::*;
//! fn set_and_check<'a>(
//!     cx: &mut impl Context<'a>,
//!     obj: Handle<'a, JsObject>
//! ) -> JsResult<'a, JsValue> {
//!     let value = cx.string("hello!");
//!     // set property "17" with integer shorthand
//!     obj.set(cx, 17, value)?;
//!     // get property "17" with string shorthand
//!     // returns the same value ("hello!")
//!     obj.get(cx, "17")
//! }
//! # }
//! ```
//!
//! [hierarchy]: crate::types#the-javascript-type-hierarchy
//! [symbol]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

#[cfg(feature = "legacy-runtime")]
pub(crate) mod class;

#[cfg(feature = "legacy-runtime")]
pub use self::class::{Class, ClassDescriptor};
pub use self::traits::*;

#[cfg(feature = "legacy-runtime")]
mod traits {
    use crate::context::Context;
    use crate::handle::{Handle, Managed};
    use crate::result::{JsResult, NeonResult, Throw};
    use crate::types::utf8::Utf8;
    use crate::types::{build, JsArray, JsValue, Value};
    use neon_runtime::raw;

    /// A property key in a JavaScript object.
    pub trait PropertyKey {
        unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool;
        unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool;
    }

    impl PropertyKey for u32 {
        unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool {
            neon_runtime::object::get_index(out, obj, self)
        }

        unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool {
            neon_runtime::object::set_index(out, obj, self, val)
        }
    }

    impl<'a, K: Value> PropertyKey for Handle<'a, K> {
        unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool {
            neon_runtime::object::get(out, obj, self.to_raw())
        }

        unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool {
            neon_runtime::object::set(out, obj, self.to_raw(), val)
        }
    }

    impl<'a> PropertyKey for &'a str {
        unsafe fn get_from(self, out: &mut raw::Local, obj: raw::Local) -> bool {
            let (ptr, len) = Utf8::from(self).into_small_unwrap().lower();
            neon_runtime::object::get_string(out, obj, ptr, len)
        }

        unsafe fn set_from(self, out: &mut bool, obj: raw::Local, val: raw::Local) -> bool {
            let (ptr, len) = Utf8::from(self).into_small_unwrap().lower();
            neon_runtime::object::set_string(out, obj, ptr, len, val)
        }
    }

    /// The trait of all object types.
    pub trait Object: Value {
        fn get<'a, V: Value, C: Context<'a>, K: PropertyKey>(
            &self,
            cx: &mut C,
            key: K,
        ) -> NeonResult<Handle<'a, V>> {
            let v: Handle<JsValue> =
                build(cx.env(), |out| unsafe { key.get_from(out, self.to_raw()) })?;
            v.downcast_or_throw(cx)
        }

        fn get_own_property_names<'a, C: Context<'a>>(&self, cx: &mut C) -> JsResult<'a, JsArray> {
            let env = cx.env();
            build(env, |out| unsafe {
                neon_runtime::object::get_own_property_names(out, env.to_raw(), self.to_raw())
            })
        }

        fn set<'a, C: Context<'a>, K: PropertyKey, W: Value>(
            &self,
            _: &mut C,
            key: K,
            val: Handle<W>,
        ) -> NeonResult<bool> {
            let mut result = false;
            if unsafe { key.set_from(&mut result, self.to_raw(), val.to_raw()) } {
                Ok(result)
            } else {
                Err(Throw::new())
            }
        }
    }

    /// The trait of types that can be a function's `this` binding.
    pub unsafe trait This: Managed {
        #[allow(clippy::wrong_self_convention)]
        fn as_this(h: raw::Local) -> Self;
    }
}

#[cfg(feature = "napi-1")]
mod traits {
    use crate::context::internal::Env;
    use crate::context::Context;
    use crate::handle::{Handle, Managed, Root};
    use crate::result::{NeonResult, Throw};
    use crate::types::utf8::Utf8;
    use crate::types::{build, JsUndefined, JsValue, Value};
    use neon_runtime::raw;

    #[cfg(feature = "napi-6")]
    use crate::result::JsResult;
    #[cfg(feature = "napi-6")]
    use crate::types::JsArray;

    /// A property key in a JavaScript object.
    pub trait PropertyKey {
        unsafe fn get_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut raw::Local,
            obj: raw::Local,
        ) -> bool;

        unsafe fn set_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut bool,
            obj: raw::Local,
            val: raw::Local,
        ) -> bool;
    }

    impl PropertyKey for u32 {
        unsafe fn get_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut raw::Local,
            obj: raw::Local,
        ) -> bool {
            neon_runtime::object::get_index(out, cx.env().to_raw(), obj, self)
        }

        unsafe fn set_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut bool,
            obj: raw::Local,
            val: raw::Local,
        ) -> bool {
            neon_runtime::object::set_index(out, cx.env().to_raw(), obj, self, val)
        }
    }

    impl<'a, K: Value> PropertyKey for Handle<'a, K> {
        unsafe fn get_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut raw::Local,
            obj: raw::Local,
        ) -> bool {
            let env = cx.env().to_raw();

            neon_runtime::object::get(out, env, obj, self.to_raw())
        }

        unsafe fn set_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut bool,
            obj: raw::Local,
            val: raw::Local,
        ) -> bool {
            let env = cx.env().to_raw();

            neon_runtime::object::set(out, env, obj, self.to_raw(), val)
        }
    }

    impl<'a> PropertyKey for &'a str {
        unsafe fn get_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut raw::Local,
            obj: raw::Local,
        ) -> bool {
            let (ptr, len) = Utf8::from(self).into_small_unwrap().lower();
            let env = cx.env().to_raw();

            neon_runtime::object::get_string(env, out, obj, ptr, len)
        }

        unsafe fn set_from<'c, C: Context<'c>>(
            self,
            cx: &mut C,
            out: &mut bool,
            obj: raw::Local,
            val: raw::Local,
        ) -> bool {
            let (ptr, len) = Utf8::from(self).into_small_unwrap().lower();
            let env = cx.env().to_raw();

            neon_runtime::object::set_string(env, out, obj, ptr, len, val)
        }
    }

    /// The trait of all object types.
    pub trait Object: Value {
        /// Gets a property from a JavaScript object that may be `undefined` and
        /// attempts to downcast the value if it existed.
        fn get_opt<'a, V: Value, C: Context<'a>, K: PropertyKey>(
            &self,
            cx: &mut C,
            key: K,
        ) -> NeonResult<Option<Handle<'a, V>>> {
            let v = self.get_value(cx, key)?;

            if v.is_a::<JsUndefined, _>(cx) {
                return Ok(None);
            }

            v.downcast_or_throw(cx).map(Some)
        }

        /// Gets a property from a JavaScript object as a [`JsValue`].
        ///
        /// If a [`getter`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get)
        /// is defined on the object, it will be called.
        fn get_value<'a, C: Context<'a>, K: PropertyKey>(
            &self,
            cx: &mut C,
            key: K,
        ) -> NeonResult<Handle<'a, JsValue>> {
            build(cx.env(), |out| unsafe {
                key.get_from(cx, out, self.to_raw())
            })
        }

        /// Gets a property from a JavaScript object and attempts to downcast as a specific type.
        /// Equivalent to calling `obj.get(&mut cx)?.downcast_or_throw(&mut cx)`.
        ///
        /// Throws an exception if the value is a different type.
        fn get<'a, V: Value, C: Context<'a>, K: PropertyKey>(
            &self,
            cx: &mut C,
            key: K,
        ) -> NeonResult<Handle<'a, V>> {
            self.get_value(cx, key)?.downcast_or_throw(cx)
        }

        #[cfg(feature = "napi-6")]
        #[cfg_attr(docsrs, doc(cfg(feature = "napi-6")))]
        fn get_own_property_names<'a, C: Context<'a>>(&self, cx: &mut C) -> JsResult<'a, JsArray> {
            let env = cx.env();

            build(cx.env(), |out| unsafe {
                neon_runtime::object::get_own_property_names(out, env.to_raw(), self.to_raw())
            })
        }

        fn set<'a, C: Context<'a>, K: PropertyKey, W: Value>(
            &self,
            cx: &mut C,
            key: K,
            val: Handle<W>,
        ) -> NeonResult<bool> {
            let mut result = false;
            if unsafe { key.set_from(cx, &mut result, self.to_raw(), val.to_raw()) } {
                Ok(result)
            } else {
                Err(Throw::new())
            }
        }

        fn root<'a, C: Context<'a>>(&self, cx: &mut C) -> Root<Self> {
            Root::new(cx, self)
        }
    }

    /// The trait of types that can be a function's `this` binding.
    pub unsafe trait This: Managed {
        #[allow(clippy::wrong_self_convention)]
        fn as_this(env: Env, h: raw::Local) -> Self;
    }
}
<|endoftext|>


<commit_before>mod lexer;
mod location;
mod parser;

pub use self::lexer::Token;
pub use self::location::Location;
<commit_msg>Add public parsing interface<commit_after>use super::ast::{Node, Program};

mod lexer;
mod location;
mod parser;

pub use self::lexer::Token;
pub use self::location::Location;

pub fn parse<I: ToString>(input: I) -> Program {
    let mut token_stream = lexer::TokenStream::from_string(input.to_string());
    let node = parser::parse_program(&mut token_stream);
    match node {
        Node::Program(program) => program,
        _ => panic!("Not a Program: {:?}", node),
    }
}
<|endoftext|>


<commit_before>use iron::{Request, Response, Middleware, Alloy};
use iron::middleware::{Status, Continue};
use std::sync::{Arc, RWLock};

pub struct Persistent<Data, Phantom> {
    pub data: Arc<RWLock<Data>>
}

impl<D: Send + Share, P> Clone for Persistent<D, P> {
    fn clone(&self) -> Persistent<D, P> {
        Persistent {
            data: self.data.clone()
        }
    }
}

impl<D: Send + Share, P> Middleware for Persistent<D, P> {
    fn enter(&mut self, _: &mut Request,
             _: &mut Response, alloy: &mut Alloy) -> Status {
        alloy.insert::<Persistent<D, P>>(self.clone());
        Continue
    }
}

impl<D: Send + Share, P> Persistent<D, P> {
    pub fn new(data: D) -> Persistent<D, P> {
        Persistent { data: Arc::new(RWLock::new(data)) }
    }
}

<commit_msg>(doc) Documented Persistent.<commit_after>use iron::{Request, Response, Middleware, Alloy};
use iron::middleware::{Status, Continue};
use std::sync::{Arc, RWLock};

/// A `Middleware` that allows for sharing a single piece of data between
/// requests under an `RWLock`.
///
/// `Persistent` has two type parameters: `Data`, which dictates the type of
/// the contained data, and `Phantom`, which is used to differentiate the types
/// of multiple instances of `Persistent` that contain the same data.
///
/// This phantom type parameter is used so that multiple `Persistent` instances
/// containing the same kind of data can be stored in the same `Alloy`.
pub struct Persistent<Data, Phantom> {
    /// The data contained within Persistent
    pub data: Arc<RWLock<Data>>
}

impl<D: Send + Share, P> Clone for Persistent<D, P> {
    fn clone(&self) -> Persistent<D, P> {
        Persistent {
            data: self.data.clone()
        }
    }
}

impl<D: Send + Share, P> Middleware for Persistent<D, P> {
    fn enter(&mut self, _: &mut Request,
             _: &mut Response, alloy: &mut Alloy) -> Status {
        alloy.insert::<Persistent<D, P>>(self.clone());
        Continue
    }
}

impl<D: Send + Share, P> Persistent<D, P> {
    /// Creates a new instance of `Persistent` containing the passed-in data.
    pub fn new(data: D) -> Persistent<D, P> {
        Persistent { data: Arc::new(RWLock::new(data)) }
    }
}

<|endoftext|>


<commit_before>//! This crate defines a
//! [Wadler-style](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf)
//! pretty-printing API.
//!
//! See `Doc` and
extern crate typed_arena;

use doc::Doc::{Append, Group, Nest, Newline, Nil, Space, Text};
use std::borrow::Cow;
use std::fmt;
use std::ops::Deref;

mod doc;

#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct BoxDoc<'a>(Box<doc::Doc<'a, BoxDoc<'a>>>);

impl<'a> fmt::Debug for BoxDoc<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> BoxDoc<'a> {
    fn new(doc: doc::Doc<'a, BoxDoc<'a>>) -> BoxDoc<'a> {
        BoxDoc(Box::new(doc))
    }
}

impl<'a> Deref for BoxDoc<'a> {
    type Target = doc::Doc<'a, BoxDoc<'a>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

/// The `DocBuilder` type allows for convenient appending of documents even for arena allocated
/// documents by storing the arena inline.
#[derive(Eq, Ord, PartialEq, PartialOrd)]
pub struct DocBuilder<'a, A: ?Sized>(pub &'a A, pub doc::Doc<'a, A::Doc>)
    where A: DocAllocator<'a> + 'a;

impl<'a, A: DocAllocator<'a> + 'a> Clone for DocBuilder<'a, A> {
    fn clone(&self) -> Self {
        DocBuilder(self.0, self.1.clone())
    }
}

impl<'a, A: ?Sized> Into<doc::Doc<'a, A::Doc>> for DocBuilder<'a, A>
    where A: DocAllocator<'a>
{
    fn into(self) -> doc::Doc<'a, A::Doc> {
        self.1
    }
}

/// The `DocAllocator` trait abstracts over a type which can allocate (pointers to) `Doc`.
pub trait DocAllocator<'a> {
    type Doc: Deref<Target = doc::Doc<'a, Self::Doc>> + Clone;
    fn alloc(&'a self, doc::Doc<'a, Self::Doc>) -> Self::Doc;

    #[inline]
    fn nil(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Nil)
    }

    #[inline]
    fn newline(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Newline)
    }

    #[inline]
    fn space(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Space)
    }

    #[inline]
    fn as_string<T: ToString>(&'a self, t: T) -> DocBuilder<'a, Self> {
        self.text(t.to_string())
    }

    #[inline]
    fn text<T: Into<Cow<'a, str>>>(&'a self, data: T) -> DocBuilder<'a, Self> {
        let text = data.into();
        debug_assert!(!text.contains(|c: char| c == '\n' || c == '\r'));
        DocBuilder(self, Text(text))
    }

    #[inline]
    fn concat<I>(&'a self, docs: I) -> DocBuilder<'a, Self>
        where I: IntoIterator,
              I::Item: Into<doc::Doc<'a, Self::Doc>>
    {
        docs.into_iter().fold(self.nil(), |a, b| a.append(b))
    }
}

impl<'a, 's, A: ?Sized> DocBuilder<'a, A>
    where A: DocAllocator<'a>
{
    #[inline]
    pub fn append<B>(self, that: B) -> DocBuilder<'a, A>
        where B: Into<doc::Doc<'a, A::Doc>>
    {
        let DocBuilder(allocator, this) = self;
        let that = that.into();
        let doc = match this {
            Nil => that,
            _ => {
                match that {
                    Nil => this,
                    _ => Append(allocator.alloc(this), allocator.alloc(that)),
                }
            }
        };
        DocBuilder(allocator, doc)
    }

    #[inline]
    pub fn group(self) -> DocBuilder<'a, A> {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Group(allocator.alloc(this)))
    }

    #[inline]
    pub fn nest(self, offset: usize) -> DocBuilder<'a, A> {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Nest(offset, allocator.alloc(this)))
    }
}

/// Newtype wrapper for `&doc::Doc`
#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct RefDoc<'a>(&'a doc::Doc<'a, RefDoc<'a>>);

impl<'a> fmt::Debug for RefDoc<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> Deref for RefDoc<'a> {
    type Target = doc::Doc<'a, RefDoc<'a>>;

    fn deref(&self) -> &doc::Doc<'a, RefDoc<'a>> {
        &self.0
    }
}

/// An arena which can be used to allocate `Doc` values.
pub type Arena<'a> = typed_arena::Arena<doc::Doc<'a, RefDoc<'a>>>;

impl<'a> DocAllocator<'a> for Arena<'a> {
    type Doc = RefDoc<'a>;

    #[inline]
    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        static SPACE: doc::Doc<'static, RefDoc<'static>> = Doc::Space;
        static NEWLINE: doc::Doc<'static, RefDoc<'static>> = Doc::Newline;

        RefDoc(match doc {
            Space => &SPACE,
            Newline => &NEWLINE,
            _ => Arena::alloc(self, doc),
        })
    }
}

pub struct BoxAllocator;

static BOX_ALLOCATOR: BoxAllocator = BoxAllocator;

impl<'a> DocAllocator<'a> for BoxAllocator {
    type Doc = BoxDoc<'a>;

    #[inline]
    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        BoxDoc::new(doc)
    }
}

pub use doc::Doc;

impl<'a, B> Doc<'a, B> {
    #[inline]
    pub fn nil() -> Doc<'a, B> {
        Nil
    }

    #[inline]
    pub fn as_string<T: ToString>(t: T) -> Doc<'a, B> {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn newline() -> Doc<'a, B> {
        Newline
    }

    #[inline]
    pub fn text<T: Into<Cow<'a, str>>>(data: T) -> Doc<'a, B> {
        let text = data.into();
        debug_assert!(!text.contains(|c: char| c == '\n' || c == '\r'));
        Text(text)
    }

    #[inline]
    pub fn space() -> Doc<'a, B> {
        Space
    }
}

impl<'a> Doc<'a, BoxDoc<'a>> {
    #[inline]
    pub fn append(self, that: Doc<'a, BoxDoc<'a>>) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).append(that).into()
    }

    #[inline]
    pub fn concat<I>(&'a self, docs: I) -> Doc<'a, BoxDoc<'a>>
        where I: IntoIterator<Item = Doc<'a, BoxDoc<'a>>>
    {
        docs.into_iter().fold(Doc::nil(), |a, b| a.append(b))
    }

    #[inline]
    pub fn group(self) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).group().into()
    }

    #[inline]
    pub fn nest(self, offset: usize) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).nest(offset).into()
    }
}

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

    macro_rules! test {
        ($size: expr, $actual: expr, $expected: expr) => {
            let mut vec = Vec::new();
            $actual.render($size, &mut vec).unwrap();
            assert_eq!(from_utf8(&vec).unwrap(), $expected);
        };
        ($actual: expr, $expected: expr) => {
            test!(70, $actual, $expected)
        }
    }

    #[test]
    fn box_doc_inference() {
        let doc = Doc::group(Doc::text("test").append(Doc::space()).append(Doc::text("test")));
        test!(doc, "test test");
    }

    #[test]
    fn forced_newline() {
        let doc = Doc::group(Doc::text("test").append(Doc::newline()).append(Doc::text("test")));
        test!(doc, "test\ntest");
    }

    #[test]
    fn block() {
        let doc = Doc::group(Doc::text("{")
            .append(Doc::space()
                .append(Doc::text("test"))
                .append(Doc::space())
                .append(Doc::text("test"))
                .nest(2))
            .append(Doc::space())
            .append(Doc::text("}")));
        test!(5, doc, "{\n  test\n  test\n}");
    }
}
<commit_msg>perf: Simplify append<commit_after>//! This crate defines a
//! [Wadler-style](http://homepages.inf.ed.ac.uk/wadler/papers/prettier/prettier.pdf)
//! pretty-printing API.
//!
//! See `Doc` and
extern crate typed_arena;

use doc::Doc::{Append, Group, Nest, Newline, Nil, Space, Text};
use std::borrow::Cow;
use std::fmt;
use std::ops::Deref;

mod doc;

#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct BoxDoc<'a>(Box<doc::Doc<'a, BoxDoc<'a>>>);

impl<'a> fmt::Debug for BoxDoc<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> BoxDoc<'a> {
    fn new(doc: doc::Doc<'a, BoxDoc<'a>>) -> BoxDoc<'a> {
        BoxDoc(Box::new(doc))
    }
}

impl<'a> Deref for BoxDoc<'a> {
    type Target = doc::Doc<'a, BoxDoc<'a>>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

/// The `DocBuilder` type allows for convenient appending of documents even for arena allocated
/// documents by storing the arena inline.
#[derive(Eq, Ord, PartialEq, PartialOrd)]
pub struct DocBuilder<'a, A: ?Sized>(pub &'a A, pub doc::Doc<'a, A::Doc>)
    where A: DocAllocator<'a> + 'a;

impl<'a, A: DocAllocator<'a> + 'a> Clone for DocBuilder<'a, A> {
    fn clone(&self) -> Self {
        DocBuilder(self.0, self.1.clone())
    }
}

impl<'a, A: ?Sized> Into<doc::Doc<'a, A::Doc>> for DocBuilder<'a, A>
    where A: DocAllocator<'a>
{
    fn into(self) -> doc::Doc<'a, A::Doc> {
        self.1
    }
}

/// The `DocAllocator` trait abstracts over a type which can allocate (pointers to) `Doc`.
pub trait DocAllocator<'a> {
    type Doc: Deref<Target = doc::Doc<'a, Self::Doc>> + Clone;
    fn alloc(&'a self, doc::Doc<'a, Self::Doc>) -> Self::Doc;

    #[inline]
    fn nil(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Nil)
    }

    #[inline]
    fn newline(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Newline)
    }

    #[inline]
    fn space(&'a self) -> DocBuilder<'a, Self> {
        DocBuilder(self, Space)
    }

    #[inline]
    fn as_string<T: ToString>(&'a self, t: T) -> DocBuilder<'a, Self> {
        self.text(t.to_string())
    }

    #[inline]
    fn text<T: Into<Cow<'a, str>>>(&'a self, data: T) -> DocBuilder<'a, Self> {
        let text = data.into();
        debug_assert!(!text.contains(|c: char| c == '\n' || c == '\r'));
        DocBuilder(self, Text(text))
    }

    #[inline]
    fn concat<I>(&'a self, docs: I) -> DocBuilder<'a, Self>
        where I: IntoIterator,
              I::Item: Into<doc::Doc<'a, Self::Doc>>
    {
        docs.into_iter().fold(self.nil(), |a, b| a.append(b))
    }
}

impl<'a, 's, A: ?Sized> DocBuilder<'a, A>
    where A: DocAllocator<'a>
{
    #[inline]
    pub fn append<B>(self, that: B) -> DocBuilder<'a, A>
        where B: Into<doc::Doc<'a, A::Doc>>
    {
        let DocBuilder(allocator, this) = self;
        let that = that.into();
        let doc = match (this, that) {
            (Nil, that) => that,
            (this, Nil) => this,
            (this, that) => Append(allocator.alloc(this), allocator.alloc(that)),
        };
        DocBuilder(allocator, doc)
    }

    #[inline]
    pub fn group(self) -> DocBuilder<'a, A> {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Group(allocator.alloc(this)))
    }

    #[inline]
    pub fn nest(self, offset: usize) -> DocBuilder<'a, A> {
        let DocBuilder(allocator, this) = self;
        DocBuilder(allocator, Nest(offset, allocator.alloc(this)))
    }
}

/// Newtype wrapper for `&doc::Doc`
#[derive(Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct RefDoc<'a>(&'a doc::Doc<'a, RefDoc<'a>>);

impl<'a> fmt::Debug for RefDoc<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<'a> Deref for RefDoc<'a> {
    type Target = doc::Doc<'a, RefDoc<'a>>;

    fn deref(&self) -> &doc::Doc<'a, RefDoc<'a>> {
        &self.0
    }
}

/// An arena which can be used to allocate `Doc` values.
pub type Arena<'a> = typed_arena::Arena<doc::Doc<'a, RefDoc<'a>>>;

impl<'a> DocAllocator<'a> for Arena<'a> {
    type Doc = RefDoc<'a>;

    #[inline]
    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        static SPACE: doc::Doc<'static, RefDoc<'static>> = Doc::Space;
        static NEWLINE: doc::Doc<'static, RefDoc<'static>> = Doc::Newline;

        RefDoc(match doc {
            Space => &SPACE,
            Newline => &NEWLINE,
            _ => Arena::alloc(self, doc),
        })
    }
}

pub struct BoxAllocator;

static BOX_ALLOCATOR: BoxAllocator = BoxAllocator;

impl<'a> DocAllocator<'a> for BoxAllocator {
    type Doc = BoxDoc<'a>;

    #[inline]
    fn alloc(&'a self, doc: doc::Doc<'a, Self::Doc>) -> Self::Doc {
        BoxDoc::new(doc)
    }
}

pub use doc::Doc;

impl<'a, B> Doc<'a, B> {
    #[inline]
    pub fn nil() -> Doc<'a, B> {
        Nil
    }

    #[inline]
    pub fn as_string<T: ToString>(t: T) -> Doc<'a, B> {
        Doc::text(t.to_string())
    }

    #[inline]
    pub fn newline() -> Doc<'a, B> {
        Newline
    }

    #[inline]
    pub fn text<T: Into<Cow<'a, str>>>(data: T) -> Doc<'a, B> {
        let text = data.into();
        debug_assert!(!text.contains(|c: char| c == '\n' || c == '\r'));
        Text(text)
    }

    #[inline]
    pub fn space() -> Doc<'a, B> {
        Space
    }
}

impl<'a> Doc<'a, BoxDoc<'a>> {
    #[inline]
    pub fn append(self, that: Doc<'a, BoxDoc<'a>>) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).append(that).into()
    }

    #[inline]
    pub fn concat<I>(&'a self, docs: I) -> Doc<'a, BoxDoc<'a>>
        where I: IntoIterator<Item = Doc<'a, BoxDoc<'a>>>
    {
        docs.into_iter().fold(Doc::nil(), |a, b| a.append(b))
    }

    #[inline]
    pub fn group(self) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).group().into()
    }

    #[inline]
    pub fn nest(self, offset: usize) -> Doc<'a, BoxDoc<'a>> {
        DocBuilder(&BOX_ALLOCATOR, self).nest(offset).into()
    }
}

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

    macro_rules! test {
        ($size: expr, $actual: expr, $expected: expr) => {
            let mut vec = Vec::new();
            $actual.render($size, &mut vec).unwrap();
            assert_eq!(from_utf8(&vec).unwrap(), $expected);
        };
        ($actual: expr, $expected: expr) => {
            test!(70, $actual, $expected)
        }
    }

    #[test]
    fn box_doc_inference() {
        let doc = Doc::group(Doc::text("test").append(Doc::space()).append(Doc::text("test")));
        test!(doc, "test test");
    }

    #[test]
    fn forced_newline() {
        let doc = Doc::group(Doc::text("test").append(Doc::newline()).append(Doc::text("test")));
        test!(doc, "test\ntest");
    }

    #[test]
    fn block() {
        let doc = Doc::group(Doc::text("{")
            .append(Doc::space()
                .append(Doc::text("test"))
                .append(Doc::space())
                .append(Doc::text("test"))
                .nest(2))
            .append(Doc::space())
            .append(Doc::text("}")));
        test!(5, doc, "{\n  test\n  test\n}");
    }
}
<|endoftext|>


<commit_before>//! Represents JavaScript exceptions as a Rust [`Result`](std::result) type.
//!
//! Most interactions with the JavaScript engine can throw a JavaScript exception. Neon APIs
//! that can throw an exception are called _throwing APIs_ and return the type
//! [`NeonResult`](NeonResult) (or its shorthand [`JsResult`](JsResult)).
//!
//! When a throwing API triggers a JavaScript exception, it returns an [Err](std::result::Result::Err)
//! result. This indicates that the thread associated with the [`Context`](crate::context::Context)
//! is now throwing, and allows Rust code to perform any cleanup. See the
//! [`neon::context`](crate::context) module documentation for more about
//! [contexts and exceptions](crate::context#throwing-exceptions).
//!
//! Typically, Neon code can manage JavaScript exceptions correctly and conveniently by
//! using Rust's [question mark (`?`)][question-mark] operator. This ensures that Rust code
//! "short-circuits" when an exception is thrown and returns back to JavaScript without
//! calling any throwing APIs.
//!
//! ## Example
//!
//! Neon functions typically use [`JsResult`](JsResult) for their return type. This
//! example defines a function that extracts a property called `"message"` from an object,
//! throwing an exception if the argument is not of the right type or extracting the property
//! fails:
//!
//! ```
//! # use neon::prelude::*;
//! fn get_message(mut cx: FunctionContext) -> JsResult<JsValue> {
//!     let obj: Handle<JsObject> = cx.argument(0)?;
//!     let prop: Handle<JsValue> = obj.get(&mut cx, "message")?;
//!     Ok(prop)
//! }
//! ```
//!
//! [question-mark]: https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/the-question-mark-operator-for-easier-error-handling.html

use crate::context::Context;
use crate::handle::Handle;
use crate::types::Value;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::marker::PhantomData;

/// A [unit type][unit] indicating that the JavaScript thread is throwing an exception.
///
/// `Throw` deliberately does not implement [`std::error::Error`](std::error::Error). It's
/// not recommended to chain JavaScript exceptions with other kinds of Rust errors,
/// since throwing means that the JavaScript thread is unavailable until the exception
/// is handled.
///
/// [unit]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields
#[derive(Debug)]
pub struct Throw(PhantomData<*mut ()>); // *mut is !Send + !Sync, making it harder to forge

impl Throw {
    pub(crate) fn new() -> Self {
        Self(PhantomData)
    }
}

impl Display for Throw {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        fmt.write_str("JavaScript Error")
    }
}

/// The result type for throwing APIs.
pub type NeonResult<T> = Result<T, Throw>;

/// Shorthand for a [`NeonResult`](NeonResult) that produces JavaScript values.
pub type JsResult<'b, T> = NeonResult<Handle<'b, T>>;

/// Extension trait for converting Rust [`Result`](std::result::Result) values
/// into [`JsResult`](JsResult) values by throwing JavaScript exceptions.
pub trait JsResultExt<'a, V: Value> {
    fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, V>;
}
<commit_msg>Tighten language in comment based on review suggestion: mut* makes `Throw` harder to store<commit_after>//! Represents JavaScript exceptions as a Rust [`Result`](std::result) type.
//!
//! Most interactions with the JavaScript engine can throw a JavaScript exception. Neon APIs
//! that can throw an exception are called _throwing APIs_ and return the type
//! [`NeonResult`](NeonResult) (or its shorthand [`JsResult`](JsResult)).
//!
//! When a throwing API triggers a JavaScript exception, it returns an [Err](std::result::Result::Err)
//! result. This indicates that the thread associated with the [`Context`](crate::context::Context)
//! is now throwing, and allows Rust code to perform any cleanup. See the
//! [`neon::context`](crate::context) module documentation for more about
//! [contexts and exceptions](crate::context#throwing-exceptions).
//!
//! Typically, Neon code can manage JavaScript exceptions correctly and conveniently by
//! using Rust's [question mark (`?`)][question-mark] operator. This ensures that Rust code
//! "short-circuits" when an exception is thrown and returns back to JavaScript without
//! calling any throwing APIs.
//!
//! ## Example
//!
//! Neon functions typically use [`JsResult`](JsResult) for their return type. This
//! example defines a function that extracts a property called `"message"` from an object,
//! throwing an exception if the argument is not of the right type or extracting the property
//! fails:
//!
//! ```
//! # use neon::prelude::*;
//! fn get_message(mut cx: FunctionContext) -> JsResult<JsValue> {
//!     let obj: Handle<JsObject> = cx.argument(0)?;
//!     let prop: Handle<JsValue> = obj.get(&mut cx, "message")?;
//!     Ok(prop)
//! }
//! ```
//!
//! [question-mark]: https://doc.rust-lang.org/edition-guide/rust-2018/error-handling-and-panics/the-question-mark-operator-for-easier-error-handling.html

use crate::context::Context;
use crate::handle::Handle;
use crate::types::Value;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::marker::PhantomData;

/// A [unit type][unit] indicating that the JavaScript thread is throwing an exception.
///
/// `Throw` deliberately does not implement [`std::error::Error`](std::error::Error). It's
/// not recommended to chain JavaScript exceptions with other kinds of Rust errors,
/// since throwing means that the JavaScript thread is unavailable until the exception
/// is handled.
///
/// [unit]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields
#[derive(Debug)]
pub struct Throw(PhantomData<*mut ()>); // *mut is !Send + !Sync, making it harder to accidentally store

impl Throw {
    pub(crate) fn new() -> Self {
        Self(PhantomData)
    }
}

impl Display for Throw {
    fn fmt(&self, fmt: &mut Formatter) -> FmtResult {
        fmt.write_str("JavaScript Error")
    }
}

/// The result type for throwing APIs.
pub type NeonResult<T> = Result<T, Throw>;

/// Shorthand for a [`NeonResult`](NeonResult) that produces JavaScript values.
pub type JsResult<'b, T> = NeonResult<Handle<'b, T>>;

/// Extension trait for converting Rust [`Result`](std::result::Result) values
/// into [`JsResult`](JsResult) values by throwing JavaScript exceptions.
pub trait JsResultExt<'a, V: Value> {
    fn or_throw<'b, C: Context<'b>>(self, cx: &mut C) -> JsResult<'a, V>;
}
<|endoftext|>


<commit_before>//! Retry sending records configuration.

/// You can calculate retrying interval as the following equation:
///
/// `retry_interval = exp ** (multiplier + retry_counts)`
///
/// see: https://github.com/jimmycuadra/retry/blob/v0.4.0/src/lib.rs#L142-L143
///
/// You can estimate to caluculate with concrete values like:
///
/// * `retry_counts`: 10, e ^ (5 + 10)/1000.0/60.0/60.0 = 0.908060381242253, about 0.9 hour
///
/// * `retry_counts`: 11, e ^ (5 + 11)/1000.0/60.0/60.0 = 2.4683640334744092, about 2.5 hours
///
/// * `retry_counts`: 12, e ^ (5 + 12)/1000.0/60.0/60.0 = 6.709709098215361, about 6.7 hours
///
/// where multiplier = 5,
/// e is [exponential function](https://doc.rust-lang.org/std/primitive.f64.html#method.exp).
///
/// ## Default values
///
/// * multiplier: `5_f64`
/// * max: 10
#[derive(Debug, Clone, PartialEq)]
pub struct RetryConf {
    max: u64,
    multiplier: f64,
}

impl Default for RetryConf {
    fn default() -> RetryConf {
        RetryConf {
            max: 10,
            multiplier: 5_f64,
        }
    }
}

impl RetryConf {
    pub fn new() -> RetryConf {
        Default::default()
    }

    pub fn max(mut self, max: u64) -> RetryConf {
        self.max = max;
        self
    }

    pub fn multiplier(mut self, multiplier: f64) -> RetryConf {
        self.multiplier = multiplier;
        self
    }

    pub fn build(self) -> (u64, f64) {
        (self.max, self.multiplier)
    }
}
<commit_msg>retry_conf: Add file path related functions<commit_after>//! Retry sending records configuration.

use std::path::PathBuf;

/// You can calculate retrying interval as the following equation:
///
/// `retry_interval = exp ** (multiplier + retry_counts)`
///
/// see: https://github.com/jimmycuadra/retry/blob/v0.4.0/src/lib.rs#L142-L143
///
/// You can estimate to caluculate with concrete values like:
///
/// * `retry_counts`: 10, e ^ (5 + 10)/1000.0/60.0/60.0 = 0.908060381242253, about 0.9 hour
///
/// * `retry_counts`: 11, e ^ (5 + 11)/1000.0/60.0/60.0 = 2.4683640334744092, about 2.5 hours
///
/// * `retry_counts`: 12, e ^ (5 + 12)/1000.0/60.0/60.0 = 6.709709098215361, about 6.7 hours
///
/// where multiplier = 5,
/// e is [exponential function](https://doc.rust-lang.org/std/primitive.f64.html#method.exp).
///
/// ## Default values
///
/// * multiplier: `5_f64`
/// * max: 10
#[derive(Debug, Clone, PartialEq)]
pub struct RetryConf {
    max: u64,
    multiplier: f64,
    store_file_path: Option<PathBuf>
}

impl Default for RetryConf {
    fn default() -> RetryConf {
        RetryConf {
            max: 10,
            multiplier: 5_f64,
            store_file_path: None
        }
    }
}

impl RetryConf {
    pub fn new() -> RetryConf {
        Default::default()
    }

    pub fn max(mut self, max: u64) -> RetryConf {
        self.max = max;
        self
    }

    pub fn multiplier(mut self, multiplier: f64) -> RetryConf {
        self.multiplier = multiplier;
        self
    }

    pub fn store_file(mut self, path: PathBuf) -> RetryConf {
        self.store_file_path = Some(path);
        self
    }

    pub fn need_to_store(self) -> bool {
        self.store_file_path.is_some()
    }

    pub fn store_path(self) -> Option<PathBuf> {
        self.store_file_path
    }

    pub fn build(self) -> (u64, f64) {
        (self.max, self.multiplier)
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[cfg(not(windows))] use screen::unix::UnixScreen;
#[cfg(windows)] pub use screen::windows::WindowsScreen;

pub enum Key {
    Char(char),
    Control(char),
    Enter,
    Backspace,
    Tab,
    ShiftTab,
    Nothing,
    Down,
    Up,
}

pub trait Screen {
    fn visible_choices(&self) -> u16;
    fn width(&self) -> u16;
    fn move_cursor_to_prompt_line(&mut self, col: u16);
    fn blank_screen(&mut self);
    fn show_cursor(&mut self);
    fn hide_cursor(&mut self);
    fn write(&mut self, s: &str);
    fn write_red_inverted(&mut self, s: &str);
    fn write_red(&mut self, s: &str);
    fn write_inverted(&mut self, s: &str);
    fn get_buffered_keys(&mut self) -> Vec<Key>;
}

#[cfg(windows)]
pub fn new(desired_rows: u16) -> Box<Screen> {
    if WindowsScreen::is_cygwin() {
//        UnixScreen::open_screen(desired_rows)
        panic!("This executable does not support Cygwin.");
    } else {
        Box::from(WindowsScreen::open_screen(desired_rows))
    }
}

#[cfg(not(windows))]
pub fn new(desired_rows: u16) -> Box<dyn Screen> {
    Box::from(UnixScreen::open_screen(desired_rows))
}

#[cfg(not(windows))] mod unix;
#[cfg(windows)] mod windows;
<commit_msg>Add explicit `dyn` to trait object<commit_after>#![allow(dead_code)]

#[cfg(not(windows))] use screen::unix::UnixScreen;
#[cfg(windows)] pub use screen::windows::WindowsScreen;

pub enum Key {
    Char(char),
    Control(char),
    Enter,
    Backspace,
    Tab,
    ShiftTab,
    Nothing,
    Down,
    Up,
}

pub trait Screen {
    fn visible_choices(&self) -> u16;
    fn width(&self) -> u16;
    fn move_cursor_to_prompt_line(&mut self, col: u16);
    fn blank_screen(&mut self);
    fn show_cursor(&mut self);
    fn hide_cursor(&mut self);
    fn write(&mut self, s: &str);
    fn write_red_inverted(&mut self, s: &str);
    fn write_red(&mut self, s: &str);
    fn write_inverted(&mut self, s: &str);
    fn get_buffered_keys(&mut self) -> Vec<Key>;
}

#[cfg(windows)]
pub fn new(desired_rows: u16) -> Box<dyn Screen> {
    if WindowsScreen::is_cygwin() {
//        UnixScreen::open_screen(desired_rows)
        panic!("This executable does not support Cygwin.");
    } else {
        Box::from(WindowsScreen::open_screen(desired_rows))
    }
}

#[cfg(not(windows))]
pub fn new(desired_rows: u16) -> Box<dyn Screen> {
    Box::from(UnixScreen::open_screen(desired_rows))
}

#[cfg(not(windows))] mod unix;
#[cfg(windows)] mod windows;
<|endoftext|>


<commit_before>// Copyright 2016 `multipart` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.
//! The server-side abstraction for multipart requests. Enabled with the `server` feature.
//!
//! Use this when you are implementing an HTTP server and want to
//! to accept, parse, and serve HTTP `multipart/form-data` requests (file uploads).
//!
//! See the `Multipart` struct for more info.

pub extern crate buf_redux;
extern crate httparse;
extern crate twoway;

use std::borrow::Borrow;
use std::io::prelude::*;
use std::sync::Arc;
use std::io;

use self::boundary::BoundaryReader;

use self::field::PrivReadEntry;

pub use self::field::{FieldHeaders, MultipartField, MultipartData, ReadEntry, ReadEntryResult};

use self::save::SaveBuilder;

pub use self::save::{Entries, SaveResult, SavedField};

/// Default typedef for shared strings.
///
/// Enable the `use_arc_str` feature to use `Arc<str>` instead, which saves an indirection but
/// cannot be constructed in Rust versions older than 1.21 (the `From<String>` impl was stabilized
/// in that release).
#[cfg(not(feature = "use_arc_str"))]
pub type ArcStr = Arc<String>;

/// Optimized typedef for shared strings, replacing `Arc<String>`.
///
/// Enabled with the `use_arc_str` feature.
#[cfg(feature = "use_arc_str")]
pub type ArcStr = Arc<str>;

macro_rules! try_opt (
    ($expr:expr) => (
        match $expr {
            Some(val) => val,
            None => return None,
        }
    );
    ($expr:expr, $before_ret:expr) => (
        match $expr {
            Some(val) => val,
            None => {
                $before_ret;
                return None;
            }
        }
    )
);

macro_rules! try_read_entry {
    ($self_:expr; $try:expr) => (
        match $try {
            Ok(res) => res,
            Err(err) => return ::server::ReadEntryResult::Error($self_, err),
        }
    )
}

mod boundary;
mod field;

#[cfg(feature = "hyper")]
pub mod hyper;

#[cfg(feature = "iron")]
pub mod iron;

#[cfg(feature = "tiny_http")]
pub mod tiny_http;

#[cfg(feature = "nickel")]
pub mod nickel;

pub mod save;

/// The server-side implementation of `multipart/form-data` requests.
///
/// Implements `Borrow<R>` to allow access to the request body, if desired.
pub struct Multipart<R> {
    reader: BoundaryReader<R>,
}

impl Multipart<()> {
    /// If the given `HttpRequest` is a multipart/form-data POST request,
    /// return the request body wrapped in the multipart reader. Otherwise,
    /// returns the original request.
    pub fn from_request<R: HttpRequest>(req: R) -> Result<Multipart<R::Body>, R> {
        //FIXME: move `map` expr to `Some` arm when nonlexical borrow scopes land.
        let boundary = match req.multipart_boundary().map(String::from) {
            Some(boundary) => boundary,
            None => return Err(req),
        };

        Ok(Multipart::with_body(req.body(), boundary))
    }
}

impl<R: Read> Multipart<R> {
    /// Construct a new `Multipart` with the given body reader and boundary.
    ///
    /// ## Note: `boundary`
    /// This will prepend the requisite `--` to the boundary string as documented in
    /// [IETF RFC 1341, Section 7.2.1: "Multipart: the common syntax"][rfc1341-7.2.1].
    /// Simply pass the value of the `boundary` key from the `Content-Type` header in the
    /// request (or use `Multipart::from_request()`, if supported).
    ///
    /// [rfc1341-7.2.1]: https://tools.ietf.org/html/rfc1341#page-30
    pub fn with_body<Bnd: Into<String>>(body: R, boundary: Bnd) -> Self {
        let boundary = boundary.into();

        info!("Multipart::with_boundary(_, {:?}", boundary);

        Multipart {
            reader: BoundaryReader::from_reader(body, boundary),
        }
    }

    /// Read the next entry from this multipart request, returning a struct with the field's name and
    /// data. See `MultipartField` for more info.
    ///
    /// ## Warning: Risk of Data Loss
    /// If the previously returned entry had contents of type `MultipartField::File`,
    /// calling this again will discard any unread contents of that entry.
    pub fn read_entry(&mut self) -> io::Result<Option<MultipartField<&mut Self>>> {
        self.read_entry_mut().into_result()
    }

    /// Read the next entry from this multipart request, returning a struct with the field's name and
    /// data. See `MultipartField` for more info.
    pub fn into_entry(self) -> ReadEntryResult<Self> {
        self.read_entry()
    }

    /// Call `f` for each entry in the multipart request.
    ///
    /// This is a substitute for Rust not supporting streaming iterators (where the return value
    /// from `next()` borrows the iterator for a bound lifetime).
    ///
    /// Returns `Ok(())` when all fields have been read, or the first error.
    pub fn foreach_entry<F>(&mut self, mut foreach: F) -> io::Result<()> where F: FnMut(MultipartField<&mut Self>) {
        loop {
            match self.read_entry() {
                Ok(Some(field)) => foreach(field),
                Ok(None) => return Ok(()),
                Err(err) => return Err(err),
            }
        }
    }

    /// Get a builder type for saving the files in this request to the filesystem.
    ///
    /// See [`SaveBuilder`](save/struct.SaveBuilder.html) for more information.
    pub fn save(&mut self) -> SaveBuilder<&mut Self> {
        SaveBuilder::new(self)
    }
}

impl<R> Borrow<R> for Multipart<R> {
    fn borrow(&self) -> &R {
        self.reader.borrow()
    }
}

impl<R: Read> PrivReadEntry for Multipart<R> {
    type Source = BoundaryReader<R>;

    fn source_mut(&mut self) -> &mut BoundaryReader<R> {
        &mut self.reader
    }

    fn set_min_buf_size(&mut self, min_buf_size: usize) {
        self.reader.set_min_buf_size(min_buf_size)
    }

    /// Consume the next boundary.
    /// Returns `true` if the last boundary was read, `false` otherwise.
    fn consume_boundary(&mut self) -> io::Result<bool> {
        debug!("Consume boundary!");
        self.reader.consume_boundary()
    }
}

/// A server-side HTTP request that may or may not be multipart.
///
/// May be implemented by mutable references if providing the request or body by-value is
/// undesirable.
pub trait HttpRequest {
    /// The body of this request.
    type Body: Read;
    /// Get the boundary string of this request if it is a POST request
    /// with the `Content-Type` header set to `multipart/form-data`.
    ///
    /// The boundary string should be supplied as an extra value of the `Content-Type` header, e.g.
    /// `Content-Type: multipart/form-data; boundary={boundary}`.
    fn multipart_boundary(&self) -> Option<&str>;

    /// Return the request body for reading.
    fn body(self) -> Self::Body;
}
<commit_msg>copy repro of #104<commit_after>// Copyright 2016 `multipart` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.
//! The server-side abstraction for multipart requests. Enabled with the `server` feature.
//!
//! Use this when you are implementing an HTTP server and want to
//! to accept, parse, and serve HTTP `multipart/form-data` requests (file uploads).
//!
//! See the `Multipart` struct for more info.

pub extern crate buf_redux;
extern crate httparse;
extern crate twoway;

use std::borrow::Borrow;
use std::io::prelude::*;
use std::sync::Arc;
use std::io;

use self::boundary::BoundaryReader;

use self::field::PrivReadEntry;

pub use self::field::{FieldHeaders, MultipartField, MultipartData, ReadEntry, ReadEntryResult};

use self::save::SaveBuilder;

pub use self::save::{Entries, SaveResult, SavedField};

/// Default typedef for shared strings.
///
/// Enable the `use_arc_str` feature to use `Arc<str>` instead, which saves an indirection but
/// cannot be constructed in Rust versions older than 1.21 (the `From<String>` impl was stabilized
/// in that release).
#[cfg(not(feature = "use_arc_str"))]
pub type ArcStr = Arc<String>;

/// Optimized typedef for shared strings, replacing `Arc<String>`.
///
/// Enabled with the `use_arc_str` feature.
#[cfg(feature = "use_arc_str")]
pub type ArcStr = Arc<str>;

macro_rules! try_opt (
    ($expr:expr) => (
        match $expr {
            Some(val) => val,
            None => return None,
        }
    );
    ($expr:expr, $before_ret:expr) => (
        match $expr {
            Some(val) => val,
            None => {
                $before_ret;
                return None;
            }
        }
    )
);

macro_rules! try_read_entry {
    ($self_:expr; $try:expr) => (
        match $try {
            Ok(res) => res,
            Err(err) => return ::server::ReadEntryResult::Error($self_, err),
        }
    )
}

mod boundary;
mod field;

#[cfg(feature = "hyper")]
pub mod hyper;

#[cfg(feature = "iron")]
pub mod iron;

#[cfg(feature = "tiny_http")]
pub mod tiny_http;

#[cfg(feature = "nickel")]
pub mod nickel;

pub mod save;

/// The server-side implementation of `multipart/form-data` requests.
///
/// Implements `Borrow<R>` to allow access to the request body, if desired.
pub struct Multipart<R> {
    reader: BoundaryReader<R>,
}

impl Multipart<()> {
    /// If the given `HttpRequest` is a multipart/form-data POST request,
    /// return the request body wrapped in the multipart reader. Otherwise,
    /// returns the original request.
    pub fn from_request<R: HttpRequest>(req: R) -> Result<Multipart<R::Body>, R> {
        //FIXME: move `map` expr to `Some` arm when nonlexical borrow scopes land.
        let boundary = match req.multipart_boundary().map(String::from) {
            Some(boundary) => boundary,
            None => return Err(req),
        };

        Ok(Multipart::with_body(req.body(), boundary))
    }
}

impl<R: Read> Multipart<R> {
    /// Construct a new `Multipart` with the given body reader and boundary.
    ///
    /// ## Note: `boundary`
    /// This will prepend the requisite `--` to the boundary string as documented in
    /// [IETF RFC 1341, Section 7.2.1: "Multipart: the common syntax"][rfc1341-7.2.1].
    /// Simply pass the value of the `boundary` key from the `Content-Type` header in the
    /// request (or use `Multipart::from_request()`, if supported).
    ///
    /// [rfc1341-7.2.1]: https://tools.ietf.org/html/rfc1341#page-30
    pub fn with_body<Bnd: Into<String>>(body: R, boundary: Bnd) -> Self {
        let boundary = boundary.into();

        info!("Multipart::with_boundary(_, {:?}", boundary);

        Multipart {
            reader: BoundaryReader::from_reader(body, boundary),
        }
    }

    /// Read the next entry from this multipart request, returning a struct with the field's name and
    /// data. See `MultipartField` for more info.
    ///
    /// ## Warning: Risk of Data Loss
    /// If the previously returned entry had contents of type `MultipartField::File`,
    /// calling this again will discard any unread contents of that entry.
    pub fn read_entry(&mut self) -> io::Result<Option<MultipartField<&mut Self>>> {
        self.read_entry_mut().into_result()
    }

    /// Read the next entry from this multipart request, returning a struct with the field's name and
    /// data. See `MultipartField` for more info.
    pub fn into_entry(self) -> ReadEntryResult<Self> {
        self.read_entry()
    }

    /// Call `f` for each entry in the multipart request.
    ///
    /// This is a substitute for Rust not supporting streaming iterators (where the return value
    /// from `next()` borrows the iterator for a bound lifetime).
    ///
    /// Returns `Ok(())` when all fields have been read, or the first error.
    pub fn foreach_entry<F>(&mut self, mut foreach: F) -> io::Result<()> where F: FnMut(MultipartField<&mut Self>) {
        loop {
            match self.read_entry() {
                Ok(Some(field)) => foreach(field),
                Ok(None) => return Ok(()),
                Err(err) => return Err(err),
            }
        }
    }

    /// Get a builder type for saving the files in this request to the filesystem.
    ///
    /// See [`SaveBuilder`](save/struct.SaveBuilder.html) for more information.
    pub fn save(&mut self) -> SaveBuilder<&mut Self> {
        SaveBuilder::new(self)
    }
}

impl<R> Borrow<R> for Multipart<R> {
    fn borrow(&self) -> &R {
        self.reader.borrow()
    }
}

impl<R: Read> PrivReadEntry for Multipart<R> {
    type Source = BoundaryReader<R>;

    fn source_mut(&mut self) -> &mut BoundaryReader<R> {
        &mut self.reader
    }

    fn set_min_buf_size(&mut self, min_buf_size: usize) {
        self.reader.set_min_buf_size(min_buf_size)
    }

    /// Consume the next boundary.
    /// Returns `true` if the last boundary was read, `false` otherwise.
    fn consume_boundary(&mut self) -> io::Result<bool> {
        debug!("Consume boundary!");
        self.reader.consume_boundary()
    }
}

/// A server-side HTTP request that may or may not be multipart.
///
/// May be implemented by mutable references if providing the request or body by-value is
/// undesirable.
pub trait HttpRequest {
    /// The body of this request.
    type Body: Read;
    /// Get the boundary string of this request if it is a POST request
    /// with the `Content-Type` header set to `multipart/form-data`.
    ///
    /// The boundary string should be supplied as an extra value of the `Content-Type` header, e.g.
    /// `Content-Type: multipart/form-data; boundary={boundary}`.
    fn multipart_boundary(&self) -> Option<&str>;

    /// Return the request body for reading.
    fn body(self) -> Self::Body;
}

#[test]
fn issue_104() {
    let logger = ::mock::log_on_panic();

    use std::io::Cursor;

    let body = "\
    POST /test.html HTTP/1.1\r\n\
    Host: example.org\r\n\
    Content-Type: multipart/form-data;boundary=\"boundary\"\r\n\r\n\
    Content-Disposition: form-data; name=\"field1\"\r\n\r\n\
    value1\r\n\
    Content-Disposition: form-data; name=\"field2\"; filename=\"example.txt\"\r\n\r\n\
    value2 ";

    let request = Cursor::new(body);

    let mut multipart = Multipart::with_body(request, "boundary");
    let multipart_result = multipart.foreach_entry(|_field| {
        // Do nothing
    });

    println!("{:?}", multipart_result);

    logger.clear();
}
<|endoftext|>


<commit_before>use std::iter::repeat;
use std::collections::VecDeque;
use std::collections::BinaryHeap;
use std::cmp::Ordering;

fn max(a: u32, b: u32) -> u32 { if a > b { a } else { b } }

#[derive(Clone)]
struct Edge {
    vertex: u32,
    weight: f32,
}

impl Edge {
    pub fn new(vertex_: u32, weight_: f32) -> Edge {
        Edge{vertex: vertex_, weight: weight_,}
    }
}

impl Ord for Edge {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl Eq for Edge {}

impl PartialOrd for Edge {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        (self.weight, self.vertex).partial_cmp(&(other.weight, other.vertex))
    }
}

impl PartialEq for Edge {
    fn eq(&self, other: &Self) -> bool {
        (self.weight, &self.vertex) == (other.weight, &other.vertex)
    }
}

struct Graph {
    nodes: Vec<Vec<Edge>>,
}

impl Graph {
    pub fn new() -> Graph { Graph{nodes: Vec::new(),} }

    pub fn add_edge(&mut self, src: u32, dst: u32, weight: f32) {
        let len = self.nodes.len();

        if (max(src, dst)) > len as u32 {
            let new_len = (max(src, dst) + 1) as usize;
            self.nodes.extend(repeat(Vec::new()).take(new_len - len))
        }
        self.nodes[src as usize].push(Edge::new(dst, weight));
    }

    pub fn bfs(&self, src: u32) {
        let mut queue: VecDeque<u32> = VecDeque::new();
        let len = self.nodes.len();
        let mut visited = vec!(false ; len);

        queue.push_front(src);

        while let Some(current) = queue.pop_back() {
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            } else { continue ; }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                queue.push_front(neighbor);
            }
        }
    }

    pub fn dfs(&self, src: u32) {
        let mut stack: Vec<u32> = Vec::new();
        let len = self.nodes.len() as usize;
        let mut visited = vec!(false ; len);

        stack.push(src);

        while let Some(current) = stack.pop() {
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            } else { continue ; }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                stack.push(neighbor);
            }
        }
    }

    pub fn dijkstra(&self, src: u32, dst: u32) {
      let mut dist: Vec<f32> = Vec::new();
      let mut prev: Vec<u32> = Vec::new();
      let mut q = BinaryHeap::new();
      const MAX_WEIGHT: f32 = std::f32::MAX;

      // init dist, prev table
      for _ in 0..self.nodes.len() {
        dist.push(MAX_WEIGHT);
        prev.push(0);
      }

      // We're at `start`, with a zero cost
      dist[src as usize] = 0.0;
      q.push(Edge::new(src, dist[src as usize]));

      while let Some(u) = q.pop() {
        // loop for all edges connected to
        for v in self.nodes[u.vertex as usize].iter() {

          let alt: f32 = dist[u.vertex as usize] + v.weight; // accumulate shortest dist from source

          // The variable alt is the length of the path from the root node to the neighbor node v
          // if it were to go through u. If this path is shorter than the current shortest path
          // recorded for v, that current path is replaced with this alt path.
          if alt < dist[v.vertex as usize] {
            dist[v.vertex as usize] = alt; // keep the shortest dist from src to v
            prev[v.vertex as usize] = u.vertex;

            q.push(Edge::new(v.vertex, dist[v.vertex as usize])); // Add unvisited v into the Q to be processed
          }
        }
      }

      let mut shortest_path: Vec<u32> = Vec::new();
      let mut curr: u32 = dst;

      shortest_path.push(curr);

      while curr != src {
        curr = prev[curr as usize];
        shortest_path.push(curr);
      }

      shortest_path.reverse();

      for v in shortest_path.iter() {
        println!("{}", v);
      }
    }
}

fn main() {
    let mut g1 = Graph::new();
    g1.add_edge(0, 1, 1.0);
    g1.add_edge(0, 2, 4.0);
    g1.add_edge(1, 0, 1.0);
    g1.add_edge(1, 2, 2.0);
    g1.add_edge(1, 3, 6.0);
    g1.add_edge(2, 0, 4.0);
    g1.add_edge(2, 1, 2.0);
    g1.add_edge(2, 3, 3.0);
    g1.add_edge(3, 1, 6.0);
    g1.add_edge(3, 2, 3.0);

    g1.bfs(3);

    println!("");

    g1.dfs(3);

    println!("");

    g1.dijkstra(0, 3);
}<commit_msg>changed prev, dist init<commit_after>#![feature(vec_resize)]

use std::iter::repeat;
use std::collections::VecDeque;
use std::collections::BinaryHeap;
use std::cmp::Ordering;

fn max(a: u32, b: u32) -> u32 { if a > b { a } else { b } }

#[derive(Clone)]
struct Edge {
    vertex: u32,
    weight: f32,
}

impl Edge {
    pub fn new(vertex_: u32, weight_: f32) -> Edge {
        Edge{vertex: vertex_, weight: weight_,}
    }
}

impl Ord for Edge {
    fn cmp(&self, other: &Self) -> Ordering {
        self.partial_cmp(other).unwrap()
    }
}

impl Eq for Edge {}

impl PartialOrd for Edge {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        (self.weight, self.vertex).partial_cmp(&(other.weight, other.vertex))
    }
}

impl PartialEq for Edge {
    fn eq(&self, other: &Self) -> bool {
        (self.weight, &self.vertex) == (other.weight, &other.vertex)
    }
}

struct Graph {
    nodes: Vec<Vec<Edge>>,
}

impl Graph {
    pub fn new() -> Graph { Graph{nodes: Vec::new(),} }

    pub fn add_edge(&mut self, src: u32, dst: u32, weight: f32) {
        let len = self.nodes.len();

        if (max(src, dst)) > len as u32 {
            let new_len = (max(src, dst) + 1) as usize;
            self.nodes.extend(repeat(Vec::new()).take(new_len - len))
        }
        self.nodes[src as usize].push(Edge::new(dst, weight));
    }

    pub fn bfs(&self, src: u32) {
        let mut queue: VecDeque<u32> = VecDeque::new();
        let len = self.nodes.len();
        let mut visited = vec!(false ; len);

        queue.push_front(src);

        while let Some(current) = queue.pop_back() {
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            } else { continue ; }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                queue.push_front(neighbor);
            }
        }
    }

    pub fn dfs(&self, src: u32) {
        let mut stack: Vec<u32> = Vec::new();
        let len = self.nodes.len() as usize;
        let mut visited = vec!(false ; len);

        stack.push(src);

        while let Some(current) = stack.pop() {
            if !visited[current as usize] {
                println!("current: {}" , current);
                visited[current as usize] = true;
            } else { continue ; }

            for n in &self.nodes[current as usize] {
                let neighbor: u32 = n.vertex;
                stack.push(neighbor);
            }
        }
    }

    pub fn dijkstra(&self, src: u32, dst: u32) {
      let mut dist: Vec<f32> = Vec::new();
      let mut prev: Vec<u32> = Vec::new();
      let mut q = BinaryHeap::new();
      const MAX_WEIGHT: f32 = std::f32::MAX;

      // init dist, prev table
      // would only work in rust nightly
      dist.resize(self.nodes.len(), MAX_WEIGHT);
      prev.resize(self.nodes.len(), 0);

      // We're at `start`, with a zero cost
      dist[src as usize] = 0.0;
      q.push(Edge::new(src, dist[src as usize]));

      while let Some(u) = q.pop() {
        // loop for all edges connected to
        for v in self.nodes[u.vertex as usize].iter() {

          let alt: f32 = dist[u.vertex as usize] + v.weight; // accumulate shortest dist from source

          // The variable alt is the length of the path from the root node to the neighbor node v
          // if it were to go through u. If this path is shorter than the current shortest path
          // recorded for v, that current path is replaced with this alt path.
          if alt < dist[v.vertex as usize] {
            dist[v.vertex as usize] = alt; // keep the shortest dist from src to v
            prev[v.vertex as usize] = u.vertex;

            q.push(Edge::new(v.vertex, dist[v.vertex as usize])); // Add unvisited v into the Q to be processed
          }
        }
      }

      let mut shortest_path: Vec<u32> = Vec::new();
      let mut curr: u32 = dst;

      shortest_path.push(curr);

      while curr != src {
        curr = prev[curr as usize];
        shortest_path.push(curr);
      }

      shortest_path.reverse();

      for v in shortest_path.iter() {
        println!("{}", v);
      }
    }
}

fn main() {
    let mut g1 = Graph::new();
    g1.add_edge(0, 1, 1.0);
    g1.add_edge(0, 2, 4.0);
    g1.add_edge(1, 0, 1.0);
    g1.add_edge(1, 2, 2.0);
    g1.add_edge(1, 3, 6.0);
    g1.add_edge(2, 0, 4.0);
    g1.add_edge(2, 1, 2.0);
    g1.add_edge(2, 3, 3.0);
    g1.add_edge(3, 1, 6.0);
    g1.add_edge(3, 2, 3.0);

    g1.bfs(3);

    println!("");

    g1.dfs(3);

    println!("");

    g1.dijkstra(0, 3);
}<|endoftext|>