<commit_before>use core::prelude::*;

use free;

use aspace::AddressSpace;
use con;
use con::write;
use dlist::DList;
use dlist::DListNode;
use dlist::DListItem;
use dict::*;
use mem::heap_copy;

pub enum FlagBit {
// The process is currently queued on the run queue.
    Queued = 0,

// Can return to user-mode with sysret, only some registers will be restored:
// rsp, rip: restored to previous values
// rcx, r11: rip and rflags, respectively
// rax: syscall return value
// Remaining registers will be 0 (?)
    FastRet = 1,
// IN_RECV: Similar to FASTRET, when waiting for a message-send rendezvous
// When set together with IN_SEND, it's a sendrcv and the SEND needs to finish
// first.
// At any time when IN_RECV is set, the proc's saved rdi contains a pointer to
// the handle being received from.
// When a process starts a receive, until it becomes properly blocked on some
// process or finishes the receive immediately, it will be both RUNNING and
// IN_RECV.
    InRecv = 2,
// Process is trying to do a synchronous send or sendrcv, blocking on the
// waiting_for process to reach a PROC_IN_RECV state. Both IN_SEND and IN_RECV
// can be set at the same time.
// At any time when IN_SEND is set, the proc's saved rdi contains a pointer to
// the handle being sent to.
// When a process starts a send, until it becomes properly blocked on some
// process or finishes the operation, it will be both RUNNING and IN_SEND.
    InSend = 3,
// Is the currently running process
    Running = 4,
// Process has had a page fault that requires a response from a backer, or has
// requested a page paged in.
// proc.fault_addr is the address that faulted/was requested.
    PFault = 5
}

impl FlagBit {
    #[inline]
    pub fn mask(self) -> uint {
        return 1 << (self as uint);
    }
}
// TODO Implement OR for FlagBit

pub struct FXSaveRegs {
    space : [u8, ..512]
}

pub struct Handle {
    node : DictNode<uint, Handle>,
    process : *mut Process,
    // pointer to other handle if any. Its 'key' field is the other-name that
    // we need when e.g. sending it a message. If null this is not associated
    // in other-proc yet.
    pub other : Option<*mut Handle>,
    pulses : uint,
}

impl DictItem<uint> for Handle {
    fn node<'a>(&'a mut self) -> &'a mut DictNode<uint, Handle> {
        &mut self.node
    }
}

impl Handle {
    pub fn new(id : uint, process : *mut Process) -> Handle {
        Handle {
            node : DictNode::new(id),
            process : process,
            other : None,
            pulses : 0
        }
    }

    pub fn id(&self) -> uint { self.node.key }
    pub fn process(&self) -> &mut Process { unsafe { &mut *self.process } }
    pub fn other(&mut self) -> Option<&mut Handle> {
        match self.other {
        Some(h) => Some(unsafe { &mut *h }),
        None => None,
        }
    }

    pub fn associate(&mut self, other: &mut Handle) {
        self.other = Some(other as *mut Handle);
        other.other = Some(self as *mut Handle);
    }

    pub fn dissociate(&mut self) {
        match self.other() {
        Some(o) => o.other = None,
        None => (),
        }
        self.other = None;
    }

    pub fn add_pulses(&mut self, pulses: uint) -> uint {
        let res = self.pulses;
        self.pulses |= pulses;
        return res;
    }

    pub fn pop_pulses(&mut self) -> uint {
        let res = self.pulses;
        self.pulses = 0;
        return res;
    }
}

pub struct PendingPulse {
    node : DictNode<uint, PendingPulse>,
    handle : *mut Handle,
}

impl DictItem<uint> for PendingPulse {
    fn node<'a>(&'a mut self) -> &'a mut DictNode<uint, PendingPulse> {
        return &mut self.node;
    }
}

impl PendingPulse {
    fn new(handle: &mut Handle) -> PendingPulse {
        PendingPulse {
            node : DictNode::new(handle.id()),
            handle: handle as *mut Handle
        }
    }
}

impl FXSaveRegs {
    fn new() -> FXSaveRegs {
        FXSaveRegs { space : [0, ..512] }
    }
}

pub struct Regs {
    pub rax : uint,
    pub rcx : uint,
    pub rdx : uint,
    pub rbx : uint,
    pub rsp : uint,
    pub rbp : uint,
    pub rsi : uint,
    pub rdi : uint,

    pub r8 : uint,
    pub r9 : uint,
    pub r10 : uint,
    pub r11 : uint,
    pub r12 : uint,
    pub r13 : uint,
    pub r14 : uint,
    pub r15 : uint,

    pub rip : uint,
    pub rflags : uint,
}

impl Regs {
    fn new() -> Regs {
        use x86::rflags;
        Regs {
            rax: 0, rcx: 0, rdx: 0, rbx: 0, rsp: 0, rbp: 0, rsi: 0, rdi: 0,
            r8: 0, r9: 0, r10: 0, r11: 0, r12: 0, r13: 0, r14: 0, r15: 0,
            rip : 0, rflags : rflags::IF
        }
    }
}

type Flags = uint;

pub struct Process {
    pub regs : Regs,
    // Physical address of PML4 to put in CR3
    pub cr3 : uint,

    // Bitwise OR of flags values
    flags : Flags,
    count : uint,

    // Pointer to the process we're waiting for (if any). See flags.
    waiting_for : *mut Process, // Option

    // List of processes waiting on this process.
    pub waiters : DList<Process>,
    node : DListNode<Process>,

    aspace : *mut AddressSpace,

    // TODO: move this into address space so handles can be shared between
    // threads.
    handles : Dict<uint, Handle>,
    pending : Dict<uint, PendingPulse>,

    // When PROC_PFAULT is set, the virtual address that faulted.
    // Note that we lose a lot of data about the mapping that we looked up
    // in PFAULT, and have to look up again in GRANT. This is intentional,
    // since we have to verify and match the GRANT to the correct page, we
    // simply don't save anything that might be wrong.
    // The lower bits are access flags for the fault/request.
    pub fault_addr: uint,

    fxsave : FXSaveRegs,
}

impl DListItem for Process {
    fn node<'a>(&'a mut self) -> &'a mut DListNode<Process> {
        return &mut self.node;
    }
}

impl Process {
    pub fn new(aspace : *mut AddressSpace) -> Process {
        let init_flags = FastRet.mask();
        Process {
            regs : Regs::new(),
            flags : init_flags, count : 0,
            waiting_for : RawPtr::null(),
            waiters : DList::empty(),
            node : DListNode::new(),
            cr3 : unsafe { (*aspace).cr3() },
            aspace : aspace,
            handles : Dict::empty(),
            pending : Dict::empty(),
            fault_addr : 0,
            fxsave : FXSaveRegs::new()
        }
    }

    #[inline]
    pub fn is(&self, f : FlagBit) -> bool {
        (self.flags & f.mask()) != 0
    }

    pub fn ipc_state(&self) -> Flags {
        self.flags & (InRecv.mask() | InSend.mask() | PFault.mask())
    }

    pub fn set(&mut self, f : FlagBit) {
        self.flags |= f.mask();
    }

    pub fn unset(&mut self, f : FlagBit) {
        self.flags &= !f.mask();
    }

    #[inline]
    pub fn is_queued(&self) -> bool { self.is(Queued) }

    pub fn is_runnable(&self) -> bool {
        self.ipc_state() == 0
    }

    pub fn aspace<'a>(&'a mut self) -> &'a mut AddressSpace {
        unsafe {
            return &mut *self.aspace;
        }
    }

    pub fn find_handle<'a>(&mut self, id : uint) -> Option<&'a mut Handle> {
        let res = self.handles.find(id);
        match res {
            Some(ref h) if h.id() != id => None,
            _ => res
        }
    }

    pub fn assoc_handles(&mut self, id: uint, other : &mut Process, other_id: uint) {
        let x = self.new_handle(id, other);
        let y = other.new_handle(other_id, self);
        x.other = Some(y as *mut Handle);
        y.other = Some(x as *mut Handle);
    }

    #[inline(never)]
    pub fn new_handle<'a>(&mut self, id : uint, other : *mut Process) -> &'a mut Handle {
        match self.handles.find(id) {
            Some(ref h) if h.id() != id => (),
            Some(h) => self.delete_handle(h),
            None => ()
        }
        self.handles.insert(heap_copy(Handle::new(id, other)))
    }

    pub fn delete_handle(&mut self, handle : &mut Handle) {
        // FIXME Needs to remove from pending list too.
        handle.dissociate();
        self.handles.remove(handle.node.key);
    }

    pub fn rename_handle(&mut self, handle : &mut Handle, new_id: uint) {
        handle.node.key = new_id;
        // TODO self.handles.unlink/relink/key_changed
    }

    pub fn add_pending_handle(&mut self, handle: &mut Handle) {
        self.pending.insert(heap_copy(PendingPulse::new(handle)));
    }

    pub fn pop_pending_handle<'a>(&mut self) -> Option<&'a mut Handle> {
        match self.pending.pop() {
        Some(p) => unsafe {
            let h = (*p).handle;
            free(p);
            Some(&mut *h)
        },
        None => None,
        }
    }

    pub fn add_waiter(&mut self, other : &mut Process) {
        if other.waiting_for.is_null() {
            self.waiters.append(other);
            other.waiting_for = self as *mut Process;
        }
    }

    pub fn remove_waiter(&mut self, other : &mut Process) {
        if other.waiting_for == (self as *mut Process) {
            self.waiters.remove(other);
            other.waiting_for = RawPtr::null();
        }
    }

    pub fn dump(&self) {
        write("proc ");
        con::writePtr(self);
        write(" f=");
        con::writeHex(self.flags);
        write(":\n");

        for (id,h) in self.handles.iter() {
            write("  handle ");
            con::writeUInt(id);
            write(" -> proc ");
            con::writeMutPtr(h.process());
            con::newline();
        }

        for p in self.waiters.iter() {
            write("  waiter ");
            con::writeMutPtr(p);
            con::newline();
        }
    }
}
<commit_msg>Remove destroyed handles from pending list<commit_after>use core::prelude::*;

use free;

use aspace::AddressSpace;
use con;
use con::write;
use dlist::DList;
use dlist::DListNode;
use dlist::DListItem;
use dict::*;
use mem::heap_copy;

pub enum FlagBit {
// The process is currently queued on the run queue.
    Queued = 0,

// Can return to user-mode with sysret, only some registers will be restored:
// rsp, rip: restored to previous values
// rcx, r11: rip and rflags, respectively
// rax: syscall return value
// Remaining registers will be 0 (?)
    FastRet = 1,
// IN_RECV: Similar to FASTRET, when waiting for a message-send rendezvous
// When set together with IN_SEND, it's a sendrcv and the SEND needs to finish
// first.
// At any time when IN_RECV is set, the proc's saved rdi contains a pointer to
// the handle being received from.
// When a process starts a receive, until it becomes properly blocked on some
// process or finishes the receive immediately, it will be both RUNNING and
// IN_RECV.
    InRecv = 2,
// Process is trying to do a synchronous send or sendrcv, blocking on the
// waiting_for process to reach a PROC_IN_RECV state. Both IN_SEND and IN_RECV
// can be set at the same time.
// At any time when IN_SEND is set, the proc's saved rdi contains a pointer to
// the handle being sent to.
// When a process starts a send, until it becomes properly blocked on some
// process or finishes the operation, it will be both RUNNING and IN_SEND.
    InSend = 3,
// Is the currently running process
    Running = 4,
// Process has had a page fault that requires a response from a backer, or has
// requested a page paged in.
// proc.fault_addr is the address that faulted/was requested.
    PFault = 5
}

