<commit_before>use std::collections::hash_map::HashMap;
use std::mem::size_of;

use dora_parser::lexer::position::Position;

use crate::baseline::fct::{JitBaselineFct, JitDescriptor, JitFct, JitFctId};
use crate::baseline::map::CodeDescriptor;
use crate::cpu::{Mem, FREG_PARAMS, REG_FP, REG_PARAMS, REG_SP, REG_THREAD, REG_TMP1};
use crate::exception::DoraToNativeInfo;
use crate::gc::Address;
use crate::masm::MacroAssembler;
use crate::mem;
use crate::threads::{ThreadLocalData, THREAD};
use crate::ty::{BuiltinType, MachineMode};
use crate::vm::FctId;
use crate::vm::VM;

pub struct NativeThunks {
    map: HashMap<Address, JitFctId>,
}

impl NativeThunks {
    pub fn new() -> NativeThunks {
        NativeThunks {
            map: HashMap::new(),
        }
    }

    pub fn find_fct(&self, ptr: Address) -> Option<JitFctId> {
        self.map.get(&ptr).map(|&jit_fct_id| jit_fct_id)
    }

    pub fn insert_fct(&mut self, ptr: Address, fct: JitFctId) {
        self.map.entry(ptr).or_insert(fct);
    }
}

#[derive(Clone)]
pub enum InternalFctDescriptor {
    NativeThunk(FctId),
    AllocThunk,
    VerifyThunk,
    TrapThunk,
}

pub struct InternalFct<'a> {
    pub ptr: Address,
    pub args: &'a [BuiltinType],
    pub return_type: BuiltinType,
    pub throws: bool,
    pub desc: InternalFctDescriptor,
}

pub fn generate<'a, 'ast: 'a>(vm: &'a VM<'ast>, fct: InternalFct, dbg: bool) -> JitFctId {
    let fct_desc = fct.desc.clone();

    let ngen = NativeGen {
        vm,
        masm: MacroAssembler::new(),
        fct,
        dbg,
    };

    let jit_fct = ngen.generate();
    let jit_start = jit_fct.ptr_start();
    let jit_end = jit_fct.ptr_end();
    let jit_fct_id: JitFctId = vm.jit_fcts.push(JitFct::Base(jit_fct)).into();

    let code_desc = match fct_desc {
        InternalFctDescriptor::NativeThunk(_) => CodeDescriptor::NativeThunk(jit_fct_id),
        InternalFctDescriptor::TrapThunk => CodeDescriptor::TrapThunk,
        InternalFctDescriptor::VerifyThunk => CodeDescriptor::VerifyThunk,
        InternalFctDescriptor::AllocThunk => CodeDescriptor::AllocThunk,
    };

    vm.insert_code_map(jit_start, jit_end, code_desc);

    jit_fct_id
}

struct NativeGen<'a, 'ast: 'a> {
    vm: &'a VM<'ast>,
    masm: MacroAssembler,

    fct: InternalFct<'a>,
    dbg: bool,
}

impl<'a, 'ast> NativeGen<'a, 'ast>
where
    'ast: 'a,
{
    pub fn generate(mut self) -> JitBaselineFct {
        let save_return = self.fct.return_type != BuiltinType::Unit;
        let args = self.fct.args.len();

        let dtn_size = size_of::<DoraToNativeInfo>() as i32;

        let offset_dtn = 0;
        let offset_return = dtn_size;
        let offset_args = offset_return + if save_return { mem::ptr_width() } else { 0 };
        let framesize = mem::align_i32(offset_args + args as i32 * mem::ptr_width(), 16);

        // `start_native_call` assumes that offset_dtn is on top of current stack frame.

        if self.dbg {
            self.masm.debug();
        }

        self.masm.prolog_size(framesize);

        save_params(&mut self.masm, self.fct.args, offset_args);

        self.masm.load_mem(
            MachineMode::Ptr,
            REG_TMP1.into(),
            Mem::Base(REG_THREAD, ThreadLocalData::dtn_offset()),
        );

        self.masm.store_mem(
            MachineMode::Ptr,
            Mem::Base(REG_SP, offset_dtn + DoraToNativeInfo::last_offset()),
            REG_TMP1.into(),
        );

        self.masm.store_mem(
            MachineMode::Ptr,
            Mem::Base(REG_SP, offset_dtn + DoraToNativeInfo::fp_offset()),
            REG_FP.into(),
        );

        self.masm.copy_pc(REG_TMP1);

        self.masm.store_mem(
            MachineMode::Ptr,
            Mem::Base(REG_SP, offset_dtn + DoraToNativeInfo::pc_offset()),
            REG_TMP1.into(),
        );

        self.masm.store_mem(
            MachineMode::Ptr,
            Mem::Base(REG_THREAD, ThreadLocalData::dtn_offset()),
            REG_SP.into(),
        );

        restore_params(&mut self.masm, self.fct.args, offset_args);

        self.masm.raw_call(self.fct.ptr.to_ptr());

        self.masm.load_mem(
            MachineMode::Ptr,
            REG_TMP1.into(),
            Mem::Base(REG_SP, offset_dtn + DoraToNativeInfo::last_offset()),
        );

        self.masm.store_mem(
            MachineMode::Ptr,
            Mem::Base(REG_THREAD, ThreadLocalData::dtn_offset()),
            REG_TMP1.into(),
        );

        self.masm.load_mem(
            MachineMode::Ptr,
            REG_TMP1.into(),
            Mem::Base(REG_THREAD, ThreadLocalData::exception_object_offset()),
        );

        let lbl_exception = self.masm.test_if_not_nil(REG_TMP1);

        self.masm.safepoint(self.vm.polling_page.addr());
        self.masm.epilog();

        self.masm.bind_label(lbl_exception);
        self.masm.throw(REG_TMP1, Position::new(1, 1));
        self.masm.nop();

        let desc = match self.fct.desc {
            InternalFctDescriptor::NativeThunk(fid) => JitDescriptor::NativeThunk(fid),
            InternalFctDescriptor::AllocThunk => JitDescriptor::AllocThunk,
            InternalFctDescriptor::VerifyThunk => JitDescriptor::VerifyThunk,
            InternalFctDescriptor::TrapThunk => JitDescriptor::TrapThunk,
        };

        self.masm.jit(self.vm, framesize, desc, self.fct.throws)
    }
}

fn save_params(masm: &mut MacroAssembler, args: &[BuiltinType], offset_args: i32) {
    let mut reg_idx = 0;
    let mut freg_idx = 0;
    let mut idx = 0;

    for &ty in args {
        let mode = ty.mode();
        let is_float = mode.is_float();
        let offset = offset_args + idx as i32 * 8;

        if is_float && freg_idx < FREG_PARAMS.len() {
            let freg = FREG_PARAMS[freg_idx].into();
            masm.store_mem(mode, Mem::Base(REG_SP, offset), freg);
            freg_idx += 1;
        } else if !is_float && reg_idx < REG_PARAMS.len() {
            let reg = REG_PARAMS[reg_idx].into();
            masm.store_mem(mode, Mem::Base(REG_SP, offset), reg);
            reg_idx += 1;
        } else {
            panic!("parameter saved on stack");
        }

        idx += 1;
    }
}

fn restore_params(masm: &mut MacroAssembler, args: &[BuiltinType], offset_args: i32) {
    let mut reg_idx = 0;
    let mut freg_idx = 0;
    let mut idx = 0;

    for &ty in args {
        let mode = ty.mode();
        let is_float = mode.is_float();
        let offset = offset_args + idx as i32 * 8;

        if is_float && freg_idx < FREG_PARAMS.len() {
            let freg = FREG_PARAMS[freg_idx].into();
            masm.load_mem(mode, freg, Mem::Base(REG_SP, offset));
            freg_idx += 1;
        } else if !is_float && reg_idx < REG_PARAMS.len() {
            let reg = REG_PARAMS[reg_idx].into();
            masm.load_mem(mode, reg, Mem::Base(REG_SP, offset));
            reg_idx += 1;
        } else {
            panic!("parameter saved on stack");
        }

        idx += 1;
    }
}

pub fn start_native_call() {
    THREAD.with(|thread| {
        thread.borrow().handles.push_border();
    });
}

pub fn finish_native_call() {
    THREAD.with(|thread| {
        thread.borrow().handles.pop_border();
    });
}
<commit_msg>dora_native: remove saven/restoring parameters<commit_after>use std::collections::hash_map::HashMap;
use std::mem::size_of;

use dora_parser::lexer::position::Position;

use crate::baseline::fct::{JitBaselineFct, JitDescriptor, JitFct, JitFctId};
use crate::baseline::map::CodeDescriptor;
use crate::cpu::{Mem, FREG_PARAMS, REG_FP, REG_PARAMS, REG_SP, REG_THREAD, REG_TMP1};
use crate::exception::DoraToNativeInfo;
use crate::gc::Address;
use crate::masm::MacroAssembler;
use crate::mem;
use crate::threads::{ThreadLocalData, THREAD};
use crate::ty::{BuiltinType, MachineMode};
use crate::vm::FctId;
use crate::vm::VM;

pub struct NativeThunks {
    map: HashMap<Address, JitFctId>,
}

impl NativeThunks {
    pub fn new() -> NativeThunks {
        NativeThunks {
            map: HashMap::new(),
        }
    }

    pub fn find_fct(&self, ptr: Address) -> Option<JitFctId> {
        self.map.get(&ptr).map(|&jit_fct_id| jit_fct_id)
    }

    pub fn insert_fct(&mut self, ptr: Address, fct: JitFctId) {
        self.map.entry(ptr).or_insert(fct);
    }
}

#[derive(Clone)]
pub enum InternalFctDescriptor {
    NativeThunk(FctId),
    AllocThunk,
    VerifyThunk,
    TrapThunk,
}

pub struct InternalFct<'a> {
    pub ptr: Address,
    pub args: &'a [BuiltinType],
    pub return_type: BuiltinType,
    pub throws: bool,
    pub desc: InternalFctDescriptor,
}

pub fn generate<'a, 'ast: 'a>(vm: &'a VM<'ast>, fct: InternalFct, dbg: bool) -> JitFctId {
    let fct_desc = fct.desc.clone();

    let ngen = NativeGen {
        vm,
        masm: MacroAssembler::new(),
        fct,
        dbg,
    };

    let jit_fct = ngen.generate();
    let jit_start = jit_fct.ptr_start();
    let jit_end = jit_fct.ptr_end();
    let jit_fct_id: JitFctId = vm.jit_fcts.push(JitFct::Base(jit_fct)).into();

    let code_desc = match fct_desc {
        InternalFctDescriptor::NativeThunk(_) => CodeDescriptor::NativeThunk(jit_fct_id),
        InternalFctDescriptor::TrapThunk => CodeDescriptor::TrapThunk,
        InternalFctDescriptor::VerifyThunk => CodeDescriptor::VerifyThunk,
        InternalFctDescriptor::AllocThunk => CodeDescriptor::AllocThunk,
    };

    vm.insert_code_map(jit_start, jit_end, code_desc);

    jit_fct_id
}

struct NativeGen<'a, 'ast: 'a> {
    vm: &'a VM<'ast>,
    masm: MacroAssembler,

    fct: InternalFct<'a>,
    dbg: bool,
}