impl FlagBit {
    #[inline]
    pub fn mask(self) -> uint {
        return 1 << (self as uint);
    }
}
// TODO Implement OR for FlagBit

pub struct FXSaveRegs {
    space : [u8, ..512]
}

pub struct Handle {
    node : DictNode<uint, Handle>,
    process : *mut Process,
    // pointer to other handle if any. Its 'key' field is the other-name that
    // we need when e.g. sending it a message. If null this is not associated
    // in other-proc yet.
    pub other : Option<*mut Handle>,
    pulses : uint,
}

impl DictItem<uint> for Handle {
    fn node<'a>(&'a mut self) -> &'a mut DictNode<uint, Handle> {
        &mut self.node
    }
}

impl Handle {
    pub fn new(id : uint, process : *mut Process) -> Handle {
        Handle {
            node : DictNode::new(id),
            process : process,
            other : None,
            pulses : 0
        }
    }

    pub fn id(&self) -> uint { self.node.key }
    pub fn process(&self) -> &mut Process { unsafe { &mut *self.process } }
    pub fn other(&mut self) -> Option<&mut Handle> {
        match self.other {
        Some(h) => Some(unsafe { &mut *h }),
        None => None,
        }
    }

    pub fn associate(&mut self, other: &mut Handle) {
        self.other = Some(other as *mut Handle);
        other.other = Some(self as *mut Handle);
    }

    pub fn dissociate(&mut self) {
        match self.other() {
        Some(o) => o.other = None,
        None => (),
        }
        self.other = None;
    }

    pub fn add_pulses(&mut self, pulses: uint) -> uint {
        let res = self.pulses;
        self.pulses |= pulses;
        return res;
    }

    pub fn pop_pulses(&mut self) -> uint {
        let res = self.pulses;
        self.pulses = 0;
        return res;
    }
}

pub struct PendingPulse {
    node : DictNode<uint, PendingPulse>,
    handle : *mut Handle,
}

impl DictItem<uint> for PendingPulse {
    fn node<'a>(&'a mut self) -> &'a mut DictNode<uint, PendingPulse> {
        return &mut self.node;
    }
}

impl PendingPulse {
    fn new(handle: &mut Handle) -> PendingPulse {
        PendingPulse {
            node : DictNode::new(handle.id()),
            handle: handle as *mut Handle
        }
    }
}

impl FXSaveRegs {
    fn new() -> FXSaveRegs {
        FXSaveRegs { space : [0, ..512] }
    }
}

pub struct Regs {
    pub rax : uint,
    pub rcx : uint,
    pub rdx : uint,
    pub rbx : uint,
    pub rsp : uint,
    pub rbp : uint,
    pub rsi : uint,
    pub rdi : uint,

    pub r8 : uint,
    pub r9 : uint,
    pub r10 : uint,
    pub r11 : uint,
    pub r12 : uint,
    pub r13 : uint,
    pub r14 : uint,
    pub r15 : uint,

    pub rip : uint,
    pub rflags : uint,
}

impl Regs {
    fn new() -> Regs {
        use x86::rflags;
        Regs {
            rax: 0, rcx: 0, rdx: 0, rbx: 0, rsp: 0, rbp: 0, rsi: 0, rdi: 0,
            r8: 0, r9: 0, r10: 0, r11: 0, r12: 0, r13: 0, r14: 0, r15: 0,
            rip : 0, rflags : rflags::IF
        }
    }
}

type Flags = uint;

pub struct Process {
    pub regs : Regs,
    // Physical address of PML4 to put in CR3
    pub cr3 : uint,

    // Bitwise OR of flags values
    flags : Flags,
    count : uint,

    // Pointer to the process we're waiting for (if any). See flags.
    waiting_for : *mut Process, // Option

    // List of processes waiting on this process.
    pub waiters : DList<Process>,
    node : DListNode<Process>,

    aspace : *mut AddressSpace,

    // TODO: move this into address space so handles can be shared between
    // threads.
    handles : Dict<uint, Handle>,
    pending : Dict<uint, PendingPulse>,

    // When PROC_PFAULT is set, the virtual address that faulted.
    // Note that we lose a lot of data about the mapping that we looked up
    // in PFAULT, and have to look up again in GRANT. This is intentional,
    // since we have to verify and match the GRANT to the correct page, we
    // simply don't save anything that might be wrong.
    // The lower bits are access flags for the fault/request.
    pub fault_addr: uint,

    fxsave : FXSaveRegs,
}

impl DListItem for Process {
    fn node<'a>(&'a mut self) -> &'a mut DListNode<Process> {
        return &mut self.node;
    }
}

impl Process {
    pub fn new(aspace : *mut AddressSpace) -> Process {
        let init_flags = FastRet.mask();
        Process {
            regs : Regs::new(),
            flags : init_flags, count : 0,
            waiting_for : RawPtr::null(),
            waiters : DList::empty(),
            node : DListNode::new(),
            cr3 : unsafe { (*aspace).cr3() },
            aspace : aspace,
            handles : Dict::empty(),
            pending : Dict::empty(),
            fault_addr : 0,
            fxsave : FXSaveRegs::new()
        }
    }

    #[inline]
    pub fn is(&self, f : FlagBit) -> bool {
        (self.flags & f.mask()) != 0
    }

    pub fn ipc_state(&self) -> Flags {
        self.flags & (InRecv.mask() | InSend.mask() | PFault.mask())
    }

    pub fn set(&mut self, f : FlagBit) {
        self.flags |= f.mask();
    }

    pub fn unset(&mut self, f : FlagBit) {
        self.flags &= !f.mask();
    }

    #[inline]
    pub fn is_queued(&self) -> bool { self.is(Queued) }

    pub fn is_runnable(&self) -> bool {
        self.ipc_state() == 0
    }

    pub fn aspace<'a>(&'a mut self) -> &'a mut AddressSpace {
        unsafe {
            return &mut *self.aspace;
        }
    }

    pub fn find_handle<'a>(&mut self, id : uint) -> Option<&'a mut Handle> {
        let res = self.handles.find(id);
        match res {
            Some(ref h) if h.id() != id => None,
            _ => res
        }
    }

    pub fn assoc_handles(&mut self, id: uint, other : &mut Process, other_id: uint) {
        let x = self.new_handle(id, other);
        let y = other.new_handle(other_id, self);
        x.other = Some(y as *mut Handle);
        y.other = Some(x as *mut Handle);
    }

    #[inline(never)]
    pub fn new_handle<'a>(&mut self, id : uint, other : *mut Process) -> &'a mut Handle {
        match self.handles.find(id) {
            Some(ref h) if h.id() != id => (),
            Some(h) => self.delete_handle(h),
            None => ()
        }
        self.handles.insert(heap_copy(Handle::new(id, other)))
    }

    pub fn delete_handle(&mut self, handle : &mut Handle) {
        handle.dissociate();
        self.pending.remove(handle.node.key);
        self.handles.remove(handle.node.key);
    }

    pub fn rename_handle(&mut self, handle : &mut Handle, new_id: uint) {
        handle.node.key = new_id;
        // TODO self.handles.unlink/relink/key_changed
    }

    pub fn add_pending_handle(&mut self, handle: &mut Handle) {
        self.pending.insert(heap_copy(PendingPulse::new(handle)));
    }

    pub fn pop_pending_handle<'a>(&mut self) -> Option<&'a mut Handle> {
        match self.pending.pop() {
        Some(p) => unsafe {
            let h = (*p).handle;
            free(p);
            Some(&mut *h)
        },
        None => None,
        }
    }

    pub fn add_waiter(&mut self, other : &mut Process) {
        if other.waiting_for.is_null() {
            self.waiters.append(other);
            other.waiting_for = self as *mut Process;
        }
    }

    pub fn remove_waiter(&mut self, other : &mut Process) {
        if other.waiting_for == (self as *mut Process) {
            self.waiters.remove(other);
            other.waiting_for = RawPtr::null();
        }
    }

    pub fn dump(&self) {
        write("proc ");
        con::writePtr(self);
        write(" f=");
        con::writeHex(self.flags);
        write(":\n");

        for (id,h) in self.handles.iter() {
            write("  handle ");
            con::writeUInt(id);
            write(" -> proc ");
            con::writeMutPtr(h.process());
            con::newline();
        }

        for p in self.waiters.iter() {
            write("  waiter ");
            con::writeMutPtr(p);
            con::newline();
        }
    }
}
<|endoftext|>


<commit_before>extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote;
use syn;

//##########################################
// #[derive] mode macros

#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    // Construct a representation of Rust code as a syntax tree
    // that we can manipulate
    let ast: syn::DeriveInput = syn::parse(input).unwrap();

    // Build the trait implementation
    impl_hello_macro(&ast)
}

fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
    let name = &ast.ident;
    let gen = quote! {
        impl HelloMacro for #name {
            fn hello_macro() -> String {
                format!("Hello, Macro! My name is {}", stringify!(#name))
            }
        }
    };
    gen.into()
}

//##########################################
// Attribute-like macros

#[proc_macro_attribute]
pub fn hello(attr: TokenStream, item: TokenStream) -> TokenStream {
    // syn::ItemFn requires feature "full"
    let input = syn::parse_macro_input!(item as syn::ItemFn);
    let name = &input.ident;

    // Our input function is always equivalent to returning 42, right?
    let result = quote! {
        fn #name() -> u32 { 42 }
    };
    result.into()
}

//##########################################
// Function-like macros

// #[proc_macro]
// pub fn sql(input: TokenStream) -> TokenStream {
// }

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<commit_msg>append a file<commit_after>extern crate proc_macro;

use proc_macro::TokenStream;
use quote::quote;
use syn;

//##########################################
// #[derive] mode macros

#[proc_macro_derive(HelloMacro)]
pub fn hello_macro_derive(input: TokenStream) -> TokenStream {
    // Construct a representation of Rust code as a syntax tree
    // that we can manipulate
    let ast: syn::DeriveInput = syn::parse(input).unwrap();

    // Build the trait implementation
    impl_hello_macro(&ast)
}

fn impl_hello_macro(ast: &syn::DeriveInput) -> TokenStream {
    let name = &ast.ident;
    let gen = quote! {
        impl HelloMacro for #name {
            fn hello_macro() -> String {
                format!("Hello, Macro! My name is {}", stringify!(#name))
            }
        }
    };
    gen.into()
}

//##########################################
// Attribute-like macros

#[proc_macro_attribute]
pub fn hello(_attr: TokenStream, item: TokenStream) -> TokenStream {
    // syn::ItemFn requires feature "full"
    let input = syn::parse_macro_input!(item as syn::ItemFn);
    let name = &input.ident;

    // Our input function is always equivalent to returning 42, right?
    let result = quote! {
        fn #name() -> u32 { 42 }
    };
    result.into()
}

#[proc_macro_attribute]
pub fn struct_extension(_attr: TokenStream, item: TokenStream) -> TokenStream {
    // syn::ItemStruct requires feature "full"
    let input = syn::parse_macro_input!(item as syn::ItemStruct);

    let name = &input.ident;

    let result =  match input.fields {
        syn::Fields::Named(ref fields) => {
            let fields = &fields.named;
            quote! {
                struct #name {
                    #fields
                    append: String,
                }
            }
        }
        syn::Fields::Unnamed(ref _fields) => panic!("not support now!"),
        syn::Fields::Unit => panic!("not support now!"),
    };

    result.into()
}

//##########################################
// Function-like macros

// #[proc_macro]
// pub fn sql(input: TokenStream) -> TokenStream {
// }

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}
<|endoftext|>


<commit_before>// Copyright ⓒ 2015-2018 Kevin B. Knapp
//
// `clap_complete` is distributed under the terms of both the MIT license and the Apache License
// (Version 2.0).
// See the [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) files in this repository
// for more information.

#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![doc = include_str!("../README.md")]
#![warn(missing_docs, trivial_casts, unused_allocation, trivial_numeric_casts)]
#![forbid(unsafe_code)]
#![allow(clippy::needless_doctest_main)]

//! ## Quick Start
//!
//! - For generating at compile-time, see [`generate_to`]
//! - For generating at runtime, see [`generate`]
//!
//! [`Shell`] is a convenience `enum` for an argument value type that implements `Generator`
//! for each natively-supported shell type.
//!
//! ## Example
//!
//! ```rust,no_run
//! use clap::{Command, AppSettings, Arg, ValueHint, value_parser};
//! use clap_complete::{generate, Generator, Shell};
//! use std::io;
//!
//! fn build_cli() -> Command<'static> {
//!     Command::new("example")
//!          .arg(Arg::new("file")
//!              .help("some input file")
//!                 .value_hint(ValueHint::AnyPath),
//!         )
//!        .arg(
//!            Arg::new("generator")
//!                .long("generate")
//!                .value_parser(value_parser!(Shell)),
//!        )
//! }
//!
//! fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
//!     generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
//! }
//!
//! fn main() {
//!     let matches = build_cli().get_matches();
//!
//!     if let Ok(generator) = matches.value_of_t::<Shell>("generator") {
//!         let mut cmd = build_cli();
//!         eprintln!("Generating completion file for {}...", generator);
//!         print_completions(generator, &mut cmd);
//!     }
//! }
//! ```

const INTERNAL_ERROR_MSG: &str = "Fatal internal error. Please consider filing a bug \
                                  report at https://github.com/clap-rs/clap/issues";

#[macro_use]
#[allow(missing_docs)]
mod macros;

pub mod generator;
pub mod shells;

pub use generator::generate;
pub use generator::generate_to;
pub use generator::Generator;
pub use shells::Shell;

#[cfg(feature = "unstable-dynamic")]
pub mod dynamic;
<commit_msg>docs(complete): Make example consistent<commit_after>// Copyright ⓒ 2015-2018 Kevin B. Knapp
//
// `clap_complete` is distributed under the terms of both the MIT license and the Apache License
// (Version 2.0).
// See the [LICENSE-APACHE](LICENSE-APACHE) and [LICENSE-MIT](LICENSE-MIT) files in this repository
// for more information.

#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![doc = include_str!("../README.md")]
#![warn(missing_docs, trivial_casts, unused_allocation, trivial_numeric_casts)]
#![forbid(unsafe_code)]
#![allow(clippy::needless_doctest_main)]

//! ## Quick Start
//!
//! - For generating at compile-time, see [`generate_to`]
//! - For generating at runtime, see [`generate`]
//!
//! [`Shell`] is a convenience `enum` for an argument value type that implements `Generator`
//! for each natively-supported shell type.
//!
//! ## Example
//!
//! ```rust,no_run
//! use clap::{Command, Arg, ValueHint, value_parser};
//! use clap_complete::{generate, Generator, Shell};
//! use std::io;
//!
//! fn build_cli() -> Command<'static> {
//!     Command::new("example")
//!          .arg(Arg::new("file")
//!              .help("some input file")
//!                 .value_hint(ValueHint::AnyPath),
//!         )
//!        .arg(
//!            Arg::new("generator")
//!                .long("generate")
//!                .takes_value(true)
//!                .value_parser(value_parser!(Shell)),
//!        )
//! }
//!
//! fn print_completions<G: Generator>(gen: G, cmd: &mut Command) {
//!     generate(gen, cmd, cmd.get_name().to_string(), &mut io::stdout());
//! }
//!
//! fn main() {
//!     let matches = build_cli().get_matches();
//!
//!     if let Some(generator) = matches.get_one::<Shell>("generator").copied() {
//!         let mut cmd = build_cli();
//!         eprintln!("Generating completion file for {}...", generator);
//!         print_completions(generator, &mut cmd);
//!     }
//! }
//! ```

const INTERNAL_ERROR_MSG: &str = "Fatal internal error. Please consider filing a bug \
                                  report at https://github.com/clap-rs/clap/issues";

#[macro_use]
#[allow(missing_docs)]
mod macros;

pub mod generator;
pub mod shells;

pub use generator::generate;
pub use generator::generate_to;
pub use generator::Generator;
pub use shells::Shell;

#[cfg(feature = "unstable-dynamic")]
pub mod dynamic;
<|endoftext|>


<commit_before>//! Log all requests in a format similar to Heroku's router, but with additional
//! information that we care about like User-Agent

use super::prelude::*;
use crate::util::request_header;
use conduit::{header, RequestExt, StatusCode};
use std::fmt::{self, Display, Formatter};
use std::time::Instant;

const SLOW_REQUEST_THRESHOLD_MS: u64 = 1000;

#[derive(Default)]
pub(super) struct LogRequests();

struct RequestStart(Instant);

impl Middleware for LogRequests {
    fn before(&self, req: &mut dyn RequestExt) -> BeforeResult {
        req.mut_extensions().insert(RequestStart(Instant::now()));
        Ok(())
    }

    fn after(&self, req: &mut dyn RequestExt, res: AfterResult) -> AfterResult {
        // Unwrap shouldn't panic as no other code has access to the private struct to remove it
        let request_start = req.extensions().find::<RequestStart>().unwrap().0;

        let response_time = request_start.elapsed();
        let response_time =
            response_time.as_secs() * 1000 + u64::from(response_time.subsec_nanos()) / 1_000_000;

        println!(
            "{}",
            RequestLine {
                req,
                res: &res,
                response_time,
            }
        );

        res
    }
}

struct CustomMetadata {
    entries: Vec<(&'static str, String)>,
}

pub fn add_custom_metadata<V: Display>(req: &mut dyn RequestExt, key: &'static str, value: V) {
    if let Some(metadata) = req.mut_extensions().find_mut::<CustomMetadata>() {
        metadata.entries.push((key, value.to_string()));
    } else {
        let mut metadata = CustomMetadata {
            entries: Vec::new(),
        };
        metadata.entries.push((key, value.to_string()));
        req.mut_extensions().insert(metadata);
    }
}

#[cfg(test)]
pub(crate) fn get_log_message(req: &dyn RequestExt, key: &'static str) -> String {
    for (k, v) in &req.extensions().find::<CustomMetadata>().unwrap().entries {
        if key == *k {
            return v.clone();
        }
    }
    panic!("expected log message for {} not found", key);
}

struct RequestLine<'r> {
    req: &'r dyn RequestExt,
    res: &'r AfterResult,
    response_time: u64,
}

impl Display for RequestLine<'_> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        let mut line = LogLine::new(f);

        let (at, status) = match self.res {
            Ok(resp) => ("info", resp.status()),
            Err(_) => ("error", StatusCode::INTERNAL_SERVER_ERROR),
        };

        line.add_field("at", at)?;
        line.add_field("method", self.req.method())?;
        line.add_quoted_field("path", FullPath(self.req))?;
        line.add_field("request_id", request_header(self.req, "x-request-id"))?;
        line.add_quoted_field("fwd", request_header(self.req, "x-real-ip"))?;
        line.add_field("service", TimeMs(self.response_time))?;
        line.add_field("status", status)?;
        line.add_quoted_field("user_agent", request_header(self.req, header::USER_AGENT))?;

        if let Some(metadata) = self.req.extensions().find::<CustomMetadata>() {
            for (key, value) in &metadata.entries {
                line.add_quoted_field(key, value)?;
            }
        }

        if let Err(err) = self.res {
            line.add_quoted_field("error", err)?;
        }

        if self.response_time > SLOW_REQUEST_THRESHOLD_MS {
            line.add_marker("SLOW REQUEST")?;
        }

        Ok(())
    }
}

struct FullPath<'a>(&'a dyn RequestExt);

impl<'a> Display for FullPath<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0.path())?;
        if let Some(q_string) = self.0.query_string() {
            write!(f, "?{}", q_string)?;
        }
        Ok(())
    }
}

struct TimeMs(u64);

impl Display for TimeMs {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)?;
        f.write_str("ms")?;
        Ok(())
    }
}

struct LogLine<'f, 'g> {
    f: &'f mut Formatter<'g>,
    first: bool,
}

impl<'f, 'g> LogLine<'f, 'g> {
    fn new(f: &'f mut Formatter<'g>) -> Self {
        Self { f, first: true }
    }

    fn add_field<K: Display, V: Display>(&mut self, key: K, value: V) -> fmt::Result {
        self.start_item()?;

        key.fmt(self.f)?;
        self.f.write_str("=")?;
        value.fmt(self.f)?;

        Ok(())
    }

    fn add_quoted_field<K: Display, V: Display>(&mut self, key: K, value: V) -> fmt::Result {
        self.start_item()?;

        key.fmt(self.f)?;
        self.f.write_str("=\"")?;
        value.fmt(self.f)?;
        self.f.write_str("\"")?;

        Ok(())
    }

    fn add_marker<M: Display>(&mut self, marker: M) -> fmt::Result {
        self.start_item()?;

        marker.fmt(self.f)?;

        Ok(())
    }

    fn start_item(&mut self) -> fmt::Result {
        if !self.first {
            self.f.write_str(" ")?;
        }
        self.first = false;
        Ok(())
    }
}
<commit_msg>Output the status code as a static string slice<commit_after>//! Log all requests in a format similar to Heroku's router, but with additional
//! information that we care about like User-Agent

use super::prelude::*;
use crate::util::request_header;
use conduit::{header, RequestExt, StatusCode};
use std::fmt::{self, Display, Formatter};
use std::time::Instant;

const SLOW_REQUEST_THRESHOLD_MS: u64 = 1000;

#[derive(Default)]
pub(super) struct LogRequests();