impl<'a, 'ast> NativeGen<'a, 'ast>
where
    'ast: 'a,
{
    pub fn generate(mut self) -> JitBaselineFct {
        let save_return = self.fct.return_type != BuiltinType::Unit;
        let args = self.fct.args.len();

        let dtn_size = size_of::<DoraToNativeInfo>() as i32;

        let offset_dtn = 0;
        let offset_return = dtn_size;
        let offset_args = offset_return + if save_return { mem::ptr_width() } else { 0 };
        let framesize = mem::align_i32(offset_args + args as i32 * mem::ptr_width(), 16);

        // `start_native_call` assumes that offset_dtn is on top of current stack frame.

        if self.dbg {
            self.masm.debug();
        }

        self.masm.prolog_size(framesize);

        self.masm.load_mem(
            MachineMode::Ptr,
            REG_TMP1.into(),
            Mem::Base(REG_THREAD, ThreadLocalData::dtn_offset()),
        );

        self.masm.store_mem(
            MachineMode::Ptr,
            Mem::Base(REG_SP, offset_dtn + DoraToNativeInfo::last_offset()),
            REG_TMP1.into(),
        );

        self.masm.store_mem(
            MachineMode::Ptr,
            Mem::Base(REG_SP, offset_dtn + DoraToNativeInfo::fp_offset()),
            REG_FP.into(),
        );

        self.masm.copy_pc(REG_TMP1);

        self.masm.store_mem(
            MachineMode::Ptr,
            Mem::Base(REG_SP, offset_dtn + DoraToNativeInfo::pc_offset()),
            REG_TMP1.into(),
        );

        self.masm.store_mem(
            MachineMode::Ptr,
            Mem::Base(REG_THREAD, ThreadLocalData::dtn_offset()),
            REG_SP.into(),
        );

        self.masm.raw_call(self.fct.ptr.to_ptr());

        self.masm.load_mem(
            MachineMode::Ptr,
            REG_TMP1.into(),
            Mem::Base(REG_SP, offset_dtn + DoraToNativeInfo::last_offset()),
        );

        self.masm.store_mem(
            MachineMode::Ptr,
            Mem::Base(REG_THREAD, ThreadLocalData::dtn_offset()),
            REG_TMP1.into(),
        );

        self.masm.load_mem(
            MachineMode::Ptr,
            REG_TMP1.into(),
            Mem::Base(REG_THREAD, ThreadLocalData::exception_object_offset()),
        );

        let lbl_exception = self.masm.test_if_not_nil(REG_TMP1);

        self.masm.safepoint(self.vm.polling_page.addr());
        self.masm.epilog();

        self.masm.bind_label(lbl_exception);
        self.masm.throw(REG_TMP1, Position::new(1, 1));
        self.masm.nop();

        let desc = match self.fct.desc {
            InternalFctDescriptor::NativeThunk(fid) => JitDescriptor::NativeThunk(fid),
            InternalFctDescriptor::AllocThunk => JitDescriptor::AllocThunk,
            InternalFctDescriptor::VerifyThunk => JitDescriptor::VerifyThunk,
            InternalFctDescriptor::TrapThunk => JitDescriptor::TrapThunk,
        };

        self.masm.jit(self.vm, framesize, desc, self.fct.throws)
    }
}

fn save_params(masm: &mut MacroAssembler, args: &[BuiltinType], offset_args: i32) {
    let mut reg_idx = 0;
    let mut freg_idx = 0;
    let mut idx = 0;

    for &ty in args {
        let mode = ty.mode();
        let is_float = mode.is_float();
        let offset = offset_args + idx as i32 * 8;

        if is_float && freg_idx < FREG_PARAMS.len() {
            let freg = FREG_PARAMS[freg_idx].into();
            masm.store_mem(mode, Mem::Base(REG_SP, offset), freg);
            freg_idx += 1;
        } else if !is_float && reg_idx < REG_PARAMS.len() {
            let reg = REG_PARAMS[reg_idx].into();
            masm.store_mem(mode, Mem::Base(REG_SP, offset), reg);
            reg_idx += 1;
        } else {
            panic!("parameter saved on stack");
        }

        idx += 1;
    }
}

fn restore_params(masm: &mut MacroAssembler, args: &[BuiltinType], offset_args: i32) {
    let mut reg_idx = 0;
    let mut freg_idx = 0;
    let mut idx = 0;

    for &ty in args {
        let mode = ty.mode();
        let is_float = mode.is_float();
        let offset = offset_args + idx as i32 * 8;

        if is_float && freg_idx < FREG_PARAMS.len() {
            let freg = FREG_PARAMS[freg_idx].into();
            masm.load_mem(mode, freg, Mem::Base(REG_SP, offset));
            freg_idx += 1;
        } else if !is_float && reg_idx < REG_PARAMS.len() {
            let reg = REG_PARAMS[reg_idx].into();
            masm.load_mem(mode, reg, Mem::Base(REG_SP, offset));
            reg_idx += 1;
        } else {
            panic!("parameter saved on stack");
        }

        idx += 1;
    }
}

pub fn start_native_call() {
    THREAD.with(|thread| {
        thread.borrow().handles.push_border();
    });
}

pub fn finish_native_call() {
    THREAD.with(|thread| {
        thread.borrow().handles.pop_border();
    });
}
<|endoftext|>


<commit_before>#![no_main]
use cfb::CompoundFile;
use libfuzzer_sys::fuzz_target;
use std::io::{Cursor, Read};

fuzz_target!(|data: &[u8]| {
    let cursor = Cursor::new(data);
    let mut cfb = match CompoundFile::open(cursor) {
        Ok(cfb) => cfb,
        Err(_) => return,
    };
    let stream_paths = cfb
        .walk()
        .filter(|e| e.is_stream())
        .map(|e| e.path().to_path_buf())
        .collect::<Vec<_>>();

    let data = stream_paths
        .into_iter()
        .map(|s| {
            let mut data = Vec::new();
            cfb.open_stream(&s)?.read_to_end(&mut data)?;
            Ok(data)
        })
        .collect::<Result<Vec<_>, std::io::Error>>();
});
<commit_msg>prevented early-exit on harness<commit_after>#![no_main]
use cfb::CompoundFile;
use libfuzzer_sys::fuzz_target;
use std::io::{Cursor, Read};

fuzz_target!(|data: &[u8]| {
    let cursor = Cursor::new(data);
    let mut cfb = match CompoundFile::open(cursor) {
        Ok(cfb) => cfb,
        Err(_) => return,
    };
    let stream_paths = cfb
        .walk()
        .filter(|e| e.is_stream())
        .map(|e| e.path().to_path_buf())
        .collect::<Vec<_>>();

    let _unused = stream_paths
        .into_iter()
        .map(|s| -> Result<Vec<u8>, std::io::Error> {
            let mut data = Vec::new();
            cfb.open_stream(&s)?.read_to_end(&mut data)?;
            Ok(data)
        })
        .collect::<Vec<_>>();
});
<|endoftext|>


<commit_before>use hashing::canonical_hash;

const SSZ_CHUNK_SIZE: usize = 128;
const HASHSIZE: usize = 32;

pub trait TreeHash {
    fn hash_tree_root(&self) -> Vec<u8>;
}

/// Returns a 32 byte hash of 'list' - a vector of byte vectors.
/// Note that this will consume 'list'.
pub fn merkle_hash(list: &mut Vec<Vec<u8>>) -> Vec<u8> {
    // flatten list
    let (mut chunk_size, mut chunkz) = list_to_blob(list);

    // get data_len as bytes. It will hashed will the merkle root
    let datalen = list.len().to_le_bytes();

    // Tree-hash
    while chunkz.len() > HASHSIZE {
        let mut new_chunkz: Vec<u8> = Vec::new();

        for two_chunks in chunkz.chunks(chunk_size * 2) {
            if two_chunks.len() == chunk_size {
                // Odd number of chunks
                let mut c = two_chunks.to_vec();
                c.append(&mut vec![0; SSZ_CHUNK_SIZE]);
                new_chunkz.append(&mut hash(&c));
            } else {
                // Hash two chuncks together
                new_chunkz.append(&mut hash(two_chunks));
            }
            chunk_size = HASHSIZE;
        }
        chunkz = new_chunkz;
    }

    chunkz.append(&mut datalen.to_vec());
    hash(&chunkz)
}

fn list_to_blob(list: &mut Vec<Vec<u8>>) -> (usize, Vec<u8>) {
    let chunk_size = if list.is_empty() {
        SSZ_CHUNK_SIZE
    } else if list[0].len() < SSZ_CHUNK_SIZE {
        let items_per_chunk = SSZ_CHUNK_SIZE / list[0].len();
        items_per_chunk * list[0].len()
    } else {
        list[0].len()
    };

    let mut data = Vec::new();
    if list.is_empty() {
        // handle and empty list
        data.append(&mut vec![0; SSZ_CHUNK_SIZE]);
    } else {
        // just create a blob here; we'll divide into
        // chunked slices when we merklize
        data.reserve(list[0].len() * list.len());
        for item in list.iter_mut() {
            data.append(item);
        }
    }
    (chunk_size, data)
}

pub fn hash(data: &[u8]) -> Vec<u8> {
    canonical_hash(data)
}

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

    #[test]
    fn test_merkle_hash() {
        let data1 = vec![1; 100];
        let data2 = vec![2; 100];
        let data3 = vec![3; 100];
        let mut list = vec![data1, data2, data3];
        let result = merkle_hash(&mut list);

        //note: should test againt a known test hash value
        assert_eq!(HASHSIZE, result.len());
    }
}
<commit_msg>Minor modification to merkle hashing<commit_after>use hashing::canonical_hash;

const SSZ_CHUNK_SIZE: usize = 128;
const HASHSIZE: usize = 32;

pub trait TreeHash {
    fn hash_tree_root(&self) -> Vec<u8>;
}

/// Returns a 32 byte hash of 'list' - a vector of byte vectors.
/// Note that this will consume 'list'.
pub fn merkle_hash(list: &mut Vec<Vec<u8>>) -> Vec<u8> {
    // flatten list
    let (mut chunk_size, mut chunkz) = list_to_blob(list);

    // get data_len as bytes. It will hashed will the merkle root
    let datalen = list.len().to_le_bytes();

    // Tree-hash
    while chunkz.len() > HASHSIZE {
        let mut new_chunkz: Vec<u8> = Vec::new();

        for two_chunks in chunkz.chunks(chunk_size * 2) {
            if two_chunks.len() == chunk_size {
                // Odd number of chunks
                let mut c = two_chunks.to_vec();
                c.append(&mut vec![0; SSZ_CHUNK_SIZE]);
                new_chunkz.append(&mut hash(&c));
            } else {
                // Hash two chuncks together
                new_chunkz.append(&mut hash(two_chunks));
            }
        }

        chunk_size = HASHSIZE;
        chunkz = new_chunkz;
    }

    chunkz.append(&mut datalen.to_vec());
    hash(&chunkz)
}

fn list_to_blob(list: &mut Vec<Vec<u8>>) -> (usize, Vec<u8>) {
    let chunk_size = if list.is_empty() {
        SSZ_CHUNK_SIZE
    } else if list[0].len() < SSZ_CHUNK_SIZE {
        let items_per_chunk = SSZ_CHUNK_SIZE / list[0].len();
        items_per_chunk * list[0].len()
    } else {
        list[0].len()
    };

    let mut data = Vec::new();
    if list.is_empty() {
        // handle and empty list
        data.append(&mut vec![0; SSZ_CHUNK_SIZE]);
    } else {
        // just create a blob here; we'll divide into
        // chunked slices when we merklize
        data.reserve(list[0].len() * list.len());
        for item in list.iter_mut() {
            data.append(item);
        }
    }
    (chunk_size, data)
}

pub fn hash(data: &[u8]) -> Vec<u8> {
    canonical_hash(data)
}

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

    #[test]
    fn test_merkle_hash() {
        let data1 = vec![1; 100];
        let data2 = vec![2; 100];
        let data3 = vec![3; 100];
        let mut list = vec![data1, data2, data3];
        let result = merkle_hash(&mut list);

        //note: should test againt a known test hash value
        assert_eq!(HASHSIZE, result.len());
    }
}
<|endoftext|>


<commit_before>use jansson_sys::json_t;
use std::os::raw::{c_char, c_int, c_void};

#[repr(C)]
#[derive(Debug)]
pub struct janus_callbacks {
    pub push_event: extern "C" fn(
        handle: *mut janus_plugin_session,
        plugin: *mut janus_plugin,
        transaction: *const c_char,
        message: *mut json_t,
        jsep: *mut json_t,
    ) -> c_int,
    pub relay_rtp: extern "C" fn(handle: *mut janus_plugin_session, video: c_int, buf: *mut c_char, len: c_int),
    pub relay_rtcp: extern "C" fn(handle: *mut janus_plugin_session, video: c_int, buf: *mut c_char, len: c_int),
    pub relay_data: extern "C" fn(handle: *mut janus_plugin_session, buf: *mut c_char, len: c_int),
    pub close_pc: extern "C" fn(handle: *mut janus_plugin_session),
    pub end_session: extern "C" fn(handle: *mut janus_plugin_session),
    pub events_is_enabled: extern "C" fn() -> c_int,
    pub notify_event: extern "C" fn(plugin: *mut janus_plugin, handle: *mut janus_plugin_session, event: *mut json_t),
}

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum janus_plugin_result_type {
    JANUS_PLUGIN_ERROR = -1,
    JANUS_PLUGIN_OK = 0,
    JANUS_PLUGIN_OK_WAIT = 1,
}

#[cfg(not(feature="refcount"))]
#[repr(C)]
#[derive(Debug)]
pub struct janus_plugin_session {
    pub gateway_handle: *mut c_void,
    pub plugin_handle: *mut c_void,
    pub stopped_bitfield: u8, // todo: clean this up
    pub __padding: [u8; 7usize],
}

#[cfg(feature="refcount")]
#[repr(C)]
#[derive(Debug)]
pub struct janus_plugin_session {
    pub gateway_handle: *mut c_void,
    pub plugin_handle: *mut c_void,
    pub stopped: c_int,
    pub ref_: ::janus_refcount,
}

#[repr(C)]
#[derive(Debug)]
pub struct janus_plugin_result {
    pub type_: janus_plugin_result_type,
    pub text: *const c_char,
    pub content: *mut json_t,
}

#[repr(C)]
#[derive(Debug)]
pub struct janus_plugin {
    pub init: unsafe extern "C" fn(callback: *mut janus_callbacks, config_path: *const c_char) -> c_int,
    pub destroy: unsafe extern "C" fn(),
    pub get_api_compatibility: unsafe extern "C" fn() -> c_int,
    pub get_version: unsafe extern "C" fn() -> c_int,
    pub get_version_string: unsafe extern "C" fn() -> *const c_char,
    pub get_description: unsafe extern "C" fn() -> *const c_char,
    pub get_name: unsafe extern "C" fn() -> *const c_char,
    pub get_author: unsafe extern "C" fn() -> *const c_char,
    pub get_package: unsafe extern "C" fn() -> *const c_char,
    pub create_session: unsafe extern "C" fn(handle: *mut janus_plugin_session, error: *mut c_int),
    pub handle_message: unsafe extern "C" fn(
        handle: *mut janus_plugin_session,
        transaction: *mut c_char,
        message: *mut json_t,
        jsep: *mut json_t,
    ) -> *mut janus_plugin_result,
    pub setup_media: unsafe extern "C" fn(handle: *mut janus_plugin_session),
    pub incoming_rtp: unsafe extern "C" fn(handle: *mut janus_plugin_session, video: c_int, buf: *mut c_char, len: c_int),
    pub incoming_rtcp: unsafe extern "C" fn(handle: *mut janus_plugin_session, video: c_int, buf: *mut c_char, len: c_int),
    pub incoming_data: unsafe extern "C" fn(handle: *mut janus_plugin_session, buf: *mut c_char, len: c_int),
    pub slow_link: unsafe extern "C" fn(handle: *mut janus_plugin_session, uplink: c_int, video: c_int),
    pub hangup_media: unsafe extern "C" fn(handle: *mut janus_plugin_session),
    pub destroy_session: unsafe extern "C" fn(handle: *mut janus_plugin_session, error: *mut c_int),
    pub query_session: unsafe extern "C" fn(handle: *mut janus_plugin_session) -> *mut json_t,
}

extern "C" {
    pub fn janus_plugin_result_new(type_: janus_plugin_result_type, text: *const c_char, content: *mut json_t) -> *mut janus_plugin_result;
    pub fn janus_plugin_result_destroy(result: *mut janus_plugin_result);
}
<commit_msg>Upgrade to plugin API v12<commit_after>use jansson_sys::json_t;
use std::os::raw::{c_char, c_int, c_void};

#[repr(C)]
#[derive(Debug)]
pub struct janus_callbacks {
    pub push_event: extern "C" fn(
        handle: *mut janus_plugin_session,
        plugin: *mut janus_plugin,
        transaction: *const c_char,
        message: *mut json_t,
        jsep: *mut json_t,
    ) -> c_int,
    pub relay_rtp: extern "C" fn(handle: *mut janus_plugin_session, video: c_int, buf: *mut c_char, len: c_int),
    pub relay_rtcp: extern "C" fn(handle: *mut janus_plugin_session, video: c_int, buf: *mut c_char, len: c_int),
    pub relay_data: extern "C" fn(handle: *mut janus_plugin_session, label: *mut c_char, buf: *mut c_char, len: c_int),
    pub close_pc: extern "C" fn(handle: *mut janus_plugin_session),
    pub end_session: extern "C" fn(handle: *mut janus_plugin_session),
    pub events_is_enabled: extern "C" fn() -> c_int,
    pub notify_event: extern "C" fn(plugin: *mut janus_plugin, handle: *mut janus_plugin_session, event: *mut json_t),
}

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum janus_plugin_result_type {
    JANUS_PLUGIN_ERROR = -1,
    JANUS_PLUGIN_OK = 0,
    JANUS_PLUGIN_OK_WAIT = 1,
}

#[cfg(not(feature="refcount"))]
#[repr(C)]
#[derive(Debug)]
pub struct janus_plugin_session {
    pub gateway_handle: *mut c_void,
    pub plugin_handle: *mut c_void,
    pub stopped_bitfield: u8, // todo: clean this up
    pub __padding: [u8; 7usize],
}

#[cfg(feature="refcount")]
#[repr(C)]
#[derive(Debug)]
pub struct janus_plugin_session {
    pub gateway_handle: *mut c_void,
    pub plugin_handle: *mut c_void,
    pub stopped: c_int,
    pub ref_: ::janus_refcount,
}

#[repr(C)]
#[derive(Debug)]
pub struct janus_plugin_result {
    pub type_: janus_plugin_result_type,
    pub text: *const c_char,
    pub content: *mut json_t,
}

#[repr(C)]
#[derive(Debug)]
pub struct janus_plugin {
    pub init: unsafe extern "C" fn(callback: *mut janus_callbacks, config_path: *const c_char) -> c_int,
    pub destroy: unsafe extern "C" fn(),
    pub get_api_compatibility: unsafe extern "C" fn() -> c_int,
    pub get_version: unsafe extern "C" fn() -> c_int,
    pub get_version_string: unsafe extern "C" fn() -> *const c_char,
    pub get_description: unsafe extern "C" fn() -> *const c_char,
    pub get_name: unsafe extern "C" fn() -> *const c_char,
    pub get_author: unsafe extern "C" fn() -> *const c_char,
    pub get_package: unsafe extern "C" fn() -> *const c_char,
    pub create_session: unsafe extern "C" fn(handle: *mut janus_plugin_session, error: *mut c_int),
    pub handle_message: unsafe extern "C" fn(
        handle: *mut janus_plugin_session,
        transaction: *mut c_char,
        message: *mut json_t,
        jsep: *mut json_t,
    ) -> *mut janus_plugin_result,
    pub setup_media: unsafe extern "C" fn(handle: *mut janus_plugin_session),
    pub incoming_rtp: unsafe extern "C" fn(handle: *mut janus_plugin_session, video: c_int, buf: *mut c_char, len: c_int),
    pub incoming_rtcp: unsafe extern "C" fn(handle: *mut janus_plugin_session, video: c_int, buf: *mut c_char, len: c_int),
    pub incoming_data: unsafe extern "C" fn(handle: *mut janus_plugin_session, label: *mut c_char, buf: *mut c_char, len: c_int),
    pub slow_link: unsafe extern "C" fn(handle: *mut janus_plugin_session, uplink: c_int, video: c_int),
    pub hangup_media: unsafe extern "C" fn(handle: *mut janus_plugin_session),
    pub destroy_session: unsafe extern "C" fn(handle: *mut janus_plugin_session, error: *mut c_int),
    pub query_session: unsafe extern "C" fn(handle: *mut janus_plugin_session) -> *mut json_t,
}

extern "C" {
    pub fn janus_plugin_result_new(type_: janus_plugin_result_type, text: *const c_char, content: *mut json_t) -> *mut janus_plugin_result;
    pub fn janus_plugin_result_destroy(result: *mut janus_plugin_result);
}
<|endoftext|>


<commit_before>use std::ops::{Deref, DerefMut};

use na::RealField;

use crate::joint::Joint;
use crate::math::{Inertia, Isometry, Point, Vector, Velocity};
use crate::object::BodyPart;

/// One link of a multibody.
pub struct MultibodyLink<N: RealField> {
    pub(crate) name: String,
    // FIXME: make all those private.
    pub(crate) internal_id: usize,
    pub(crate) assembly_id: usize,
    pub(crate) impulse_id: usize,
    pub(crate) is_leaf: bool,

    // XXX: rename to "joint".
    // (And rename the full-coordinates joint constraints JointConstraint).
    pub(crate) parent_internal_id: usize,
    pub(crate) dof: Box<dyn Joint<N>>,
    pub(crate) parent_shift: Vector<N>,
    pub(crate) body_shift: Vector<N>,

    // Change at each time step.
    pub(crate) parent_to_world: Isometry<N>,
    pub(crate) local_to_world: Isometry<N>,
    pub(crate) local_to_parent: Isometry<N>,
    // FIXME: put this on a workspace buffer instead ?
    pub(crate) velocity_dot_wrt_joint: Velocity<N>,
    // J' q' in world space. FIXME: what could be a better name ?
    pub(crate) velocity_wrt_joint: Velocity<N>,
    // J  q' in world space.
    pub(crate) velocity: Velocity<N>,
    pub(crate) inertia: Inertia<N>,
    pub(crate) com: Point<N>,