struct RequestStart(Instant);

impl Middleware for LogRequests {
    fn before(&self, req: &mut dyn RequestExt) -> BeforeResult {
        req.mut_extensions().insert(RequestStart(Instant::now()));
        Ok(())
    }

    fn after(&self, req: &mut dyn RequestExt, res: AfterResult) -> AfterResult {
        // Unwrap shouldn't panic as no other code has access to the private struct to remove it
        let request_start = req.extensions().find::<RequestStart>().unwrap().0;

        let response_time = request_start.elapsed();
        let response_time =
            response_time.as_secs() * 1000 + u64::from(response_time.subsec_nanos()) / 1_000_000;

        println!(
            "{}",
            RequestLine {
                req,
                res: &res,
                response_time,
            }
        );

        res
    }
}

struct CustomMetadata {
    entries: Vec<(&'static str, String)>,
}

pub fn add_custom_metadata<V: Display>(req: &mut dyn RequestExt, key: &'static str, value: V) {
    if let Some(metadata) = req.mut_extensions().find_mut::<CustomMetadata>() {
        metadata.entries.push((key, value.to_string()));
    } else {
        let mut metadata = CustomMetadata {
            entries: Vec::new(),
        };
        metadata.entries.push((key, value.to_string()));
        req.mut_extensions().insert(metadata);
    }
}

#[cfg(test)]
pub(crate) fn get_log_message(req: &dyn RequestExt, key: &'static str) -> String {
    for (k, v) in &req.extensions().find::<CustomMetadata>().unwrap().entries {
        if key == *k {
            return v.clone();
        }
    }
    panic!("expected log message for {} not found", key);
}

struct RequestLine<'r> {
    req: &'r dyn RequestExt,
    res: &'r AfterResult,
    response_time: u64,
}

impl Display for RequestLine<'_> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        let mut line = LogLine::new(f);

        let (at, status) = match self.res {
            Ok(resp) => ("info", resp.status()),
            Err(_) => ("error", StatusCode::INTERNAL_SERVER_ERROR),
        };

        line.add_field("at", at)?;
        line.add_field("method", self.req.method())?;
        line.add_quoted_field("path", FullPath(self.req))?;
        line.add_field("request_id", request_header(self.req, "x-request-id"))?;
        line.add_quoted_field("fwd", request_header(self.req, "x-real-ip"))?;
        line.add_field("service", TimeMs(self.response_time))?;
        line.add_field("status", status.as_str())?;
        line.add_quoted_field("user_agent", request_header(self.req, header::USER_AGENT))?;

        if let Some(metadata) = self.req.extensions().find::<CustomMetadata>() {
            for (key, value) in &metadata.entries {
                line.add_quoted_field(key, value)?;
            }
        }

        if let Err(err) = self.res {
            line.add_quoted_field("error", err)?;
        }

        if self.response_time > SLOW_REQUEST_THRESHOLD_MS {
            line.add_marker("SLOW REQUEST")?;
        }

        Ok(())
    }
}

struct FullPath<'a>(&'a dyn RequestExt);

impl<'a> Display for FullPath<'a> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0.path())?;
        if let Some(q_string) = self.0.query_string() {
            write!(f, "?{}", q_string)?;
        }
        Ok(())
    }
}

struct TimeMs(u64);

impl Display for TimeMs {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)?;
        f.write_str("ms")?;
        Ok(())
    }
}

struct LogLine<'f, 'g> {
    f: &'f mut Formatter<'g>,
    first: bool,
}

impl<'f, 'g> LogLine<'f, 'g> {
    fn new(f: &'f mut Formatter<'g>) -> Self {
        Self { f, first: true }
    }

    fn add_field<K: Display, V: Display>(&mut self, key: K, value: V) -> fmt::Result {
        self.start_item()?;

        key.fmt(self.f)?;
        self.f.write_str("=")?;
        value.fmt(self.f)?;

        Ok(())
    }

    fn add_quoted_field<K: Display, V: Display>(&mut self, key: K, value: V) -> fmt::Result {
        self.start_item()?;

        key.fmt(self.f)?;
        self.f.write_str("=\"")?;
        value.fmt(self.f)?;
        self.f.write_str("\"")?;

        Ok(())
    }

    fn add_marker<M: Display>(&mut self, marker: M) -> fmt::Result {
        self.start_item()?;

        marker.fmt(self.f)?;

        Ok(())
    }

    fn start_item(&mut self) -> fmt::Result {
        if !self.first {
            self.f.write_str(" ")?;
        }
        self.first = false;
        Ok(())
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::vec::Vec;
// use std::io::{Read, Write};
use std::collections::VecDeque;
use std::option::Option;

use mio::{Token, EventLoop, EventSet, PollOpt, TryRead, TryWrite};
use mio::tcp::TcpStream;
use bytes::{Buf, MutBuf, ByteBuf, MutByteBuf, alloc};

use raftserver::Result;
use super::ConnData;
use super::server::Server;
use super::handler::ServerHandler;
use util::codec::rpc;

pub struct Conn {
    pub sock: TcpStream,
    pub token: Token,
    pub interest: EventSet,

    // peer_addr is for remote peer address, we only set this
    // when we connect to the remote peer.
    pub peer_addr: Option<String>,

    // message header
    last_msg_id: u64,
    header: MutByteBuf,
    // message
    payload: Option<MutByteBuf>,

    // write buffer, including msg header already.
    res: VecDeque<ByteBuf>,
}

fn try_read_data<T: TryRead, B: MutBuf>(r: &mut T, buf: &mut B) -> Result<()> {
    if buf.remaining() == 0 {
        return Ok(());
    }

    // TODO: use try_read_buf directly if we can solve the compile problem.
    unsafe {
        // header is not full read, we will try read more.
        let n = try!(r.try_read(buf.mut_bytes()));
        match n {
            None => {
                // nothing to do here now, but should we return an error or panic?
                error!("connection read None data");
            }
            Some(n) => buf.advance(n),
        }
    }

    Ok(())
}

fn create_mem_buf(s: usize) -> MutByteBuf {
    unsafe {
        ByteBuf::from_mem_ref(alloc::heap(s.next_power_of_two()), s as u32, 0, s as u32).flip()
    }
}

impl Conn {
    pub fn new(sock: TcpStream, token: Token, peer_addr: Option<String>) -> Conn {
        Conn {
            sock: sock,
            token: token,
            interest: EventSet::readable() | EventSet::hup(),
            header: create_mem_buf(rpc::MSG_HEADER_LEN),
            payload: None,
            res: VecDeque::new(),
            last_msg_id: 0,
            peer_addr: peer_addr,
        }
    }

    pub fn reregister<T: ServerHandler>(&mut self,
                                        event_loop: &mut EventLoop<Server<T>>)
                                        -> Result<()> {
        try!(event_loop.reregister(&self.sock, self.token, self.interest, PollOpt::edge()));
        Ok(())
    }

    pub fn read<T: ServerHandler>(&mut self,
                                  _: &mut EventLoop<Server<T>>)
                                  -> Result<(Vec<ConnData>)> {
        let mut bufs = vec![];

        loop {
            // Because we use the edge trigger, so here we must read whole data.
            if self.payload.is_none() {
                try!(try_read_data(&mut self.sock, &mut self.header));
                if self.header.remaining() > 0 {
                    // we need to read more data for header
                    break;
                }

                // we have already read whole header, parse it and begin to read payload.
                let (msg_id, payload_len) = try!(rpc::decode_msg_header(self.header
                                                                            .bytes()));
                self.last_msg_id = msg_id;
                self.payload = Some(create_mem_buf(payload_len));
            }

            // payload here can't be None.
            let mut payload = self.payload.take().unwrap();
            try!(try_read_data(&mut self.sock, &mut payload));
            if payload.remaining() > 0 {
                // we need to read more data for payload
                self.payload = Some(payload);
                break;
            }

            bufs.push(ConnData {
                msg_id: self.last_msg_id,
                data: payload.flip(),
            });

            self.header.clear();
        }

        Ok((bufs))
    }

    fn write_buf(&mut self) -> Result<usize> {
        // we check empty before.
        let mut buf = self.res.front_mut().unwrap();

        let n = try!(self.sock.try_write(buf.bytes()));
        match n {
            None => {}
            Some(n) => buf.advance(n),
        }

        Ok(buf.remaining())
    }

    pub fn write<T: ServerHandler>(&mut self, event_loop: &mut EventLoop<Server<T>>) -> Result<()> {
        while !self.res.is_empty() {
            let remaining = try!(self.write_buf());

            if remaining > 0 {
                // we don't write all data, so must try later.
                // we have already registered writable, no need registering again.
                return Ok(());
            }
            self.res.pop_front();
        }

        // no data for writing, remove writable.
        self.interest.remove(EventSet::writable());
        self.reregister(event_loop)
    }

    pub fn append_write_buf<T: ServerHandler>(&mut self,
                                              event_loop: &mut EventLoop<Server<T>>,
                                              msg: ConnData)
                                              -> Result<()> {
        // Now we just push data to a write buffer and register writable for later writing.
        // Later we can write data directly, if meet WOUNDBLOCK error(don't write all data OK),
        // we can register writable at that time.
        // We must also check `socket is not connected` error too, when we connect to a remote
        // peer, mio puts this socket in event loop immediately, but this socket may not be
        // connected at that time, so we must register writable too for this case.
        self.res.push_back(msg.encode_to_buf());

        if !self.interest.is_writable() {
            // re-register writable if we have not,
            // if registered, we can only remove this flag when
            // writing all data in writable function.
            self.interest.insert(EventSet::writable());
            return self.reregister(event_loop);
        }

        Ok(())
    }
}
<commit_msg>server: Tiny clean up<commit_after>#![allow(dead_code)]

use std::vec::Vec;
// use std::io::{Read, Write};
use std::collections::VecDeque;
use std::option::Option;

use mio::{Token, EventLoop, EventSet, PollOpt, TryRead, TryWrite};
use mio::tcp::TcpStream;
use bytes::{Buf, MutBuf, ByteBuf, MutByteBuf, alloc};

use raftserver::Result;
use super::ConnData;
use super::server::Server;
use super::handler::ServerHandler;
use util::codec::rpc;

pub struct Conn {
    pub sock: TcpStream,
    pub token: Token,
    pub interest: EventSet,

    // peer_addr is for remote peer address, we only set this
    // when we connect to the remote peer.
    pub peer_addr: Option<String>,

    // message header
    last_msg_id: u64,
    header: MutByteBuf,
    // message
    payload: Option<MutByteBuf>,

    // write buffer, including msg header already.
    res: VecDeque<ByteBuf>,
}

fn try_read_data<T: TryRead, B: MutBuf>(r: &mut T, buf: &mut B) -> Result<()> {
    if buf.remaining() == 0 {
        return Ok(());
    }

    // TODO: use try_read_buf directly if we can solve the compile problem.
    unsafe {
        // header is not full read, we will try read more.
        let n = try!(r.try_read(buf.mut_bytes()));
        match n {
            None => {
                // nothing to do here now, but should we return an error or panic?
                error!("connection read None data");
            }
            Some(n) => buf.advance(n),
        }
    }

    Ok(())
}

fn create_mem_buf(s: usize) -> MutByteBuf {
    unsafe {
        ByteBuf::from_mem_ref(alloc::heap(s.next_power_of_two()), s as u32, 0, s as u32).flip()
    }
}

impl Conn {
    pub fn new(sock: TcpStream, token: Token, peer_addr: Option<String>) -> Conn {
        Conn {
            sock: sock,
            token: token,
            interest: EventSet::readable() | EventSet::hup(),
            header: create_mem_buf(rpc::MSG_HEADER_LEN),
            payload: None,
            res: VecDeque::new(),
            last_msg_id: 0,
            peer_addr: peer_addr,
        }
    }

    pub fn reregister<T: ServerHandler>(&mut self,
                                        event_loop: &mut EventLoop<Server<T>>)
                                        -> Result<()> {
        try!(event_loop.reregister(&self.sock, self.token, self.interest, PollOpt::edge()));
        Ok(())
    }

    pub fn read<T: ServerHandler>(&mut self,
                                  _: &mut EventLoop<Server<T>>)
                                  -> Result<Vec<ConnData>> {
        let mut bufs = vec![];

        loop {
            // Because we use the edge trigger, so here we must read whole data.
            if self.payload.is_none() {
                try!(try_read_data(&mut self.sock, &mut self.header));
                if self.header.remaining() > 0 {
                    // we need to read more data for header
                    break;
                }

                // we have already read whole header, parse it and begin to read payload.
                let (msg_id, payload_len) = try!(rpc::decode_msg_header(self.header
                                                                            .bytes()));
                self.last_msg_id = msg_id;
                self.payload = Some(create_mem_buf(payload_len));
            }

            // payload here can't be None.
            let mut payload = self.payload.take().unwrap();
            try!(try_read_data(&mut self.sock, &mut payload));
            if payload.remaining() > 0 {
                // we need to read more data for payload
                self.payload = Some(payload);
                break;
            }

            bufs.push(ConnData {
                msg_id: self.last_msg_id,
                data: payload.flip(),
            });

            self.header.clear();
        }

        Ok(bufs)
    }

    fn write_buf(&mut self) -> Result<usize> {
        // we check empty before.
        let mut buf = self.res.front_mut().unwrap();

        let n = try!(self.sock.try_write(buf.bytes()));
        match n {
            None => {}
            Some(n) => buf.advance(n),
        }

        Ok(buf.remaining())
    }

    pub fn write<T: ServerHandler>(&mut self, event_loop: &mut EventLoop<Server<T>>) -> Result<()> {
        while !self.res.is_empty() {
            let remaining = try!(self.write_buf());

            if remaining > 0 {
                // we don't write all data, so must try later.
                // we have already registered writable, no need registering again.
                return Ok(());
            }
            self.res.pop_front();
        }

        // no data for writing, remove writable.
        self.interest.remove(EventSet::writable());
        self.reregister(event_loop)
    }

    pub fn append_write_buf<T: ServerHandler>(&mut self,
                                              event_loop: &mut EventLoop<Server<T>>,
                                              msg: ConnData)
                                              -> Result<()> {
        // Now we just push data to a write buffer and register writable for later writing.
        // Later we can write data directly, if meet WOUNDBLOCK error(don't write all data OK),
        // we can register writable at that time.
        // We must also check `socket is not connected` error too, when we connect to a remote
        // peer, mio puts this socket in event loop immediately, but this socket may not be
        // connected at that time, so we must register writable too for this case.
        self.res.push_back(msg.encode_to_buf());

        if !self.interest.is_writable() {
            // re-register writable if we have not,
            // if registered, we can only remove this flag when
            // writing all data in writable function.
            self.interest.insert(EventSet::writable());
            return self.reregister(event_loop);
        }

        Ok(())
    }
}
<|endoftext|>


<commit_before>fn main() {
    println!("Hello, world!");
}
<commit_msg>Example of initialization and inserting data to hash map<commit_after>use std::collections::HashMap;

fn main() {
    let mut scores = HashMap::new();
    scores.insert(String::from("Blue"), 10);
    scores.insert(String::from("Yellow"), 50);
}
<|endoftext|>


<commit_before>extern crate num_traits;

use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::fmt::{self, Display, Formatter};
use std::hash::Hash;
use std::iter::FromIterator;
use std::vec::Vec;
use self::num_traits::One;
use recognisable::Transition;
use pmcfg::{PMCFG, PMCFGRule, VarT};
use tree_stack_automaton::{TreeStack, TreeStackAutomaton, TreeStackInstruction};

// types for analysis of derivation trees of PMCFGs
pub type RuleCallerMap<N, T, W> = BTreeMap<PMCFGRule<N, T, W>, Vec<(usize, Vec<T>)>>;
pub type DerivationSnippet<N, T, W> = (PMCFGRule<N, T, W>, Vec<Vec<PMCFGRule<N, T, W>>>);

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub enum PosState<X> {
    Designated,
    Initial,
    Position(X, usize, usize),
}

impl<X> PosState<X> {
    pub fn map<F, Y>(&self, f: F) -> PosState<Y>
        where F: Fn(&X) -> Y,
    {
        match *self {
            PosState::Designated => PosState::Designated,
            PosState::Initial => PosState::Initial,
            PosState::Position(ref x, i, j) => PosState::Position(f(x), i, j),
        }
    }
}

impl<X: Display> Display for PosState<X> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            PosState::Designated
                => write!(f, "@"),
            PosState::Initial
                => write!(f, "I"),
            PosState::Position(ref x, i, j)
                => write!(f, "({}, {}, {})", x, i, j)
        }
    }
}