    pub(crate) local_inertia: Inertia<N>,
    pub(crate) local_com: Point<N>,
    // TODO: User-defined data
    // user_data:       T
}

impl<N: RealField> MultibodyLink<N> {
    /// Creates a new multibody link.
    pub fn new(
        internal_id: usize,
        assembly_id: usize,
        impulse_id: usize,
        parent_internal_id: usize,
        dof: Box<dyn Joint<N>>,
        parent_shift: Vector<N>,
        body_shift: Vector<N>,
        parent_to_world: Isometry<N>,
        local_to_world: Isometry<N>,
        local_to_parent: Isometry<N>,
        local_inertia: Inertia<N>,
        local_com: Point<N>,
    ) -> Self {
        let is_leaf = true;
        let velocity = Velocity::zero();
        let velocity_dot_wrt_joint = Velocity::zero();
        let velocity_wrt_joint = Velocity::zero();
        let inertia = local_inertia.transformed(&local_to_world);
        let com = local_to_world * local_com;

        MultibodyLink {
            name: String::new(),
            internal_id,
            assembly_id,
            impulse_id,
            is_leaf,
            parent_internal_id,
            dof,
            parent_shift,
            body_shift,
            parent_to_world,
            local_to_world,
            local_to_parent,
            velocity_dot_wrt_joint,
            velocity_wrt_joint,
            velocity,
            local_inertia,
            local_com,
            inertia,
            com,
        }
    }

    /// Checks if this link is the root of the multibody.
    #[inline]
    pub fn is_root(&self) -> bool {
        self.internal_id == 0
    }

    /// Reference to the joint attaching this link to its parent.
    #[inline]
    pub fn joint(&self) -> &dyn Joint<N> {
        &*self.dof
    }

    /// Mutable reference to the joint attaching this link to its parent.
    #[inline]
    pub fn joint_mut(&mut self) -> &mut dyn Joint<N> {
        &mut *self.dof
    }

    /// The shift between this link's parent and this link joint origin.
    #[inline]
    pub fn parent_shift(&self) -> &Vector<N> {
        &self.parent_shift
    }

    /// The shift between this link's joint origin and this link origin.
    #[inline]
    pub fn body_shift(&self) -> &Vector<N> {
        &self.body_shift
    }

    /// This link's name.
    #[inline]
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Sets this link's name.
    #[inline]
    pub fn set_name(&mut self, name: String) {
        self.name = name
    }

    /// The handle of this multibody link.
    #[inline]
    pub fn link_id(&self) -> usize {
        self.internal_id
    }
}

impl<N: RealField> BodyPart<N> for MultibodyLink<N> {
    #[inline]
    fn is_ground(&self) -> bool {
        false
    }

    #[inline]
    fn center_of_mass(&self) -> Point<N> {
        self.com
    }

    #[inline]
    fn local_center_of_mass(&self) -> Point<N> {
        self.local_com
    }

    #[inline]
    fn velocity(&self) -> Velocity<N> {
        self.velocity
    }

    #[inline]
    fn position(&self) -> Isometry<N> {
        self.local_to_world
    }

    #[inline]
    fn local_inertia(&self) -> Inertia<N> {
        self.local_inertia
    }

    #[inline]
    fn inertia(&self) -> Inertia<N> {
        self.inertia
    }
}

// FIXME: keep this even if we already have the Index2 traits?
pub(crate) struct MultibodyLinkVec<N: RealField>(pub Vec<MultibodyLink<N>>);

impl<N: RealField> MultibodyLinkVec<N> {
    // #[inline]
    // pub fn get_with_parent(&self, i: usize) -> (&MultibodyLink<N>, &MultibodyLink<N>) {
    //     assert!(
    //         i != 0,
    //         "The parent of this body is not part of the same multibody."
    //     );
    //     let rb = &self[i];
    //     let parent_rb = &self[rb.parent.internal_id];

    //     (rb, parent_rb)
    // }
    #[inline]
    pub fn get_mut_with_parent(&mut self, i: usize) -> (&mut MultibodyLink<N>, &MultibodyLink<N>) {
        let parent_id = self[i].parent_internal_id;

        assert!(
            parent_id != i,
            "Internal error: circular rigid body dependency."
        );
        assert!(parent_id < self.len(), "Invalid parent index.");

        unsafe {
            let rb = &mut *(self.get_unchecked_mut(i) as *mut _);
            let parent_rb = &*(self.get_unchecked(parent_id) as *const _);
            (rb, parent_rb)
        }
    }
}

impl<N: RealField> Deref for MultibodyLinkVec<N> {
    type Target = Vec<MultibodyLink<N>>;

    #[inline]
    fn deref(&self) -> &Vec<MultibodyLink<N>> {
        let MultibodyLinkVec(ref me) = *self;
        me
    }
}

impl<N: RealField> DerefMut for MultibodyLinkVec<N> {
    #[inline]
    fn deref_mut(&mut self) -> &mut Vec<MultibodyLink<N>> {
        let MultibodyLinkVec(ref mut me) = *self;
        me
    }
}
<commit_msg>Expose ability to get `MultibodyLink` parent ID<commit_after>use std::ops::{Deref, DerefMut};

use na::RealField;

use crate::joint::Joint;
use crate::math::{Inertia, Isometry, Point, Vector, Velocity};
use crate::object::BodyPart;

/// One link of a multibody.
pub struct MultibodyLink<N: RealField> {
    pub(crate) name: String,
    // FIXME: make all those private.
    pub(crate) internal_id: usize,
    pub(crate) assembly_id: usize,
    pub(crate) impulse_id: usize,
    pub(crate) is_leaf: bool,

    // XXX: rename to "joint".
    // (And rename the full-coordinates joint constraints JointConstraint).
    pub(crate) parent_internal_id: usize,
    pub(crate) dof: Box<dyn Joint<N>>,
    pub(crate) parent_shift: Vector<N>,
    pub(crate) body_shift: Vector<N>,

    // Change at each time step.
    pub(crate) parent_to_world: Isometry<N>,
    pub(crate) local_to_world: Isometry<N>,
    pub(crate) local_to_parent: Isometry<N>,
    // FIXME: put this on a workspace buffer instead ?
    pub(crate) velocity_dot_wrt_joint: Velocity<N>,
    // J' q' in world space. FIXME: what could be a better name ?
    pub(crate) velocity_wrt_joint: Velocity<N>,
    // J  q' in world space.
    pub(crate) velocity: Velocity<N>,
    pub(crate) inertia: Inertia<N>,
    pub(crate) com: Point<N>,

    pub(crate) local_inertia: Inertia<N>,
    pub(crate) local_com: Point<N>,
    // TODO: User-defined data
    // user_data:       T
}

impl<N: RealField> MultibodyLink<N> {
    /// Creates a new multibody link.
    pub fn new(
        internal_id: usize,
        assembly_id: usize,
        impulse_id: usize,
        parent_internal_id: usize,
        dof: Box<dyn Joint<N>>,
        parent_shift: Vector<N>,
        body_shift: Vector<N>,
        parent_to_world: Isometry<N>,
        local_to_world: Isometry<N>,
        local_to_parent: Isometry<N>,
        local_inertia: Inertia<N>,
        local_com: Point<N>,
    ) -> Self {
        let is_leaf = true;
        let velocity = Velocity::zero();
        let velocity_dot_wrt_joint = Velocity::zero();
        let velocity_wrt_joint = Velocity::zero();
        let inertia = local_inertia.transformed(&local_to_world);
        let com = local_to_world * local_com;

        MultibodyLink {
            name: String::new(),
            internal_id,
            assembly_id,
            impulse_id,
            is_leaf,
            parent_internal_id,
            dof,
            parent_shift,
            body_shift,
            parent_to_world,
            local_to_world,
            local_to_parent,
            velocity_dot_wrt_joint,
            velocity_wrt_joint,
            velocity,
            local_inertia,
            local_com,
            inertia,
            com,
        }
    }

    /// Checks if this link is the root of the multibody.
    #[inline]
    pub fn is_root(&self) -> bool {
        self.internal_id == 0
    }

    /// Reference to the joint attaching this link to its parent.
    #[inline]
    pub fn joint(&self) -> &dyn Joint<N> {
        &*self.dof
    }

    /// Mutable reference to the joint attaching this link to its parent.
    #[inline]
    pub fn joint_mut(&mut self) -> &mut dyn Joint<N> {
        &mut *self.dof
    }

    /// The shift between this link's parent and this link joint origin.
    #[inline]
    pub fn parent_shift(&self) -> &Vector<N> {
        &self.parent_shift
    }

    /// The shift between this link's joint origin and this link origin.
    #[inline]
    pub fn body_shift(&self) -> &Vector<N> {
        &self.body_shift
    }

    /// This link's name.
    #[inline]
    pub fn name(&self) -> &str {
        &self.name
    }

    /// Sets this link's name.
    #[inline]
    pub fn set_name(&mut self, name: String) {
        self.name = name
    }

    /// The handle of this multibody link.
    #[inline]
    pub fn link_id(&self) -> usize {
        self.internal_id
    }

    /// The handle of the parent link.
    #[inline]
    pub fn parent_id(&self) -> Option<usize> {
        if self.internal_id != 0 {
            Some(self.parent_internal_id)
        } else {
            None
        }
    }
}

impl<N: RealField> BodyPart<N> for MultibodyLink<N> {
    #[inline]
    fn is_ground(&self) -> bool {
        false
    }

    #[inline]
    fn center_of_mass(&self) -> Point<N> {
        self.com
    }

    #[inline]
    fn local_center_of_mass(&self) -> Point<N> {
        self.local_com
    }

    #[inline]
    fn velocity(&self) -> Velocity<N> {
        self.velocity
    }

    #[inline]
    fn position(&self) -> Isometry<N> {
        self.local_to_world
    }

    #[inline]
    fn local_inertia(&self) -> Inertia<N> {
        self.local_inertia
    }

    #[inline]
    fn inertia(&self) -> Inertia<N> {
        self.inertia
    }
}

// FIXME: keep this even if we already have the Index2 traits?
pub(crate) struct MultibodyLinkVec<N: RealField>(pub Vec<MultibodyLink<N>>);

impl<N: RealField> MultibodyLinkVec<N> {
    // #[inline]
    // pub fn get_with_parent(&self, i: usize) -> (&MultibodyLink<N>, &MultibodyLink<N>) {
    //     assert!(
    //         i != 0,
    //         "The parent of this body is not part of the same multibody."
    //     );
    //     let rb = &self[i];
    //     let parent_rb = &self[rb.parent.internal_id];

    //     (rb, parent_rb)
    // }
    #[inline]
    pub fn get_mut_with_parent(&mut self, i: usize) -> (&mut MultibodyLink<N>, &MultibodyLink<N>) {
        let parent_id = self[i].parent_internal_id;

        assert!(
            parent_id != i,
            "Internal error: circular rigid body dependency."
        );
        assert!(parent_id < self.len(), "Invalid parent index.");

        unsafe {
            let rb = &mut *(self.get_unchecked_mut(i) as *mut _);
            let parent_rb = &*(self.get_unchecked(parent_id) as *const _);
            (rb, parent_rb)
        }
    }
}

impl<N: RealField> Deref for MultibodyLinkVec<N> {
    type Target = Vec<MultibodyLink<N>>;