// TODO assumes that the PMCFG is monotonic on the visit-order of components
impl<N: Clone + Ord + PartialEq + Hash,
     T: Clone + Ord + PartialEq + Hash,
     W: Clone + Ord + PartialEq + One
     > From<PMCFG<N, T, W>> for TreeStackAutomaton<PosState<PMCFGRule<N, T, W>>, T, W> {
    fn from(g: PMCFG<N, T, W>) -> Self {
        let mut transitions = Vec::new();

        let mut rule_map: BTreeMap<N, Vec<PMCFGRule<N, T, W>>>
            = BTreeSet::from_iter(
                g.rules
                    .iter()
                    .map(|r| r.head.clone())
            )
            .iter()
            .map(|n| (
                n.clone(),
                Vec::<PMCFGRule<N, T, W>>::new()
            ))
            .collect();

        let mut down_info: RuleCallerMap<N, T, W>
            = BTreeMap::new();

        let mut initial_rules: Vec<PMCFGRule<N, T, W>>
            = Vec::new();

        for r in g.rules.clone() {
            if g.initial.contains(&r.head) {
                initial_rules.push(r.clone())
            }
            rule_map.get_mut(&r.head).unwrap().push(r.clone());

            let mut var_cnt_vec = Vec::new();
            let mut i: usize;
            let mut down_buffer: Vec<T> = Vec::new();
            for component in &r.composition.composition {
                i = 0;
                for ntt in component {
                    down_buffer.clear();
                    match *ntt {
                        VarT::Var(_, _)
                            => {
                                i += 1;
                                down_buffer.clear();
                            },
                        VarT::T(ref t)
                            => {
                                down_buffer.push(t.clone());
                            }
                    }
                }
                var_cnt_vec.push((i, down_buffer.clone()));
            }
            down_info.insert(r.clone(), var_cnt_vec);
        }

        for r in initial_rules {
            transitions.push(
                Transition {
                    word: Vec::new(),
                    weight: r.weight.clone(),
                    instruction: TreeStackInstruction::Push {
                        n: 0,
                        current_val: PosState::Initial,
                        new_val: PosState::Position(r.clone(), 0, 0)
                    }
                }
            );

            match down_info[&r][0] {
                (j, ref word) => {
                    transitions.push(
                        Transition {
                            word: word.clone(),
                            weight: W::one(),
                            instruction: TreeStackInstruction::Down {
                                current_val: PosState::Position(r.clone(), 0, j),
                                old_val: PosState::Initial,
                                new_val: PosState::Designated
                            }
                        }
                    );
                }
            }
        }
        // each [r, [r₁, …, rₖ]] on the agenda signifies that r(r₁(…), …, rₖ(…)) is a possible subderivation
        let mut agenda: Vec<DerivationSnippet<N, T, W>>
            = Vec::new();

        for r in g.rules {
            agenda.push(
                ( r.clone(),
                  r.tail.iter().map(|n| rule_map[n].clone()).collect()
                )
            );
        }

        let mut buffer: Vec<T>;

        let mut j: usize;
        let mut k: usize;

        for (r, rss) in agenda {
            j = 0;
            let mut previous_component: Vec<Option<usize>> = rss.iter().map(|_| None).collect();
            for component in r.composition.composition.clone() {
                buffer = Vec::new();
                k = 0;
                for token in component {
                    match token {
                        VarT::Var(i1, j1) => {
                            for ri in &rss[i1] {
                                transitions.push(Transition {
                                    word: buffer.clone(),
                                    weight: match previous_component[i1] {
                                        None => ri.weight.clone(),
                                        Some(_) => W::one(),
                                    },
                                    instruction: match previous_component[i1] {
                                        None => {
                                            TreeStackInstruction::Push {
                                                n: i1,
                                                current_val: PosState::Position(r.clone(), j, k),
                                                new_val: PosState::Position(ri.clone(), j1, 0)
                                            }
                                        },
                                        Some(j0) => {
                                            TreeStackInstruction::Up {
                                                n: i1,
                                                current_val: PosState::Position(r.clone(), j, k),
                                                old_val: PosState::Position(
                                                    ri.clone(),
                                                    j0,
                                                    down_info[ri][j0].0
                                                ),
                                                new_val: PosState::Position(ri.clone(), j1, 0)
                                            }
                                        }
                                    }
                                });

                                transitions.push(Transition {
                                    word: down_info[ri][j1].1.clone(),
                                    weight: W::one(),
                                    instruction: TreeStackInstruction::Down {
                                        current_val: PosState::Position(
                                            ri.clone(),
                                            j1,
                                            down_info[ri][j1].0
                                        ),
                                        old_val: PosState::Position(r.clone(), j, k),
                                        new_val: PosState::Position(r.clone(), j, k + 1)
                                    }
                                });
                            }

                            previous_component[i1] = Some(j1);
                            k += 1;
                            buffer.clear();
                        },

                        VarT::T(t) => {
                            buffer.push(t);
                        }
                    }
                }

                j += 1;
            }
        }

        TreeStackAutomaton::new(
            transitions,
            TreeStack::new(PosState::Initial)
        )
    }
}
<commit_msg>src/tree_stack_automaton/from_pmcfg.rs: added to_abstract_syntax_tree()<commit_after>extern crate num_traits;

use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::fmt::{self, Display, Formatter};
use std::hash::Hash;
use std::iter::FromIterator;
use std::vec::Vec;
use self::num_traits::One;
use recognisable::Transition;
use pmcfg::{PMCFG, PMCFGRule, VarT};
use tree_stack_automaton::{TreeStack, TreeStackAutomaton, TreeStackInstruction};

// types for analysis of derivation trees of PMCFGs
pub type RuleCallerMap<N, T, W> = BTreeMap<PMCFGRule<N, T, W>, Vec<(usize, Vec<T>)>>;
pub type DerivationSnippet<N, T, W> = (PMCFGRule<N, T, W>, Vec<Vec<PMCFGRule<N, T, W>>>);

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub enum PosState<X> {
    Designated,
    Initial,
    Position(X, usize, usize),
}

impl<X> PosState<X> {
    pub fn map<F, Y>(&self, f: F) -> PosState<Y>
        where F: Fn(&X) -> Y,
    {
        match *self {
            PosState::Designated => PosState::Designated,
            PosState::Initial => PosState::Initial,
            PosState::Position(ref x, i, j) => PosState::Position(f(x), i, j),
        }
    }
}

impl<X: Display> Display for PosState<X> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        match *self {
            PosState::Designated
                => write!(f, "@"),
            PosState::Initial
                => write!(f, "I"),
            PosState::Position(ref x, i, j)
                => write!(f, "({}, {}, {})", x, i, j)
        }
    }
}

// TODO assumes that the PMCFG is monotonic on the visit-order of components
impl<N: Clone + Ord + PartialEq + Hash,
     T: Clone + Ord + PartialEq + Hash,
     W: Clone + Ord + PartialEq + One
     > From<PMCFG<N, T, W>> for TreeStackAutomaton<PosState<PMCFGRule<N, T, W>>, T, W> {
    fn from(g: PMCFG<N, T, W>) -> Self {
        let mut transitions = Vec::new();

        let mut rule_map: BTreeMap<N, Vec<PMCFGRule<N, T, W>>>
            = BTreeSet::from_iter(
                g.rules
                    .iter()
                    .map(|r| r.head.clone())
            )
            .iter()
            .map(|n| (
                n.clone(),
                Vec::<PMCFGRule<N, T, W>>::new()
            ))
            .collect();

        let mut down_info: RuleCallerMap<N, T, W>
            = BTreeMap::new();

        let mut initial_rules: Vec<PMCFGRule<N, T, W>>
            = Vec::new();

        for r in g.rules.clone() {
            if g.initial.contains(&r.head) {
                initial_rules.push(r.clone())
            }
            rule_map.get_mut(&r.head).unwrap().push(r.clone());

            let mut var_cnt_vec = Vec::new();
            let mut i: usize;
            let mut down_buffer: Vec<T> = Vec::new();
            for component in &r.composition.composition {
                i = 0;
                for ntt in component {
                    down_buffer.clear();
                    match *ntt {
                        VarT::Var(_, _)
                            => {
                                i += 1;
                                down_buffer.clear();
                            },
                        VarT::T(ref t)
                            => {
                                down_buffer.push(t.clone());
                            }
                    }
                }
                var_cnt_vec.push((i, down_buffer.clone()));
            }
            down_info.insert(r.clone(), var_cnt_vec);
        }

        for r in initial_rules {
            transitions.push(
                Transition {
                    word: Vec::new(),
                    weight: r.weight.clone(),
                    instruction: TreeStackInstruction::Push {
                        n: 0,
                        current_val: PosState::Initial,
                        new_val: PosState::Position(r.clone(), 0, 0)
                    }
                }
            );

            match down_info[&r][0] {
                (j, ref word) => {
                    transitions.push(
                        Transition {
                            word: word.clone(),
                            weight: W::one(),
                            instruction: TreeStackInstruction::Down {
                                current_val: PosState::Position(r.clone(), 0, j),
                                old_val: PosState::Initial,
                                new_val: PosState::Designated
                            }
                        }
                    );
                }
            }
        }
        // each [r, [r₁, …, rₖ]] on the agenda signifies that r(r₁(…), …, rₖ(…)) is a possible subderivation
        let mut agenda: Vec<DerivationSnippet<N, T, W>>
            = Vec::new();

        for r in g.rules {
            agenda.push(
                ( r.clone(),
                  r.tail.iter().map(|n| rule_map[n].clone()).collect()
                )
            );
        }

        let mut buffer: Vec<T>;

        let mut j: usize;
        let mut k: usize;

        for (r, rss) in agenda {
            j = 0;
            let mut previous_component: Vec<Option<usize>> = rss.iter().map(|_| None).collect();
            for component in r.composition.composition.clone() {
                buffer = Vec::new();
                k = 0;
                for token in component {
                    match token {
                        VarT::Var(i1, j1) => {
                            for ri in &rss[i1] {
                                transitions.push(Transition {
                                    word: buffer.clone(),
                                    weight: match previous_component[i1] {
                                        None => ri.weight.clone(),
                                        Some(_) => W::one(),
                                    },
                                    instruction: match previous_component[i1] {
                                        None => {
                                            TreeStackInstruction::Push {
                                                n: i1,
                                                current_val: PosState::Position(r.clone(), j, k),
                                                new_val: PosState::Position(ri.clone(), j1, 0)
                                            }
                                        },
                                        Some(j0) => {
                                            TreeStackInstruction::Up {
                                                n: i1,
                                                current_val: PosState::Position(r.clone(), j, k),
                                                old_val: PosState::Position(
                                                    ri.clone(),
                                                    j0,
                                                    down_info[ri][j0].0
                                                ),
                                                new_val: PosState::Position(ri.clone(), j1, 0)
                                            }
                                        }
                                    }
                                });

                                transitions.push(Transition {
                                    word: down_info[ri][j1].1.clone(),
                                    weight: W::one(),
                                    instruction: TreeStackInstruction::Down {
                                        current_val: PosState::Position(
                                            ri.clone(),
                                            j1,
                                            down_info[ri][j1].0
                                        ),
                                        old_val: PosState::Position(r.clone(), j, k),
                                        new_val: PosState::Position(r.clone(), j, k + 1)
                                    }
                                });
                            }

                            previous_component[i1] = Some(j1);
                            k += 1;
                            buffer.clear();
                        },

                        VarT::T(t) => {
                            buffer.push(t);
                        }
                    }
                }

                j += 1;
            }
        }

        TreeStackAutomaton::new(
            transitions,
            TreeStack::new(PosState::Initial)
        )
    }
}

pub fn to_abstract_syntax_tree<A>((tree_map, _): (BTreeMap<Vec<usize>, PosState<A>>, Vec<usize>)) -> BTreeMap<Vec<usize>, A> {
    let mut abstract_syntax_tree = BTreeMap::new();

    for (address, pos_state) in tree_map {
        let (curr_root_child, relative_address) = if let Some((first, rest)) = address.split_first() {
            (first.clone(), rest.to_vec())
        } else {
            continue;
        };

        if curr_root_child != 0 {
            continue;
        }

        if let PosState::Position(value, _, _) = pos_state {
            abstract_syntax_tree.insert(relative_address, value);
        } else {
            panic!("The given tree map contains 'designated' or 'initial' nodes that are not the root!");
        }
    }

    abstract_syntax_tree
}
<|endoftext|>


<commit_before>use core::borrow::Borrow;
use core::cmp::Ordering;
use core::ops::{Bound, RangeBounds};

use super::node::{marker, ForceResult::*, Handle, NodeRef};

use SearchBound::*;
use SearchResult::*;

pub enum SearchBound<T> {
    /// An inclusive bound to look for, just like `Bound::Included(T)`.
    Included(T),
    /// An exclusive bound to look for, just like `Bound::Excluded(T)`.
    Excluded(T),
    /// An unconditional inclusive bound, just like `Bound::Unbounded`.
    AllIncluded,
    /// An unconditional exclusive bound.
    AllExcluded,
}

impl<T> SearchBound<T> {
    pub fn from_range(range_bound: Bound<T>) -> Self {
        match range_bound {
            Bound::Included(t) => Included(t),
            Bound::Excluded(t) => Excluded(t),
            Bound::Unbounded => AllIncluded,
        }
    }
}

pub enum SearchResult<BorrowType, K, V, FoundType, GoDownType> {
    Found(Handle<NodeRef<BorrowType, K, V, FoundType>, marker::KV>),
    GoDown(Handle<NodeRef<BorrowType, K, V, GoDownType>, marker::Edge>),
}

pub enum IndexResult {
    KV(usize),
    Edge(usize),
}

impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
    /// Looks up a given key in a (sub)tree headed by the node, recursively.
    /// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
    /// returns a `GoDown` with the handle of the leaf edge where the key belongs.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    pub fn search_tree<Q: ?Sized>(
        mut self,
        key: &Q,
    ) -> SearchResult<BorrowType, K, V, marker::LeafOrInternal, marker::Leaf>
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        loop {
            self = match self.search_node(key) {
                Found(handle) => return Found(handle),
                GoDown(handle) => match handle.force() {
                    Leaf(leaf) => return GoDown(leaf),
                    Internal(internal) => internal.descend(),
                },
            }
        }
    }

    /// Descends to the nearest node where the edge matching the lower bound
    /// of the range is different from the edge matching the upper bound, i.e.,
    /// the nearest node that has at least one key contained in the range.
    ///
    /// If found, returns an `Ok` with that node, the pair of edge indices in it
    /// delimiting the range, and the corresponding pair of bounds for
    /// continuing the search in the child nodes, in case the node is internal.
    ///
    /// If not found, returns an `Err` with the leaf edge matching the entire
    /// range.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    pub fn search_tree_for_bifurcation<'r, Q: ?Sized, R>(
        mut self,
        range: &'r R,
    ) -> Result<
        (
            NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
            usize,
            usize,
            SearchBound<&'r Q>,
            SearchBound<&'r Q>,
        ),
        Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
    >
    where
        Q: Ord,
        K: Borrow<Q>,
        R: RangeBounds<Q>,
    {
        // It might be unsound to inline these variables if this logic changes (#81138).
        // We assume the bounds reported by `range` remain the same, but
        // an adversarial implementation could change between calls
        let (start, end) = (range.start_bound(), range.end_bound());
        match (start, end) {
            (Bound::Excluded(s), Bound::Excluded(e)) if s == e => {
                panic!("range start and end are equal and excluded in BTreeMap")
            }
            (Bound::Included(s) | Bound::Excluded(s), Bound::Included(e) | Bound::Excluded(e))
                if s > e =>
            {
                panic!("range start is greater than range end in BTreeMap")
            }
            _ => {}
        }
        let mut lower_bound = SearchBound::from_range(start);
        let mut upper_bound = SearchBound::from_range(end);
        loop {
            let (lower_edge_idx, lower_child_bound) = self.find_lower_bound_index(lower_bound);
            let (upper_edge_idx, upper_child_bound) = self.find_upper_bound_index(upper_bound);
            // SAFETY: This panic is used for safety, so external impls can't be called here. The
            // comparison is done with integers for that reason.
            if lower_edge_idx > upper_edge_idx {
                panic!("Ord is ill-defined in BTreeMap range")
            }
            if lower_edge_idx < upper_edge_idx {
                return Ok((
                    self,
                    lower_edge_idx,
                    upper_edge_idx,
                    lower_child_bound,
                    upper_child_bound,
                ));
            }
            let common_edge = unsafe { Handle::new_edge(self, lower_edge_idx) };
            match common_edge.force() {
                Leaf(common_edge) => return Err(common_edge),
                Internal(common_edge) => {
                    self = common_edge.descend();
                    lower_bound = lower_child_bound;
                    upper_bound = upper_child_bound;
                }
            }
        }
    }

    /// Finds an edge in the node delimiting the lower bound of a range.
    /// Also returns the lower bound to be used for continuing the search in
    /// the matching child node, if `self` is an internal node.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    pub fn find_lower_bound_edge<'r, Q>(
        self,
        bound: SearchBound<&'r Q>,
    ) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        let (edge_idx, bound) = self.find_lower_bound_index(bound);
        let edge = unsafe { Handle::new_edge(self, edge_idx) };
        (edge, bound)
    }

    /// Clone of `find_lower_bound_edge` for the upper bound.
    pub fn find_upper_bound_edge<'r, Q>(
        self,
        bound: SearchBound<&'r Q>,
    ) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        let (edge_idx, bound) = self.find_upper_bound_index(bound);
        let edge = unsafe { Handle::new_edge(self, edge_idx) };
        (edge, bound)
    }
}

impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
    /// Looks up a given key in the node, without recursion.
    /// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
    /// returns a `GoDown` with the handle of the edge where the key might be found
    /// (if the node is internal) or where the key can be inserted.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    pub fn search_node<Q: ?Sized>(self, key: &Q) -> SearchResult<BorrowType, K, V, Type, Type>
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        match self.find_key_index(key) {
            IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }),
            IndexResult::Edge(idx) => GoDown(unsafe { Handle::new_edge(self, idx) }),
        }
    }

    /// Returns either the KV index in the node at which the key (or an equivalent)
    /// exists, or the edge index where the key belongs.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    fn find_key_index<Q: ?Sized>(&self, key: &Q) -> IndexResult
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        let node = self.reborrow();
        let keys = node.keys();
        for (i, k) in keys.iter().enumerate() {
            match key.cmp(k.borrow()) {
                Ordering::Greater => {}
                Ordering::Equal => return IndexResult::KV(i),
                Ordering::Less => return IndexResult::Edge(i),
            }
        }
        IndexResult::Edge(keys.len())
    }

    /// Finds an edge index in the node delimiting the lower bound of a range.
    /// Also returns the lower bound to be used for continuing the search in
    /// the matching child node, if `self` is an internal node.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    fn find_lower_bound_index<'r, Q>(
        &self,
        bound: SearchBound<&'r Q>,
    ) -> (usize, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        match bound {
            Included(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx, AllExcluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            Excluded(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx + 1, AllIncluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            AllIncluded => (0, AllIncluded),
            AllExcluded => (self.len(), AllExcluded),
        }
    }

    /// Clone of `find_lower_bound_index` for the upper bound.
    fn find_upper_bound_index<'r, Q>(
        &self,
        bound: SearchBound<&'r Q>,
    ) -> (usize, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        match bound {
            Included(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx + 1, AllExcluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            Excluded(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx, AllIncluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            AllIncluded => (self.len(), AllIncluded),
            AllExcluded => (0, AllExcluded),
        }
    }
}
<commit_msg>Fix comments based on review<commit_after>use core::borrow::Borrow;
use core::cmp::Ordering;
use core::ops::{Bound, RangeBounds};

use super::node::{marker, ForceResult::*, Handle, NodeRef};

use SearchBound::*;
use SearchResult::*;

pub enum SearchBound<T> {
    /// An inclusive bound to look for, just like `Bound::Included(T)`.
    Included(T),
    /// An exclusive bound to look for, just like `Bound::Excluded(T)`.
    Excluded(T),
    /// An unconditional inclusive bound, just like `Bound::Unbounded`.
    AllIncluded,
    /// An unconditional exclusive bound.
    AllExcluded,
}

impl<T> SearchBound<T> {
    pub fn from_range(range_bound: Bound<T>) -> Self {
        match range_bound {
            Bound::Included(t) => Included(t),
            Bound::Excluded(t) => Excluded(t),
            Bound::Unbounded => AllIncluded,
        }
    }
}

pub enum SearchResult<BorrowType, K, V, FoundType, GoDownType> {
    Found(Handle<NodeRef<BorrowType, K, V, FoundType>, marker::KV>),
    GoDown(Handle<NodeRef<BorrowType, K, V, GoDownType>, marker::Edge>),
}

pub enum IndexResult {
    KV(usize),
    Edge(usize),
}

impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
    /// Looks up a given key in a (sub)tree headed by the node, recursively.
    /// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
    /// returns a `GoDown` with the handle of the leaf edge where the key belongs.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    pub fn search_tree<Q: ?Sized>(
        mut self,
        key: &Q,
    ) -> SearchResult<BorrowType, K, V, marker::LeafOrInternal, marker::Leaf>
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        loop {
            self = match self.search_node(key) {
                Found(handle) => return Found(handle),
                GoDown(handle) => match handle.force() {
                    Leaf(leaf) => return GoDown(leaf),
                    Internal(internal) => internal.descend(),
                },
            }
        }
    }

    /// Descends to the nearest node where the edge matching the lower bound
    /// of the range is different from the edge matching the upper bound, i.e.,
    /// the nearest node that has at least one key contained in the range.
    ///
    /// If found, returns an `Ok` with that node, the pair of edge indices in it
    /// delimiting the range, and the corresponding pair of bounds for
    /// continuing the search in the child nodes, in case the node is internal.
    ///
    /// If not found, returns an `Err` with the leaf edge matching the entire
    /// range.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    pub fn search_tree_for_bifurcation<'r, Q: ?Sized, R>(
        mut self,
        range: &'r R,
    ) -> Result<
        (
            NodeRef<BorrowType, K, V, marker::LeafOrInternal>,
            usize,
            usize,
            SearchBound<&'r Q>,
            SearchBound<&'r Q>,
        ),
        Handle<NodeRef<BorrowType, K, V, marker::Leaf>, marker::Edge>,
    >
    where
        Q: Ord,
        K: Borrow<Q>,
        R: RangeBounds<Q>,
    {
        // Inlining these variables should be avoided. We assume the bounds reported by `range`
        // remain the same, but an adversarial implementation could change between calls (#81138).
        let (start, end) = (range.start_bound(), range.end_bound());
        match (start, end) {
            (Bound::Excluded(s), Bound::Excluded(e)) if s == e => {
                panic!("range start and end are equal and excluded in BTreeMap")
            }
            (Bound::Included(s) | Bound::Excluded(s), Bound::Included(e) | Bound::Excluded(e))
                if s > e =>
            {
                panic!("range start is greater than range end in BTreeMap")
            }
            _ => {}
        }
        let mut lower_bound = SearchBound::from_range(start);
        let mut upper_bound = SearchBound::from_range(end);
        loop {
            let (lower_edge_idx, lower_child_bound) = self.find_lower_bound_index(lower_bound);
            let (upper_edge_idx, upper_child_bound) = self.find_upper_bound_index(upper_bound);
            if lower_edge_idx > upper_edge_idx {
                panic!("Ord is ill-defined in BTreeMap range")
            }
            if lower_edge_idx < upper_edge_idx {
                return Ok((
                    self,
                    lower_edge_idx,
                    upper_edge_idx,
                    lower_child_bound,
                    upper_child_bound,
                ));
            }
            let common_edge = unsafe { Handle::new_edge(self, lower_edge_idx) };
            match common_edge.force() {
                Leaf(common_edge) => return Err(common_edge),
                Internal(common_edge) => {
                    self = common_edge.descend();
                    lower_bound = lower_child_bound;
                    upper_bound = upper_child_bound;
                }
            }
        }
    }

    /// Finds an edge in the node delimiting the lower bound of a range.
    /// Also returns the lower bound to be used for continuing the search in
    /// the matching child node, if `self` is an internal node.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    pub fn find_lower_bound_edge<'r, Q>(
        self,
        bound: SearchBound<&'r Q>,
    ) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        let (edge_idx, bound) = self.find_lower_bound_index(bound);
        let edge = unsafe { Handle::new_edge(self, edge_idx) };
        (edge, bound)
    }

    /// Clone of `find_lower_bound_edge` for the upper bound.
    pub fn find_upper_bound_edge<'r, Q>(
        self,
        bound: SearchBound<&'r Q>,
    ) -> (Handle<Self, marker::Edge>, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        let (edge_idx, bound) = self.find_upper_bound_index(bound);
        let edge = unsafe { Handle::new_edge(self, edge_idx) };
        (edge, bound)
    }
}

impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
    /// Looks up a given key in the node, without recursion.
    /// Returns a `Found` with the handle of the matching KV, if any. Otherwise,
    /// returns a `GoDown` with the handle of the edge where the key might be found
    /// (if the node is internal) or where the key can be inserted.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    pub fn search_node<Q: ?Sized>(self, key: &Q) -> SearchResult<BorrowType, K, V, Type, Type>
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        match self.find_key_index(key) {
            IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }),
            IndexResult::Edge(idx) => GoDown(unsafe { Handle::new_edge(self, idx) }),
        }
    }

    /// Returns either the KV index in the node at which the key (or an equivalent)
    /// exists, or the edge index where the key belongs.
    ///
    /// The result is meaningful only if the tree is ordered by key, like the tree
    /// in a `BTreeMap` is.
    fn find_key_index<Q: ?Sized>(&self, key: &Q) -> IndexResult
    where
        Q: Ord,
        K: Borrow<Q>,
    {
        let node = self.reborrow();
        let keys = node.keys();
        for (i, k) in keys.iter().enumerate() {
            match key.cmp(k.borrow()) {
                Ordering::Greater => {}
                Ordering::Equal => return IndexResult::KV(i),
                Ordering::Less => return IndexResult::Edge(i),
            }
        }
        IndexResult::Edge(keys.len())
    }

    /// Finds an edge index in the node delimiting the lower bound of a range.
    /// Also returns the lower bound to be used for continuing the search in
    /// the matching child node, if `self` is an internal node.
    ///
    /// The result is meaningful only if the tree is ordered by key.
    fn find_lower_bound_index<'r, Q>(
        &self,
        bound: SearchBound<&'r Q>,
    ) -> (usize, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        match bound {
            Included(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx, AllExcluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            Excluded(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx + 1, AllIncluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            AllIncluded => (0, AllIncluded),
            AllExcluded => (self.len(), AllExcluded),
        }
    }

    /// Clone of `find_lower_bound_index` for the upper bound.
    fn find_upper_bound_index<'r, Q>(
        &self,
        bound: SearchBound<&'r Q>,
    ) -> (usize, SearchBound<&'r Q>)
    where
        Q: ?Sized + Ord,
        K: Borrow<Q>,
    {
        match bound {
            Included(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx + 1, AllExcluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            Excluded(key) => match self.find_key_index(key) {
                IndexResult::KV(idx) => (idx, AllIncluded),
                IndexResult::Edge(idx) => (idx, bound),
            },
            AllIncluded => (self.len(), AllIncluded),
            AllExcluded => (0, AllExcluded),
        }
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(clippy)]
#![deny(clippy)]

fn prefix_underscore(_x: u32) -> u32 {
    _x + 1 //~ ERROR used binding which is prefixed with an underscore
}

fn in_macro(_x: u32) {
    println!("{}", _x); //~ ERROR used binding which is prefixed with an underscore
}

fn non_prefix_underscore(some_foo: u32) -> u32 {
    some_foo + 1
}

fn unused_underscore(_foo: u32) -> u32 {
    1
}

fn main() {
    let foo = 0u32;
    // tests of unused_underscore lint
    let _ = prefix_underscore(foo);
    in_macro(foo);
    // possible false positives
    let _ = non_prefix_underscore(foo);
    let _ = unused_underscore(foo);
}

<commit_msg>Add more tests<commit_after>#![feature(plugin)]
#![plugin(clippy)]
#![deny(clippy)]

/// Test that we lint if we use a binding with a single leading underscore
fn prefix_underscore(_x: u32) -> u32 {
    _x + 1 //~ ERROR used binding which is prefixed with an underscore
}

/// Test that we lint even if the use is within a macro expansion
fn in_macro(_x: u32) {
    println!("{}", _x); //~ ERROR used binding which is prefixed with an underscore
}

/// Test that we do not lint if the underscore is not a prefix
fn non_prefix_underscore(some_foo: u32) -> u32 {
    some_foo + 1
}

/// Test that we do not lint if we do not use the binding
fn unused_underscore(_foo: u32) -> u32 {
    1
}

// Non-variable bindings with preceding underscore
fn _fn_test() {}
struct _StructTest;
enum _EnumTest {
    _FieldA,
    _FieldB(_StructTest)
}

/// Test that we do not lint for non-variable bindings
fn non_variables() {
    _fn_test();
    let _s = _StructTest;
    let _e = match _EnumTest::_FieldB(_StructTest) {
        _EnumTest::_FieldA => 0,
        _EnumTest::_FieldB(_st) => 1,
    };
    let f = _fn_test;
    f();
}

fn main() {
    let foo = 0u32;
    // tests of unused_underscore lint
    let _ = prefix_underscore(foo);
    in_macro(foo);
    // possible false positives
    let _ = non_prefix_underscore(foo);
    let _ = unused_underscore(foo);
    non_variables();
}

<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::smoke_test_environment::SwarmBuilder;
use aptos::move_tool::MemberId;
use aptos::test::CliTestFramework;
use aptos_logger::info;
use move_deps::move_package::source_package::manifest_parser::parse_move_manifest_from_file;
use std::collections::BTreeMap;
use std::str::FromStr;

const PACKAGE_NAME: &str = "AwesomePackage";
const HELLO_BLOCKCHAIN: &str = "HelloBlockchain";

#[tokio::test]
async fn test_move_compile_flow() {
    let mut cli = CliTestFramework::local_new(1);

    cli.init_move_dir();
    let move_dir = cli.move_dir();
    let account = cli.account_id(0).to_hex_literal();

    let mut package_addresses = BTreeMap::new();
    package_addresses.insert(HELLO_BLOCKCHAIN, "_");

    cli.init_package(PACKAGE_NAME.to_string(), package_addresses)
        .await
        .expect("Should succeed");

    // The manifest should work to compile
    let mut named_addresses = BTreeMap::new();
    named_addresses.insert(HELLO_BLOCKCHAIN, account.as_str());
    match cli.compile_package(named_addresses.clone()).await {
        Ok(modules) => assert!(modules.is_empty()),
        Err(err) => panic!("Error compiling: {:?}", err),
    }

    // Let's check that it's setup correctly
    let manifest = parse_move_manifest_from_file(move_dir.join("Move.toml").as_path())
        .expect("Expect a Move.toml file");
    assert_eq!(manifest.package.name.as_str(), PACKAGE_NAME);
    // Expect "0.0.0"
    assert_eq!(manifest.package.version.0, 0);
    assert_eq!(manifest.package.version.1, 0);
    assert_eq!(manifest.package.version.2, 0);

    let addresses = manifest.addresses.expect("Expect some addresses");
    assert_eq!(addresses.len(), 1);
    let (key, value) = addresses.iter().next().expect("Expect an address");
    assert_eq!(key.as_str(), HELLO_BLOCKCHAIN);
    assert!(value.is_none());

    assert_eq!(manifest.dependencies.len(), 1);

    let dependency = manifest.dependencies.iter().next().unwrap();
    assert_eq!("AptosFramework", dependency.0.to_string());
    dependency
        .1
        .git_info
        .as_ref()
        .expect("Expect some git information");

    // Now try to compile real code
    cli.add_move_files();

    match cli.compile_package(named_addresses.clone()).await {
        Ok(modules) => assert!(!modules.is_empty()),
        Err(err) => panic!("Error compiling: {:?}", err),
    }

    // Run tests to ensure they work too
    match cli.test_package(named_addresses.clone(), None).await {
        Ok(result) => assert_eq!("Success", result),
        Err(err) => panic!("Error testing: {:?}", err),
    }
}

#[tokio::test]
async fn test_move_publish_flow() {
    let (_swarm, mut cli, _faucet) = SwarmBuilder::new_local(1)
        .with_aptos()
        .build_with_cli(2)
        .await;

    let account = cli.account_id(0).to_hex_literal();
    // Setup move package
    cli.init_move_dir();
    let mut package_addresses = BTreeMap::new();
    package_addresses.insert(HELLO_BLOCKCHAIN, "_");
    cli.init_package(PACKAGE_NAME.to_string(), package_addresses)
        .await
        .expect("Should succeed");
    cli.add_move_files();

    cli.wait_for_account(0)
        .await
        .expect("Should create account");
    info!("Move package dir: {}", cli.move_dir().display());

    // Let's publish it
    let mut named_addresses = BTreeMap::new();
    named_addresses.insert(HELLO_BLOCKCHAIN, account.as_str());
    let _ = match cli.publish_package(0, None, named_addresses, false).await {
        Ok(response) => response,
        Err(err) => panic!("Should not have failed to publish package {:?}", err),
    };

    // TODO: Verify transaction summary

    // Wrong number of args will definitely fail
    let function_id = MemberId::from_str(&format!("{}::message::set_message", account)).unwrap();

    assert!(cli
        .run_function(0, None, function_id.clone(), vec![], vec![])
        .await
        .is_err());

    assert!(cli
        .run_function(0, None, function_id, vec!["string:hello_world"], vec![])
        .await
        .is_ok());
    // TODO: Verify output
}
<commit_msg>[testsuite] Bump version used for move init<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::smoke_test_environment::SwarmBuilder;
use aptos::move_tool::MemberId;
use aptos::test::CliTestFramework;
use aptos_logger::info;
use move_deps::move_package::source_package::manifest_parser::parse_move_manifest_from_file;
use std::collections::BTreeMap;
use std::str::FromStr;

const PACKAGE_NAME: &str = "AwesomePackage";
const HELLO_BLOCKCHAIN: &str = "HelloBlockchain";

#[tokio::test]
async fn test_move_compile_flow() {
    let mut cli = CliTestFramework::local_new(1);

    cli.init_move_dir();
    let move_dir = cli.move_dir();
    let account = cli.account_id(0).to_hex_literal();

    let mut package_addresses = BTreeMap::new();
    package_addresses.insert(HELLO_BLOCKCHAIN, "_");

    cli.init_package(PACKAGE_NAME.to_string(), package_addresses)
        .await
        .expect("Should succeed");

    // The manifest should work to compile
    let mut named_addresses = BTreeMap::new();
    named_addresses.insert(HELLO_BLOCKCHAIN, account.as_str());
    match cli.compile_package(named_addresses.clone()).await {
        Ok(modules) => assert!(modules.is_empty()),
        Err(err) => panic!("Error compiling: {:?}", err),
    }

    // Let's check that it's setup correctly
    let manifest = parse_move_manifest_from_file(move_dir.join("Move.toml").as_path())
        .expect("Expect a Move.toml file");
    assert_eq!(manifest.package.name.as_str(), PACKAGE_NAME);
    // Expect "1.0.0"
    assert_eq!(manifest.package.version.0, 1);
    assert_eq!(manifest.package.version.1, 0);
    assert_eq!(manifest.package.version.2, 0);

    let addresses = manifest.addresses.expect("Expect some addresses");
    assert_eq!(addresses.len(), 1);
    let (key, value) = addresses.iter().next().expect("Expect an address");
    assert_eq!(key.as_str(), HELLO_BLOCKCHAIN);
    assert!(value.is_none());

    assert_eq!(manifest.dependencies.len(), 1);

    let dependency = manifest.dependencies.iter().next().unwrap();
    assert_eq!("AptosFramework", dependency.0.to_string());
    dependency
        .1
        .git_info
        .as_ref()
        .expect("Expect some git information");

    // Now try to compile real code
    cli.add_move_files();

    match cli.compile_package(named_addresses.clone()).await {
        Ok(modules) => assert!(!modules.is_empty()),
        Err(err) => panic!("Error compiling: {:?}", err),
    }

    // Run tests to ensure they work too
    match cli.test_package(named_addresses.clone(), None).await {
        Ok(result) => assert_eq!("Success", result),
        Err(err) => panic!("Error testing: {:?}", err),
    }
}

#[tokio::test]
async fn test_move_publish_flow() {
    let (_swarm, mut cli, _faucet) = SwarmBuilder::new_local(1)
        .with_aptos()
        .build_with_cli(2)
        .await;

    let account = cli.account_id(0).to_hex_literal();
    // Setup move package
    cli.init_move_dir();
    let mut package_addresses = BTreeMap::new();
    package_addresses.insert(HELLO_BLOCKCHAIN, "_");
    cli.init_package(PACKAGE_NAME.to_string(), package_addresses)
        .await
        .expect("Should succeed");
    cli.add_move_files();

    cli.wait_for_account(0)
        .await
        .expect("Should create account");
    info!("Move package dir: {}", cli.move_dir().display());

    // Let's publish it
    let mut named_addresses = BTreeMap::new();
    named_addresses.insert(HELLO_BLOCKCHAIN, account.as_str());
    let _ = match cli.publish_package(0, None, named_addresses, false).await {
        Ok(response) => response,
        Err(err) => panic!("Should not have failed to publish package {:?}", err),
    };

    // TODO: Verify transaction summary

    // Wrong number of args will definitely fail
    let function_id = MemberId::from_str(&format!("{}::message::set_message", account)).unwrap();

    assert!(cli
        .run_function(0, None, function_id.clone(), vec![], vec![])
        .await
        .is_err());

    assert!(cli
        .run_function(0, None, function_id, vec!["string:hello_world"], vec![])
        .await
        .is_ok());
    // TODO: Verify output
}
<|endoftext|>