    #[inline]
    fn deref(&self) -> &Vec<MultibodyLink<N>> {
        let MultibodyLinkVec(ref me) = *self;
        me
    }
}

impl<N: RealField> DerefMut for MultibodyLinkVec<N> {
    #[inline]
    fn deref_mut(&mut self) -> &mut Vec<MultibodyLink<N>> {
        let MultibodyLinkVec(ref mut me) = *self;
        me
    }
}
<|endoftext|>


<commit_before>use rustc_hash::FxHashMap;
use std::sync::Arc;

use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
use ra_syntax::{
    ast::{self, AstNode},
    AstPtr, SourceFile,
};

use crate::{
    code_model::{Module, ModuleSource},
    db::{AstDatabase, DefDatabase, HirDatabase},
    generics::HasGenericParams,
    ids::LocationCtx,
    resolve::Resolver,
    ty::Ty,
    type_ref::TypeRef,
    Const, Function, HasSource, HirFileId, Source, TraitRef, TypeAlias,
};

#[derive(Debug, Default, PartialEq, Eq)]
pub struct ImplSourceMap {
    map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>,
}

impl ImplSourceMap {
    fn insert(&mut self, impl_id: ImplId, impl_block: &ast::ImplBlock) {
        self.map.insert(impl_id, AstPtr::new(impl_block))
    }

    pub fn get(&self, source: &ModuleSource, impl_id: ImplId) -> ast::ImplBlock {
        let file = match source {
            ModuleSource::SourceFile(file) => file.clone(),
            ModuleSource::Module(m) => m.syntax().ancestors().find_map(SourceFile::cast).unwrap(),
        };

        self.map[impl_id].to_node(file.syntax()).to_owned()
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ImplBlock {
    module: Module,
    impl_id: ImplId,
}

impl HasSource for ImplBlock {
    type Ast = ast::ImplBlock;
    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ImplBlock> {
        let source_map = db.impls_in_module_with_source_map(self.module).1;
        let src = self.module.definition_source(db);
        Source { file_id: src.file_id, ast: source_map.get(&src.ast, self.impl_id) }
    }
}

impl ImplBlock {
    pub(crate) fn containing(
        module_impl_blocks: Arc<ModuleImplBlocks>,
        item: ImplItem,
    ) -> Option<ImplBlock> {
        let impl_id = *module_impl_blocks.impls_by_def.get(&item)?;
        Some(ImplBlock { module: module_impl_blocks.module, impl_id })
    }

    pub(crate) fn from_id(module: Module, impl_id: ImplId) -> ImplBlock {
        ImplBlock { module, impl_id }
    }

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

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

    pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
        db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned()
    }

    pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef {
        db.impls_in_module(self.module).impls[self.impl_id].target_type().clone()
    }

    pub fn target_ty(&self, db: &impl HirDatabase) -> Ty {
        Ty::from_hir(db, &self.resolver(db), &self.target_type(db))
    }

    pub fn target_trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> {
        let target_ty = self.target_ty(db);
        TraitRef::from_hir(db, &self.resolver(db), &self.target_trait(db)?, Some(target_ty))
    }

    pub fn items(&self, db: &impl DefDatabase) -> Vec<ImplItem> {
        db.impls_in_module(self.module).impls[self.impl_id].items().to_vec()
    }

    pub fn is_negative(&self, db: &impl DefDatabase) -> bool {
        db.impls_in_module(self.module).impls[self.impl_id].negative
    }

    pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
        let r = self.module().resolver(db);
        // add generic params, if present
        let p = self.generic_params(db);
        let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
        let r = r.push_impl_block_scope(self.clone());
        r
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImplData {
    target_trait: Option<TypeRef>,
    target_type: TypeRef,
    items: Vec<ImplItem>,
    negative: bool,
}

impl ImplData {
    pub(crate) fn from_ast(
        db: &(impl DefDatabase + AstDatabase),
        file_id: HirFileId,
        module: Module,
        node: &ast::ImplBlock,
    ) -> Self {
        let target_trait = node.target_trait().map(TypeRef::from_ast);
        let target_type = TypeRef::from_ast_opt(node.target_type());
        let ctx = LocationCtx::new(db, module, file_id);
        let negative = node.is_negative();
        let items = if let Some(item_list) = node.item_list() {
            item_list
                .impl_items()
                .map(|item_node| match item_node {
                    ast::ImplItem::FnDef(it) => Function { id: ctx.to_def(&it) }.into(),
                    ast::ImplItem::ConstDef(it) => Const { id: ctx.to_def(&it) }.into(),
                    ast::ImplItem::TypeAliasDef(it) => TypeAlias { id: ctx.to_def(&it) }.into(),
                })
                .collect()
        } else {
            Vec::new()
        };
        ImplData { target_trait, target_type, items, negative }
    }

    pub fn target_trait(&self) -> Option<&TypeRef> {
        self.target_trait.as_ref()
    }

    pub fn target_type(&self) -> &TypeRef {
        &self.target_type
    }

    pub fn items(&self) -> &[ImplItem] {
        &self.items
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
//FIXME: rename to ImplDef?
pub enum ImplItem {
    Method(Function),
    Const(Const),
    TypeAlias(TypeAlias),
    // Existential
}
impl_froms!(ImplItem: Const, TypeAlias);

impl From<Function> for ImplItem {
    fn from(func: Function) -> ImplItem {
        ImplItem::Method(func)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ImplId(pub RawId);
impl_arena_id!(ImplId);

/// The collection of impl blocks is a two-step process: first we collect the
/// blocks per-module; then we build an index of all impl blocks in the crate.
/// This way, we avoid having to do this process for the whole crate whenever
/// a file is changed; as long as the impl blocks in the file don't change,
/// we don't need to do the second step again.
#[derive(Debug, PartialEq, Eq)]
pub struct ModuleImplBlocks {
    pub(crate) module: Module,
    pub(crate) impls: Arena<ImplId, ImplData>,
    impls_by_def: FxHashMap<ImplItem, ImplId>,
}

impl ModuleImplBlocks {
    fn collect(
        db: &(impl DefDatabase + AstDatabase),
        module: Module,
        source_map: &mut ImplSourceMap,
    ) -> Self {
        let mut m = ModuleImplBlocks {
            module,
            impls: Arena::default(),
            impls_by_def: FxHashMap::default(),
        };

        let src = m.module.definition_source(db);
        let node = match &src.ast {
            ModuleSource::SourceFile(node) => node.syntax().clone(),
            ModuleSource::Module(node) => {
                node.item_list().expect("inline module should have item list").syntax().clone()
            }
        };

        for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) {
            let impl_block = ImplData::from_ast(db, src.file_id, m.module, &impl_block_ast);
            let id = m.impls.alloc(impl_block);
            for &impl_item in &m.impls[id].items {
                m.impls_by_def.insert(impl_item, id);
            }

            source_map.insert(id, &impl_block_ast);
        }

        m
    }
}

pub(crate) fn impls_in_module_with_source_map_query(
    db: &(impl DefDatabase + AstDatabase),
    module: Module,
) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
    let mut source_map = ImplSourceMap::default();

    let result = ModuleImplBlocks::collect(db, module, &mut source_map);

    (Arc::new(result), Arc::new(source_map))
}

pub(crate) fn impls_in_module(db: &impl DefDatabase, module: Module) -> Arc<ModuleImplBlocks> {
    db.impls_in_module_with_source_map(module).0
}
<commit_msg>fix panic when fetching generics<commit_after>use rustc_hash::FxHashMap;
use std::sync::Arc;

use ra_arena::{impl_arena_id, map::ArenaMap, Arena, RawId};
use ra_syntax::{
    ast::{self, AstNode},
    AstPtr,
};

use crate::{
    code_model::{Module, ModuleSource},
    db::{AstDatabase, DefDatabase, HirDatabase},
    generics::HasGenericParams,
    ids::LocationCtx,
    resolve::Resolver,
    ty::Ty,
    type_ref::TypeRef,
    Const, Function, HasSource, HirFileId, Source, TraitRef, TypeAlias,
};

#[derive(Debug, Default, PartialEq, Eq)]
pub struct ImplSourceMap {
    map: ArenaMap<ImplId, AstPtr<ast::ImplBlock>>,
}

impl ImplSourceMap {
    fn insert(&mut self, impl_id: ImplId, impl_block: &ast::ImplBlock) {
        self.map.insert(impl_id, AstPtr::new(impl_block))
    }

    pub fn get(&self, source: &ModuleSource, impl_id: ImplId) -> ast::ImplBlock {
        let root = match source {
            ModuleSource::SourceFile(file) => file.syntax().clone(),
            ModuleSource::Module(m) => m.syntax().ancestors().last().unwrap(),
        };

        self.map[impl_id].to_node(&root)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ImplBlock {
    module: Module,
    impl_id: ImplId,
}

impl HasSource for ImplBlock {
    type Ast = ast::ImplBlock;
    fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ImplBlock> {
        let source_map = db.impls_in_module_with_source_map(self.module).1;
        let src = self.module.definition_source(db);
        Source { file_id: src.file_id, ast: source_map.get(&src.ast, self.impl_id) }
    }
}

impl ImplBlock {
    pub(crate) fn containing(
        module_impl_blocks: Arc<ModuleImplBlocks>,
        item: ImplItem,
    ) -> Option<ImplBlock> {
        let impl_id = *module_impl_blocks.impls_by_def.get(&item)?;
        Some(ImplBlock { module: module_impl_blocks.module, impl_id })
    }

    pub(crate) fn from_id(module: Module, impl_id: ImplId) -> ImplBlock {
        ImplBlock { module, impl_id }
    }

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

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

    pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
        db.impls_in_module(self.module).impls[self.impl_id].target_trait().cloned()
    }

    pub fn target_type(&self, db: &impl DefDatabase) -> TypeRef {
        db.impls_in_module(self.module).impls[self.impl_id].target_type().clone()
    }

    pub fn target_ty(&self, db: &impl HirDatabase) -> Ty {
        Ty::from_hir(db, &self.resolver(db), &self.target_type(db))
    }

    pub fn target_trait_ref(&self, db: &impl HirDatabase) -> Option<TraitRef> {
        let target_ty = self.target_ty(db);
        TraitRef::from_hir(db, &self.resolver(db), &self.target_trait(db)?, Some(target_ty))
    }

    pub fn items(&self, db: &impl DefDatabase) -> Vec<ImplItem> {
        db.impls_in_module(self.module).impls[self.impl_id].items().to_vec()
    }

    pub fn is_negative(&self, db: &impl DefDatabase) -> bool {
        db.impls_in_module(self.module).impls[self.impl_id].negative
    }

    pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
        let r = self.module().resolver(db);
        // add generic params, if present
        let p = self.generic_params(db);
        let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
        let r = r.push_impl_block_scope(self.clone());
        r
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ImplData {
    target_trait: Option<TypeRef>,
    target_type: TypeRef,
    items: Vec<ImplItem>,
    negative: bool,
}

impl ImplData {
    pub(crate) fn from_ast(
        db: &(impl DefDatabase + AstDatabase),
        file_id: HirFileId,
        module: Module,
        node: &ast::ImplBlock,
    ) -> Self {
        let target_trait = node.target_trait().map(TypeRef::from_ast);
        let target_type = TypeRef::from_ast_opt(node.target_type());
        let ctx = LocationCtx::new(db, module, file_id);
        let negative = node.is_negative();
        let items = if let Some(item_list) = node.item_list() {
            item_list
                .impl_items()
                .map(|item_node| match item_node {
                    ast::ImplItem::FnDef(it) => Function { id: ctx.to_def(&it) }.into(),
                    ast::ImplItem::ConstDef(it) => Const { id: ctx.to_def(&it) }.into(),
                    ast::ImplItem::TypeAliasDef(it) => TypeAlias { id: ctx.to_def(&it) }.into(),
                })
                .collect()
        } else {
            Vec::new()
        };
        ImplData { target_trait, target_type, items, negative }
    }

    pub fn target_trait(&self) -> Option<&TypeRef> {
        self.target_trait.as_ref()
    }

    pub fn target_type(&self) -> &TypeRef {
        &self.target_type
    }

    pub fn items(&self) -> &[ImplItem] {
        &self.items
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
//FIXME: rename to ImplDef?
pub enum ImplItem {
    Method(Function),
    Const(Const),
    TypeAlias(TypeAlias),
    // Existential
}
impl_froms!(ImplItem: Const, TypeAlias);

impl From<Function> for ImplItem {
    fn from(func: Function) -> ImplItem {
        ImplItem::Method(func)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ImplId(pub RawId);
impl_arena_id!(ImplId);

/// The collection of impl blocks is a two-step process: first we collect the
/// blocks per-module; then we build an index of all impl blocks in the crate.
/// This way, we avoid having to do this process for the whole crate whenever
/// a file is changed; as long as the impl blocks in the file don't change,
/// we don't need to do the second step again.
#[derive(Debug, PartialEq, Eq)]
pub struct ModuleImplBlocks {
    pub(crate) module: Module,
    pub(crate) impls: Arena<ImplId, ImplData>,
    impls_by_def: FxHashMap<ImplItem, ImplId>,
}

impl ModuleImplBlocks {
    fn collect(
        db: &(impl DefDatabase + AstDatabase),
        module: Module,
        source_map: &mut ImplSourceMap,
    ) -> Self {
        let mut m = ModuleImplBlocks {
            module,
            impls: Arena::default(),
            impls_by_def: FxHashMap::default(),
        };

        let src = m.module.definition_source(db);
        let node = match &src.ast {
            ModuleSource::SourceFile(node) => node.syntax().clone(),
            ModuleSource::Module(node) => {
                node.item_list().expect("inline module should have item list").syntax().clone()
            }
        };

        for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) {
            let impl_block = ImplData::from_ast(db, src.file_id, m.module, &impl_block_ast);
            let id = m.impls.alloc(impl_block);
            for &impl_item in &m.impls[id].items {
                m.impls_by_def.insert(impl_item, id);
            }

            source_map.insert(id, &impl_block_ast);
        }

        m
    }
}

pub(crate) fn impls_in_module_with_source_map_query(
    db: &(impl DefDatabase + AstDatabase),
    module: Module,
) -> (Arc<ModuleImplBlocks>, Arc<ImplSourceMap>) {
    let mut source_map = ImplSourceMap::default();

    let result = ModuleImplBlocks::collect(db, module, &mut source_map);

    (Arc::new(result), Arc::new(source_map))
}

pub(crate) fn impls_in_module(db: &impl DefDatabase, module: Module) -> Arc<ModuleImplBlocks> {
    db.impls_in_module_with_source_map(module).0
}
<|endoftext|>


<commit_before>
use super::*;
mod tools
{
  #[ allow( unused_imports ) ]
  pub use super::super::*;
}

/// Private namespace of the module.
mod private
{
}

TheModule::mod_interface!
{

  // xxx : test with `layer { layer_a, layer_a };`
  // xxx : test with `use { layer_a, layer_a };`

  /// layer_a
  layer layer_a;
  /// layer_b
  layer layer_b;

}

//

// include!( "../../only_test/layer_divergent_only_test.rs" );
include!( "../../only_test/layer_simple_only_test.rs" );

<commit_msg>!test<commit_after>
use super::*;
mod tools
{
  #[ allow( unused_imports ) ]
  pub use super::super::*;
}

/// Private namespace of the module.
mod private
{
}

TheModule::mod_interface!
{

  // xxx : test with `layer { layer_a, layer_a };`
  // xxx : test with `use { layer_a, layer_a };`

  /// layer_a
  layer layer_a;
  /// layer_b
  layer layer_b;

}

//

// include!( "../../only_test/layer_divergent_only_test.rs" );
include!( "../../only_test/layer_simple_only_test.rs" );<|endoftext|>


<commit_before>use std::vec;
use std::slice;
use std::default::Default;
use std::fmt;

use clear::Clear;

pub struct RepeatedField<T> {
    vec: Vec<T>,
    len: uint,
}

impl<T> Collection for RepeatedField<T> {
    #[inline]
    fn len(&self) -> uint {
        self.len
    }
}

impl<T> Mutable for RepeatedField<T> {
    #[inline]
    fn clear(&mut self) {
        self.len = 0;
    }
}

impl<T> Clear for RepeatedField<T> {
    #[inline]
    fn clear(&mut self) {
        self.len = 0;
    }
}

impl<T> Default for RepeatedField<T> {
    #[inline]
    fn default() -> RepeatedField<T> {
        RepeatedField {
            vec: Vec::new(),
            len: 0,
        }
    }
}

impl<T> RepeatedField<T> {
    #[inline]
    pub fn new() -> RepeatedField<T> {
        Default::default()
    }

    #[inline]
    pub fn from_vec(vec: Vec<T>) -> RepeatedField<T> {
        let len = vec.len();
        RepeatedField {
            vec: vec,
            len: len,
        }
    }

    #[inline]
    pub fn into_vec(self) -> Vec<T> {
        let mut vec = self.vec;
        vec.truncate(self.len);
        vec
    }

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

    #[inline]
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        self.vec.mut_slice_to(self.len)
    }

    #[inline]
    pub fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T] {
        self.as_slice().slice(start, end)
    }

    #[inline]
    pub fn mut_slice<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [T] {
        self.as_mut_slice().mut_slice(start, end)
    }

    #[inline]
    pub fn slice_from<'a>(&'a self, start: uint) -> &'a [T] {
        self.as_slice().slice_from(start)
    }

    #[inline]
    pub fn mut_slice_from<'a>(&'a mut self, start: uint) -> &'a mut [T] {
        self.as_mut_slice().mut_slice_from(start)
    }

    #[inline]
    pub fn slice_to<'a>(&'a self, end: uint) -> &'a [T] {
        self.as_slice().slice_to(end)
    }

    #[inline]
    pub fn mut_slice_to<'a>(&'a mut self, end: uint) -> &'a mut [T] {
        self.as_mut_slice().mut_slice_to(end)
    }

    #[inline]
    pub fn mut_split_at<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]) {
        self.as_mut_slice().mut_split_at(mid)
    }

    #[inline]
    pub fn tail<'a>(&'a self) -> &'a [T] {
        self.as_slice().tail()
    }

    #[inline]
    pub fn tailn<'a>(&'a self, n: uint) -> &'a [T] {
        self.as_slice().tailn(n)
    }

    #[inline]
    pub fn last<'a>(&'a self) -> Option<&'a T> {
        self.as_slice().last()
    }

    #[inline]
    pub fn mut_last<'a>(&'a mut self) -> Option<&'a mut T> {
        self.as_mut_slice().mut_last()
    }

    #[inline]
    pub fn init<'a>(&'a self) -> &'a [T] {
        self.as_slice().init()
    }

    #[inline]
    pub fn push(&mut self, value: T) {
        if self.len == self.vec.len() {
            self.vec.push(value);
        } else {
            *self.vec.get_mut(self.len) = value;
        }
        self.len += 1;
    }

    #[inline]
    pub fn pop(&mut self) -> Option<T> {
        if self.len == 0 {
            None
        } else {
            self.vec.truncate(self.len);
            self.len -= 1;
            self.vec.pop()
        }
    }

    #[inline]
    pub fn insert(&mut self, index: uint, value: T) {
        assert!(index <= self.len);
        self.vec.insert(index, value);
        self.len += 1;
    }

    #[inline]
    pub fn remove(&mut self, index: uint) -> Option<T> {
        if index < self.len {
            self.len -= 1;
            self.vec.remove(index)
        } else {
            None
        }
    }

    #[inline]
    pub fn truncate(&mut self, len: uint) {
        if self.len > len {
            self.len = len;
        }
    }

    #[inline]
    pub fn reverse(&mut self) {
        self.as_mut_slice().reverse()
    }

    #[inline]
    pub fn move_iter(mut self) -> vec::MoveItems<T> {
        self.vec.truncate(self.len);
        self.vec.move_iter()
    }

    #[inline]
    pub fn get<'a>(&'a self, index: uint) -> &'a T {
        &self.as_slice()[index]
    }

    #[inline]
    pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
        &mut self.as_mut_slice()[index]
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> slice::Items<'a, T> {
        self.as_slice().iter()
    }

    #[inline]
    pub fn mut_iter<'a>(&'a mut self) -> slice::MutItems<'a, T> {
        self.as_mut_slice().mut_iter()
    }

    #[inline]
    pub fn sort_by(&mut self, compare: |&T, &T| -> Ordering) {
        self.as_mut_slice().sort_by(compare)
    }

    #[inline]
    pub fn as_ptr(&self) -> *const T {
        self.vec.as_ptr()
    }

    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut T {
        self.vec.as_mut_ptr()
    }
}

impl<T : Default+Clear> RepeatedField<T> {
    pub fn push_default<'a>(&'a mut self) -> &'a mut T {
        if self.len == self.vec.len() {
            self.vec.push(Default::default());
        } else {
            self.vec.get_mut(self.len).clear();
        }
        self.len += 1;
        self.mut_last().unwrap()
    }
}

impl<T : Clone> RepeatedField<T> {
    #[inline]
    pub fn from_slice(values: &[T]) -> RepeatedField<T> {
        RepeatedField::from_vec(Vec::from_slice(values))
    }
}

impl<T : Clone> Clone for RepeatedField<T> {
    #[inline]
    fn clone(&self) -> RepeatedField<T> {
        RepeatedField {
            vec: Vec::from_slice(self.as_slice()),
            len: self.len(),
        }
    }
}

impl<T> FromIterator<T> for RepeatedField<T> {
    #[inline]
    fn from_iter<I : Iterator<T>>(iter: I) -> RepeatedField<T> {
        RepeatedField::from_vec(FromIterator::from_iter(iter))
    }
}

impl<T : PartialEq> PartialEq for RepeatedField<T> {
    #[inline]
    fn eq(&self, other: &RepeatedField<T>) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl<T : Eq> Eq for RepeatedField<T> {}

impl<T : PartialEq> RepeatedField<T> {
    #[inline]
    pub fn contains(&self, value: &T) -> bool {
        self.as_slice().contains(value)
    }
}

impl<T> Vector<T> for RepeatedField<T> {
    #[inline]
    fn as_slice<'a>(&'a self) -> &'a [T] {
        self.vec.slice_to(self.len)
    }
}

impl<T : fmt::Show> fmt::Show for RepeatedField<T> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}
<commit_msg>Update for rust language changes<commit_after>use std::vec;
use std::slice;
use std::default::Default;
use std::fmt;

use clear::Clear;

pub struct RepeatedField<T> {
    vec: Vec<T>,
    len: uint,
}

impl<T> Collection for RepeatedField<T> {
    #[inline]
    fn len(&self) -> uint {
        self.len
    }
}

impl<T> Mutable for RepeatedField<T> {
    #[inline]
    fn clear(&mut self) {
        self.len = 0;
    }
}

impl<T> Clear for RepeatedField<T> {
    #[inline]
    fn clear(&mut self) {
        self.len = 0;
    }
}

impl<T> Default for RepeatedField<T> {
    #[inline]
    fn default() -> RepeatedField<T> {
        RepeatedField {
            vec: Vec::new(),
            len: 0,
        }
    }
}

impl<T> RepeatedField<T> {
    #[inline]
    pub fn new() -> RepeatedField<T> {
        Default::default()
    }

    #[inline]
    pub fn from_vec(vec: Vec<T>) -> RepeatedField<T> {
        let len = vec.len();
        RepeatedField {
            vec: vec,
            len: len,
        }
    }

    #[inline]
    pub fn into_vec(self) -> Vec<T> {
        let mut vec = self.vec;
        vec.truncate(self.len);
        vec
    }

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

    #[inline]
    pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
        self.vec.mut_slice_to(self.len)
    }

    #[inline]
    pub fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T] {
        self.as_slice().slice(start, end)
    }

    #[inline]
    pub fn mut_slice<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [T] {
        self.as_mut_slice().mut_slice(start, end)
    }

    #[inline]
    pub fn slice_from<'a>(&'a self, start: uint) -> &'a [T] {
        self.as_slice().slice_from(start)
    }

    #[inline]
    pub fn mut_slice_from<'a>(&'a mut self, start: uint) -> &'a mut [T] {
        self.as_mut_slice().mut_slice_from(start)
    }

    #[inline]
    pub fn slice_to<'a>(&'a self, end: uint) -> &'a [T] {
        self.as_slice().slice_to(end)
    }

    #[inline]
    pub fn mut_slice_to<'a>(&'a mut self, end: uint) -> &'a mut [T] {
        self.as_mut_slice().mut_slice_to(end)
    }

    #[inline]
    pub fn mut_split_at<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]) {
        self.as_mut_slice().mut_split_at(mid)
    }

    #[inline]
    pub fn tail<'a>(&'a self) -> &'a [T] {
        self.as_slice().tail()
    }

    #[inline]
    pub fn tailn<'a>(&'a self, n: uint) -> &'a [T] {
        self.as_slice().tailn(n)
    }

    #[inline]
    pub fn last<'a>(&'a self) -> Option<&'a T> {
        self.as_slice().last()
    }

    #[inline]
    pub fn mut_last<'a>(&'a mut self) -> Option<&'a mut T> {
        self.as_mut_slice().mut_last()
    }

    #[inline]
    pub fn init<'a>(&'a self) -> &'a [T] {
        self.as_slice().init()
    }

    #[inline]
    pub fn push(&mut self, value: T) {
        if self.len == self.vec.len() {
            self.vec.push(value);
        } else {
            *self.vec.get_mut(self.len) = value;
        }
        self.len += 1;
    }

    #[inline]
    pub fn pop(&mut self) -> Option<T> {
        if self.len == 0 {
            None
        } else {
            self.vec.truncate(self.len);
            self.len -= 1;
            self.vec.pop()
        }
    }

    #[inline]
    pub fn insert(&mut self, index: uint, value: T) {
        assert!(index <= self.len);
        self.vec.insert(index, value);
        self.len += 1;
    }

    #[inline]
    pub fn remove(&mut self, index: uint) -> Option<T> {
        if index < self.len {
            self.len -= 1;
            self.vec.remove(index)
        } else {
            None
        }
    }

    #[inline]
    pub fn truncate(&mut self, len: uint) {
        if self.len > len {
            self.len = len;
        }
    }

    #[inline]
    pub fn reverse(&mut self) {
        self.as_mut_slice().reverse()
    }

    #[inline]
    pub fn move_iter(mut self) -> vec::MoveItems<T> {
        self.vec.truncate(self.len);
        self.vec.move_iter()
    }

    #[inline]
    pub fn get<'a>(&'a self, index: uint) -> &'a T {
        &self.as_slice()[index]
    }

    #[inline]
    pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut T {
        &mut self.as_mut_slice()[index]
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> slice::Items<'a, T> {
        self.as_slice().iter()
    }

    #[inline]
    pub fn mut_iter<'a>(&'a mut self) -> slice::MutItems<'a, T> {
        self.as_mut_slice().mut_iter()
    }

    #[inline]
    pub fn sort_by(&mut self, compare: |&T, &T| -> Ordering) {
        self.as_mut_slice().sort_by(compare)
    }

    #[inline]
    pub fn as_ptr(&self) -> *const T {
        self.vec.as_ptr()
    }

    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut T {
        self.vec.as_mut_ptr()
    }
}

impl<T : Default+Clear> RepeatedField<T> {
    pub fn push_default<'a>(&'a mut self) -> &'a mut T {
        if self.len == self.vec.len() {
            self.vec.push(Default::default());
        } else {
            self.vec.get_mut(self.len).clear();
        }
        self.len += 1;
        self.mut_last().unwrap()
    }
}

impl<T : Clone> RepeatedField<T> {
    #[inline]
    pub fn from_slice(values: &[T]) -> RepeatedField<T> {
        RepeatedField::from_vec(Vec::from_slice(values))
    }
}

impl<T : Clone> Clone for RepeatedField<T> {
    #[inline]
    fn clone(&self) -> RepeatedField<T> {
        RepeatedField {
            vec: Vec::from_slice(self.as_slice()),
            len: self.len(),
        }
    }
}

impl<T> FromIterator<T> for RepeatedField<T> {
    #[inline]
    fn from_iter<I : Iterator<T>>(iter: I) -> RepeatedField<T> {
        RepeatedField::from_vec(FromIterator::from_iter(iter))
    }
}

impl<T : PartialEq> PartialEq for RepeatedField<T> {
    #[inline]
    fn eq(&self, other: &RepeatedField<T>) -> bool {
        self.as_slice() == other.as_slice()
    }
}

impl<T : Eq> Eq for RepeatedField<T> {}

impl<T : PartialEq> RepeatedField<T> {
    #[inline]
    pub fn contains(&self, value: &T) -> bool {
        self.as_slice().contains(value)
    }
}

impl<T> Slice<T> for RepeatedField<T> {
    #[inline]
    fn as_slice<'a>(&'a self) -> &'a [T] {
        self.vec.slice_to(self.len)
    }
}

impl<T : fmt::Show> fmt::Show for RepeatedField<T> {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.as_slice().fmt(f)
    }
}
<|endoftext|>


<commit_before>use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
use humantime::parse_duration;
use std::time::Duration;
use time;

use super::error::*;
use failure::ResultExt;

#[derive(Default, Debug)]
pub struct CommandParser {
    on_date: Option<String>,
    at_time: Option<String>,
    in_duration: Option<String>,
    every_time: Option<String>,
    target: String,
    message: Option<String>,
}

#[derive(PartialEq, Clone, Copy)]
enum ParseState {
    None,
    On,
    At,
    In,
    Every,
    Msg,
}

impl CommandParser {
    pub fn parse_target(mut tokens: Vec<String>) -> Result<Self, RemindError> {
        let mut parser = CommandParser::default();

        if let Some(target) = tokens.pop() {
            parser.target = target;
        } else {
            Err(ErrorKind::MissingReceiver)?;
        }

        parser.parse_tokens(tokens)
    }

    pub fn with_target(tokens: Vec<String>, target: String) -> Result<Self, RemindError> {
        let mut parser = CommandParser::default();
        parser.target = target;

        parser.parse_tokens(tokens)
    }

    fn parse_tokens(mut self, tokens: Vec<String>) -> Result<Self, RemindError> {
        let mut state = ParseState::None;
        let mut cur_str = String::new();

        for token in tokens {
            let next_state = match token.as_ref() {
                "on" => ParseState::On,
                "at" => ParseState::At,
                "in" => ParseState::In,
                "every" => ParseState::Every,
                "to" => ParseState::Msg,
                _ => {
                    if !cur_str.is_empty() {
                        cur_str.push(' ');
                    }
                    cur_str.push_str(&token);
                    state
                }
            };

            if next_state != state {
                if state != ParseState::None {
                    self = self.add_string_by_state(&state, cur_str)?;
                    cur_str = String::new();
                }

                state = next_state;
            }
        }

        self = self.add_string_by_state(&state, cur_str)?;

        if self.message.is_none() {
            return Err(ErrorKind::MissingMessage.into());
        }

        if self.in_duration.is_some() && self.at_time.is_some()
            || self.in_duration.is_some() && self.on_date.is_some()
        {
            return Err(ErrorKind::AmbiguousTime.into());
        }

        if self.in_duration.is_none() && self.at_time.is_none() && self.on_date.is_none() {
            return Err(ErrorKind::MissingTime.into());
        }

        Ok(self)
    }

    fn add_string_by_state(self, state: &ParseState, string: String) -> Result<Self, RemindError> {
        use self::ParseState::*;
        let string = Some(string);
        match state {
            &On if self.on_date.is_none() => {
                return Ok(CommandParser {
                    on_date: string,
                    ..self
                })
            }
            &At if self.at_time.is_none() => {
                return Ok(CommandParser {
                    at_time: string,
                    ..self
                })
            }
            &In if self.in_duration.is_none() => {
                return Ok(CommandParser {
                    in_duration: string,
                    ..self
                })
            }
            &Msg if self.message.is_none() => {
                return Ok(CommandParser {
                    message: string,
                    ..self
                })
            }
            &Every if self.every_time.is_none() => {
                return Ok(CommandParser {
                    every_time: string,
                    ..self
                })
            }
            _ => Err(ErrorKind::MissingMessage.into()),
        }
    }

    fn parse_date(&self, str_date: &str) -> Result<NaiveDate, RemindError> {
        let nums = str_date
            .split('.')
            .map(|s| s.parse::<u32>())
            .collect::<Result<Vec<_>, _>>()
            .context(ErrorKind::InvalidDate)?;

        if 2 > nums.len() || nums.len() > 3 {
            return Err(ErrorKind::InvalidDate.into());
        }

        let day = nums[0];
        let month = nums[1];

        let parse_date = match nums.get(2) {
            Some(year) => {
                NaiveDate::from_ymd_opt(*year as i32, month, day).ok_or(ErrorKind::InvalidDate)?
            }
            None => {
                let now = time::now();
                let date = NaiveDate::from_ymd_opt(now.tm_year + 1900, month, day)
                    .ok_or(ErrorKind::InvalidDate)?;
                if date.succ().and_hms(0, 0, 0).timestamp() < now.to_timespec().sec {
                    NaiveDate::from_ymd(now.tm_year + 1901, month, day)
                } else {
                    date
                }
            }
        };

        Ok(parse_date)
    }

    fn parse_time(&self, str_time: &str) -> Result<NaiveTime, RemindError> {
        let nums = str_time
            .split(':')
            .map(|s| s.parse::<u32>())
            .collect::<Result<Vec<_>, _>>()
            .context(ErrorKind::InvalidTime)?;

        if 2 != nums.len() {
            return Err(ErrorKind::InvalidTime.into());
        }

        let hour = nums[0];
        let minute = nums[1];

        Ok(NaiveTime::from_hms(hour, minute, 0))
    }

    pub fn get_time(&self, min_dur: Duration) -> Result<NaiveDateTime, RemindError> {
        if let Some(ref str_duration) = self.in_duration {
            let duration = parse_duration(&str_duration).context(ErrorKind::InvalidTime)?;

            if duration < min_dur {
                return Err(ErrorKind::TimeShort.into());
            }

            let tm = time::now().to_timespec();
            return Ok(NaiveDateTime::from_timestamp(
                tm.sec + duration.as_secs() as i64,
                0u32,
            ));
        }

        let mut date = None;
        if let Some(ref str_date) = self.on_date {
            date = Some(self.parse_date(str_date)?);
        }

        if let Some(ref str_time) = self.at_time {
            let time = self.parse_time(str_time)?;

            if let Some(date) = date {
                Ok(date.and_time(time))
            } else {
                let now = time::now();
                let today = NaiveDate::from_ymd_opt(
                    now.tm_year + 1900,
                    now.tm_mon as u32 + 1,
                    now.tm_mday as u32,
                ).ok_or(ErrorKind::InvalidDate)?;

                let time_today = today.and_time(time);

                if time_today.timestamp() < now.to_timespec().sec {
                    debug!("tomorrow");

                    Ok(today.succ().and_time(time))
                } else {
                    debug!("today");

                    Ok(time_today)
                }
            }
        } else {
            Ok(date.expect("At this point date has to be set")
                .and_hms(0, 0, 0))
        }
    }

    pub fn get_repeat(&self, min_dur: Duration) -> Result<Option<Duration>, RemindError> {
        if let Some(mut words) = self.every_time.clone() {
            if !words.chars().next().unwrap().is_digit(10) {
                words.insert(0, '1');
            }
            let dur = parse_duration(&words).context(ErrorKind::InvalidTime)?;

            if dur < min_dur {
                return Err(ErrorKind::RepeatTimeShort.into());
            }

            Ok(Some(dur))
        } else {
            Ok(None)
        }
    }

    pub fn get_target(&self) -> &str {
        &self.target
    }

    pub fn get_message(&self) -> &str {
        self.message.as_ref().expect("Has to be set")
    }
}
<commit_msg>Remind: Fix target parsing<commit_after>use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
use humantime::parse_duration;
use std::time::Duration;
use time;

use super::error::*;
use failure::ResultExt;

#[derive(Default, Debug)]
pub struct CommandParser {
    on_date: Option<String>,
    at_time: Option<String>,
    in_duration: Option<String>,
    every_time: Option<String>,
    target: String,
    message: Option<String>,
}

#[derive(PartialEq, Clone, Copy)]
enum ParseState {
    None,
    On,
    At,
    In,
    Every,
    Msg,
}

impl CommandParser {
    pub fn parse_target(mut tokens: Vec<String>) -> Result<Self, RemindError> {
        let mut parser = CommandParser::default();

        if tokens.is_empty() {
            Err(ErrorKind::MissingReceiver)?;
        }

        parser.target = tokens.remove(0);

        parser.parse_tokens(tokens)
    }

    pub fn with_target(tokens: Vec<String>, target: String) -> Result<Self, RemindError> {
        let mut parser = CommandParser::default();
        parser.target = target;

        parser.parse_tokens(tokens)
    }

    fn parse_tokens(mut self, tokens: Vec<String>) -> Result<Self, RemindError> {
        let mut state = ParseState::None;
        let mut cur_str = String::new();

        for token in tokens {
            let next_state = match token.as_ref() {
                "on" => ParseState::On,
                "at" => ParseState::At,
                "in" => ParseState::In,
                "every" => ParseState::Every,
                "to" => ParseState::Msg,
                _ => {
                    if !cur_str.is_empty() {
                        cur_str.push(' ');
                    }
                    cur_str.push_str(&token);
                    state
                }
            };

            if next_state != state {
                if state != ParseState::None {
                    self = self.add_string_by_state(&state, cur_str)?;
                    cur_str = String::new();
                }

                state = next_state;
            }
        }

        self = self.add_string_by_state(&state, cur_str)?;

        if self.message.is_none() {
            return Err(ErrorKind::MissingMessage.into());
        }

        if self.in_duration.is_some() && self.at_time.is_some()
            || self.in_duration.is_some() && self.on_date.is_some()
        {
            return Err(ErrorKind::AmbiguousTime.into());
        }

        if self.in_duration.is_none() && self.at_time.is_none() && self.on_date.is_none() {
            return Err(ErrorKind::MissingTime.into());
        }

        Ok(self)
    }

    fn add_string_by_state(self, state: &ParseState, string: String) -> Result<Self, RemindError> {
        use self::ParseState::*;
        let string = Some(string);
        match state {
            &On if self.on_date.is_none() => {
                return Ok(CommandParser {
                    on_date: string,
                    ..self
                })
            }
            &At if self.at_time.is_none() => {
                return Ok(CommandParser {
                    at_time: string,
                    ..self
                })
            }
            &In if self.in_duration.is_none() => {
                return Ok(CommandParser {
                    in_duration: string,
                    ..self
                })
            }
            &Msg if self.message.is_none() => {
                return Ok(CommandParser {
                    message: string,
                    ..self
                })
            }
            &Every if self.every_time.is_none() => {
                return Ok(CommandParser {
                    every_time: string,
                    ..self
                })
            }
            _ => Err(ErrorKind::MissingMessage.into()),
        }
    }

    fn parse_date(&self, str_date: &str) -> Result<NaiveDate, RemindError> {
        let nums = str_date
            .split('.')
            .map(|s| s.parse::<u32>())
            .collect::<Result<Vec<_>, _>>()
            .context(ErrorKind::InvalidDate)?;

        if 2 > nums.len() || nums.len() > 3 {
            return Err(ErrorKind::InvalidDate.into());
        }

        let day = nums[0];
        let month = nums[1];

        let parse_date = match nums.get(2) {
            Some(year) => {
                NaiveDate::from_ymd_opt(*year as i32, month, day).ok_or(ErrorKind::InvalidDate)?
            }
            None => {
                let now = time::now();
                let date = NaiveDate::from_ymd_opt(now.tm_year + 1900, month, day)
                    .ok_or(ErrorKind::InvalidDate)?;
                if date.succ().and_hms(0, 0, 0).timestamp() < now.to_timespec().sec {
                    NaiveDate::from_ymd(now.tm_year + 1901, month, day)
                } else {
                    date
                }
            }
        };

        Ok(parse_date)
    }

    fn parse_time(&self, str_time: &str) -> Result<NaiveTime, RemindError> {
        let nums = str_time
            .split(':')
            .map(|s| s.parse::<u32>())
            .collect::<Result<Vec<_>, _>>()
            .context(ErrorKind::InvalidTime)?;

        if 2 != nums.len() {
            return Err(ErrorKind::InvalidTime.into());
        }

        let hour = nums[0];
        let minute = nums[1];

        Ok(NaiveTime::from_hms(hour, minute, 0))
    }

    pub fn get_time(&self, min_dur: Duration) -> Result<NaiveDateTime, RemindError> {
        if let Some(ref str_duration) = self.in_duration {
            let duration = parse_duration(&str_duration).context(ErrorKind::InvalidTime)?;

            if duration < min_dur {
                return Err(ErrorKind::TimeShort.into());
            }

            let tm = time::now().to_timespec();
            return Ok(NaiveDateTime::from_timestamp(
                tm.sec + duration.as_secs() as i64,
                0u32,
            ));
        }

        let mut date = None;
        if let Some(ref str_date) = self.on_date {
            date = Some(self.parse_date(str_date)?);
        }

        if let Some(ref str_time) = self.at_time {
            let time = self.parse_time(str_time)?;

            if let Some(date) = date {
                Ok(date.and_time(time))
            } else {
                let now = time::now();
                let today = NaiveDate::from_ymd_opt(
                    now.tm_year + 1900,
                    now.tm_mon as u32 + 1,
                    now.tm_mday as u32,
                ).ok_or(ErrorKind::InvalidDate)?;

                let time_today = today.and_time(time);

                if time_today.timestamp() < now.to_timespec().sec {
                    debug!("tomorrow");

                    Ok(today.succ().and_time(time))
                } else {
                    debug!("today");

                    Ok(time_today)
                }
            }
        } else {
            Ok(date.expect("At this point date has to be set")
                .and_hms(0, 0, 0))
        }
    }

    pub fn get_repeat(&self, min_dur: Duration) -> Result<Option<Duration>, RemindError> {
        if let Some(mut words) = self.every_time.clone() {
            if !words.chars().next().unwrap().is_digit(10) {
                words.insert(0, '1');
            }
            let dur = parse_duration(&words).context(ErrorKind::InvalidTime)?;

            if dur < min_dur {
                return Err(ErrorKind::RepeatTimeShort.into());
            }

            Ok(Some(dur))
        } else {
            Ok(None)
        }
    }

    pub fn get_target(&self) -> &str {
        &self.target
    }

    pub fn get_message(&self) -> &str {
        self.message.as_ref().expect("Has to be set")
    }
}
<|endoftext|>


<commit_before>/**
 * Generate variants of a base value by applying parts
 *
 * Example:
 *
 * ```ignore
 * generate_variants(path, vec!["foo", "bar", "baz"], |b, v| {
 *    let b = b.clone();
 *    b.push(v);
 *    b
 * })
 *
 * ```
 *
 */
pub fn generate_variants<A, B, C, F>(base: A, modders: Vec<B>, f: &F)
    -> Vec<C>
    where
        F: Fn(&A, B) -> C
{
    modders.into_iter().map(|m| f(&base, m)).collect()
}

<commit_msg>util: Add variant-tests<commit_after>/**
 * Generate variants of a base value by applying parts
 *
 * Example:
 *
 * ```ignore
 * generate_variants(path, vec!["foo", "bar", "baz"], |b, v| {
 *    let b = b.clone();
 *    b.push(v);
 *    b
 * })
 *
 * ```
 *
 */
pub fn generate_variants<A, B, C, F>(base: A, modders: Vec<B>, f: &F)
    -> Vec<C>
    where
        F: Fn(&A, B) -> C
{
    modders.into_iter().map(|m| f(&base, m)).collect()
}

#[cfg(test)]
mod test {

    use super::generate_variants;

    #[test]
    fn test_variants_simple() {
        let base = 1;
        let vars = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
        let res = generate_variants(base, vars, &|base, var| base + var);

        assert!(res.len() == 11, format!("Length is {} instead of 11", res.len()));
        assert!(res.iter().all(|i| *i > 0));
        assert!(res == vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
    }

    #[test]
    fn test_variants_pathes() {
        use std::path::PathBuf;

        let base = PathBuf::from("/");
        let vars = vec!["foo", "bar", "baz"];
        let res = generate_variants(base, vars, &|base, var| {
            let mut base = base.clone();
            base.push(var);
            base
        });

        assert!(res.len() == 3, format!("Length is {} instead of 3", res.len()));
        let eq_vec = vec!["/foo", "/bar", "/baz"];
        let eq     = eq_vec.iter().map(PathBuf::from);
        assert!(res.into_iter().zip(eq).all(|(orig, equi)| orig == equi));
    }

}

<|endoftext|>