<commit_before>use arch::paging::{ActivePageTable, Page, PageIter, VirtualAddress};
use arch::paging::entry::EntryFlags;

#[derive(Debug)]
pub struct Memory {
    start: VirtualAddress,
    size: usize,
    flags: EntryFlags
}

impl Memory {
    pub fn new(start: VirtualAddress, size: usize, flags: EntryFlags) -> Self {
        let mut memory = Memory {
            start: start,
            size: size,
            flags: flags
        };

        memory.map(true);

        memory
    }

    pub fn start_address(&self) -> VirtualAddress {
        self.start
    }

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

    pub fn pages(&self) -> PageIter {
        let start_page = Page::containing_address(self.start);
        let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1));
        Page::range_inclusive(start_page, end_page)
    }

    pub fn map(&mut self, flush: bool) {
        let mut active_table = unsafe { ActivePageTable::new() };

        for page in self.pages() {
            active_table.map(page, self.flags);
            if flush {
                active_table.flush(page);
            }
        }
    }

    pub fn unmap(&mut self, flush: bool) {
        let mut active_table = unsafe { ActivePageTable::new() };

        for page in self.pages() {
            active_table.unmap(page);
            if flush {
                active_table.flush(page);
            }
        }
    }

    pub fn remap(&mut self, new_flags: EntryFlags, flush: bool) {
        let mut active_table = unsafe { ActivePageTable::new() };

        for page in self.pages() {
            active_table.remap(page, new_flags);
            if flush {
                active_table.flush(page);
            }
        }

        self.flags = new_flags;
    }

    pub fn resize(&mut self, new_size: usize, flush: bool) {
        let mut active_table = unsafe { ActivePageTable::new() };

        if new_size > self.size {
            let start_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size));
            let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + new_size - 1));
            for page in Page::range_inclusive(start_page, end_page) {
                //println!("Map {:X}", page.start_address().get());
                if active_table.translate_page(page).is_none() {
                    //println!("Not found - mapping");
                    active_table.map(page, self.flags);
                    if flush {
                        active_table.flush(page);
                    }
                } else {
                    //println!("Found - skipping");
                }
            }
        } else if new_size < self.size {
            let start_page = Page::containing_address(VirtualAddress::new(self.start.get() + new_size));
            let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1));
            for page in Page::range_inclusive(start_page, end_page) {
                //println!("Unmap {:X}", page.start_address().get());
                if active_table.translate_page(page).is_some() {
                    //println!("Found - unmapping");
                    active_table.unmap(page);
                    if flush {
                        active_table.flush(page);
                    }
                } else {
                    //println!("Not found - skipping");
                }
            }
        }

        self.size = new_size;
    }
}

impl Drop for Memory {
    fn drop(&mut self) {
        self.unmap(true);
    }
}
<commit_msg>Add comments<commit_after>use arch::paging::{ActivePageTable, Page, PageIter, VirtualAddress};
use arch::paging::entry::EntryFlags;

#[derive(Debug)]
pub struct Memory {
    start: VirtualAddress,
    size: usize,
    flags: EntryFlags
}

impl Memory {
    pub fn new(start: VirtualAddress, size: usize, flags: EntryFlags) -> Self {
        let mut memory = Memory {
            start: start,
            size: size,
            flags: flags
        };

        memory.map(true);

        memory
    }

    pub fn start_address(&self) -> VirtualAddress {
        self.start
    }

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

    pub fn pages(&self) -> PageIter {
        let start_page = Page::containing_address(self.start);
        let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1));
        Page::range_inclusive(start_page, end_page)
    }

    pub fn map(&mut self, flush: bool) {
        let mut active_table = unsafe { ActivePageTable::new() };

        //TODO: Clear pages?
        for page in self.pages() {
            active_table.map(page, self.flags);
            if flush {
                active_table.flush(page);
            }
        }
    }

    pub fn unmap(&mut self, flush: bool) {
        let mut active_table = unsafe { ActivePageTable::new() };

        for page in self.pages() {
            active_table.unmap(page);
            if flush {
                active_table.flush(page);
            }
        }
    }

    pub fn remap(&mut self, new_flags: EntryFlags, flush: bool) {
        let mut active_table = unsafe { ActivePageTable::new() };

        for page in self.pages() {
            active_table.remap(page, new_flags);
            if flush {
                active_table.flush(page);
            }
        }

        self.flags = new_flags;
    }

    pub fn resize(&mut self, new_size: usize, flush: bool) {
        let mut active_table = unsafe { ActivePageTable::new() };

        //TODO: Clear pages?
        //TODO: Calculate page changes to minimize operations
        if new_size > self.size {
            let start_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size));
            let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + new_size - 1));
            for page in Page::range_inclusive(start_page, end_page) {
                //println!("Map {:X}", page.start_address().get());
                if active_table.translate_page(page).is_none() {
                    //println!("Not found - mapping");
                    active_table.map(page, self.flags);
                    if flush {
                        active_table.flush(page);
                    }
                } else {
                    //println!("Found - skipping {:X}", page.start_address().get());
                }
            }
        } else if new_size < self.size {
            let start_page = Page::containing_address(VirtualAddress::new(self.start.get() + new_size));
            let end_page = Page::containing_address(VirtualAddress::new(self.start.get() + self.size - 1));
            for page in Page::range_inclusive(start_page, end_page) {
                //println!("Unmap {:X}", page.start_address().get());
                if active_table.translate_page(page).is_some() {
                    //println!("Found - unmapping");
                    active_table.unmap(page);
                    if flush {
                        active_table.flush(page);
                    }
                } else {
                    //println!("Not found - skipping {:X}", page.start_address().get());
                }
            }
        }

        self.size = new_size;
    }
}

impl Drop for Memory {
    fn drop(&mut self) {
        self.unmap(true);
    }
}
<|endoftext|>


<commit_before>use block_producer::{BeaconNode, BeaconNodeError, PublishOutcome};
use protos::services::{
    BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest,
};
use protos::services_grpc::BeaconBlockServiceClient;
use ssz::{ssz_encode, Decodable};
use std::sync::Arc;
use types::{BeaconBlock, BeaconBlockBody, Eth1Data, Hash256, PublicKey, Signature, Slot};

/// A newtype designed to wrap the gRPC-generated service so the `BeaconNode` trait may be
/// implemented upon it.
pub struct BeaconBlockGrpcClient {
    client: Arc<BeaconBlockServiceClient>,
}

impl BeaconBlockGrpcClient {
    pub fn new(client: Arc<BeaconBlockServiceClient>) -> Self {
        Self { client }
    }
}

impl BeaconNode for BeaconBlockGrpcClient {
    fn proposer_nonce(&self, pubkey: &PublicKey) -> Result<u64, BeaconNodeError> {
        // TODO: this might not be required.
        //
        // See: https://github.com/ethereum/eth2.0-specs/pull/496
        panic!("Not implemented.")
    }
    /// Request a Beacon Node (BN) to produce a new block at the supplied slot.
    ///
    /// Returns `None` if it is not possible to produce at the supplied slot. For example, if the
    /// BN is unable to find a parent block.
    fn produce_beacon_block(
        &self,
        slot: Slot,
        randao_reveal: &Signature,
    ) -> Result<Option<BeaconBlock>, BeaconNodeError> {
        let mut req = ProduceBeaconBlockRequest::new();
        req.set_slot(slot.as_u64());

        let reply = self
            .client
            .produce_beacon_block(&req)
            .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?;

        if reply.has_block() {
            let block = reply.get_block();

            let (signature, _) = Signature::ssz_decode(block.get_signature(), 0)
                .map_err(|_| BeaconNodeError::DecodeFailure)?;

            let (randao_reveal, _) = Signature::ssz_decode(block.get_randao_reveal(), 0)
                .map_err(|_| BeaconNodeError::DecodeFailure)?;

            // TODO: this conversion is incomplete; fix it.
            Ok(Some(BeaconBlock {
                slot: Slot::new(block.get_slot()),
                parent_root: Hash256::zero(),
                state_root: Hash256::zero(),
                randao_reveal,
                eth1_data: Eth1Data {
                    deposit_root: Hash256::zero(),
                    block_hash: Hash256::zero(),
                },
                signature,
                body: BeaconBlockBody {
                    proposer_slashings: vec![],
                    attester_slashings: vec![],
                    attestations: vec![],
                    deposits: vec![],
                    exits: vec![],
                },
            }))
        } else {
            Ok(None)
        }
    }

    /// Request a Beacon Node (BN) to publish a block.
    ///
    /// Generally, this will be called after a `produce_beacon_block` call with a block that has
    /// been completed (signed) by the validator client.
    fn publish_beacon_block(&self, block: BeaconBlock) -> Result<PublishOutcome, BeaconNodeError> {
        let mut req = PublishBeaconBlockRequest::new();

        // TODO: this conversion is incomplete; fix it.
        let mut grpc_block = GrpcBeaconBlock::new();
        grpc_block.set_slot(block.slot.as_u64());
        grpc_block.set_block_root(vec![0]);
        grpc_block.set_randao_reveal(ssz_encode(&block.randao_reveal));
        grpc_block.set_signature(ssz_encode(&block.signature));

        req.set_block(grpc_block);

        let reply = self
            .client
            .publish_beacon_block(&req)
            .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?;

        if reply.get_success() {
            Ok(PublishOutcome::ValidBlock)
        } else {
            // TODO: distinguish between different errors
            Ok(PublishOutcome::InvalidBlock("Publish failed".to_string()))
        }
    }
}
<commit_msg>Update validator_client for spec v0.2.0<commit_after>use block_producer::{BeaconNode, BeaconNodeError, PublishOutcome};
use protos::services::{
    BeaconBlock as GrpcBeaconBlock, ProduceBeaconBlockRequest, PublishBeaconBlockRequest,
};
use protos::services_grpc::BeaconBlockServiceClient;
use ssz::{ssz_encode, Decodable};
use std::sync::Arc;
use types::{BeaconBlock, BeaconBlockBody, Eth1Data, Hash256, PublicKey, Signature, Slot};

/// A newtype designed to wrap the gRPC-generated service so the `BeaconNode` trait may be
/// implemented upon it.
pub struct BeaconBlockGrpcClient {
    client: Arc<BeaconBlockServiceClient>,
}

impl BeaconBlockGrpcClient {
    pub fn new(client: Arc<BeaconBlockServiceClient>) -> Self {
        Self { client }
    }
}

impl BeaconNode for BeaconBlockGrpcClient {
    /// Request a Beacon Node (BN) to produce a new block at the supplied slot.
    ///
    /// Returns `None` if it is not possible to produce at the supplied slot. For example, if the
    /// BN is unable to find a parent block.
    fn produce_beacon_block(
        &self,
        slot: Slot,
        randao_reveal: &Signature,
    ) -> Result<Option<BeaconBlock>, BeaconNodeError> {
        let mut req = ProduceBeaconBlockRequest::new();
        req.set_slot(slot.as_u64());

        let reply = self
            .client
            .produce_beacon_block(&req)
            .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?;

        if reply.has_block() {
            let block = reply.get_block();

            let (signature, _) = Signature::ssz_decode(block.get_signature(), 0)
                .map_err(|_| BeaconNodeError::DecodeFailure)?;

            let (randao_reveal, _) = Signature::ssz_decode(block.get_randao_reveal(), 0)
                .map_err(|_| BeaconNodeError::DecodeFailure)?;

            // TODO: this conversion is incomplete; fix it.
            Ok(Some(BeaconBlock {
                slot: Slot::new(block.get_slot()),
                parent_root: Hash256::zero(),
                state_root: Hash256::zero(),
                randao_reveal,
                eth1_data: Eth1Data {
                    deposit_root: Hash256::zero(),
                    block_hash: Hash256::zero(),
                },
                signature,
                body: BeaconBlockBody {
                    proposer_slashings: vec![],
                    attester_slashings: vec![],
                    attestations: vec![],
                    deposits: vec![],
                    exits: vec![],
                },
            }))
        } else {
            Ok(None)
        }
    }

    /// Request a Beacon Node (BN) to publish a block.
    ///
    /// Generally, this will be called after a `produce_beacon_block` call with a block that has
    /// been completed (signed) by the validator client.
    fn publish_beacon_block(&self, block: BeaconBlock) -> Result<PublishOutcome, BeaconNodeError> {
        let mut req = PublishBeaconBlockRequest::new();

        // TODO: this conversion is incomplete; fix it.
        let mut grpc_block = GrpcBeaconBlock::new();
        grpc_block.set_slot(block.slot.as_u64());
        grpc_block.set_block_root(vec![0]);
        grpc_block.set_randao_reveal(ssz_encode(&block.randao_reveal));
        grpc_block.set_signature(ssz_encode(&block.signature));

        req.set_block(grpc_block);

        let reply = self
            .client
            .publish_beacon_block(&req)
            .map_err(|err| BeaconNodeError::RemoteFailure(format!("{:?}", err)))?;

        if reply.get_success() {
            Ok(PublishOutcome::ValidBlock)
        } else {
            // TODO: distinguish between different errors
            Ok(PublishOutcome::InvalidBlock("Publish failed".to_string()))
        }
    }
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]

extern crate rand;
extern crate rayon;
extern crate time;

use rand::{Rng, SeedableRng, XorShiftRng};
use std::env;
use std::str::FromStr;

trait Joiner {
    fn is_parallel() -> bool;
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send;
}

struct Parallel;
impl Joiner for Parallel {
    #[inline]
    fn is_parallel() -> bool {
        true
    }
    #[inline]
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send
    {
        rayon::join(oper_a, oper_b)
    }
}

struct Sequential;
impl Joiner for Sequential {
    #[inline]
    fn is_parallel() -> bool {
        false
    }
    #[inline]
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send
    {
        let a = oper_a();
        let b = oper_b();
        (a, b)
    }
}

fn quick_sort<J:Joiner, T:PartialOrd+Send>(v: &mut [T]) {
    if v.len() <= 1 {
        return;
    }

    if J::is_parallel() && v.len() <= 1024 {
        return quick_sort::<Sequential, T>(v);
    }

    let mid = partition(v);
    let (lo, hi) = v.split_at_mut(mid);
    J::join(|| quick_sort::<J,T>(lo),
            || quick_sort::<J,T>(hi));
}

fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
    let pivot = v.len() - 1;
    let mut i = 0;
    for j in 0..pivot {
        if v[j] <= v[pivot] {
            v.swap(i, j);
            i += 1;
        }
    }
    v.swap(i, pivot);
    i
}

fn main() {
    let mut kilo = 24;
    let mut run_par = true;
    let mut run_seq = true;

    let args = env::args();
    for arg in args.skip(1) {
        if arg == "--no-par" {
            run_par = false;
        } else if arg == "--no-seq" {
            run_seq = false;
        } else {
            match usize::from_str(&arg) {
                Ok(v) => kilo = v,
                Err(_) => {
                    println!("invalid argument `{}`, expected integer", arg);
                }
            }
        }
    }

    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
    let data: Vec<_> = (0..kilo*1024).map(|_| rng.next_u32()).collect();

    rayon::initialize();

    let par_time = if run_par {
        let mut data = data.clone();
        let par_start = time::precise_time_ns();
        quick_sort::<Parallel, u32>(&mut data);
        time::precise_time_ns() - par_start
    } else {
        0
    };

    let seq_time = if run_seq {
        let mut data = data.clone();
        let seq_start = time::precise_time_ns();
        quick_sort::<Sequential, u32>(&mut data);
        time::precise_time_ns() - seq_start
    } else {
        0
    };

    println!("Array length    : {}K 32-bit integers", kilo);
    if run_par { println!("Parallel time   : {}", par_time); }
    if run_seq { println!("Sequential time : {}", seq_time); }
    if run_par && run_seq {
        println!("Parallel speedup: {}", (seq_time as f64) / (par_time as f64));
    }
}
<commit_msg>add reps parameter<commit_after>#![allow(non_camel_case_types)]

extern crate rand;
extern crate rayon;
extern crate time;

use rand::{Rng, SeedableRng, XorShiftRng};
use std::env;
use std::str::FromStr;

trait Joiner {
    fn is_parallel() -> bool;
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send;
}

struct Parallel;
impl Joiner for Parallel {
    #[inline]
    fn is_parallel() -> bool {
        true
    }
    #[inline]
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send
    {
        rayon::join(oper_a, oper_b)
    }
}

struct Sequential;
impl Joiner for Sequential {
    #[inline]
    fn is_parallel() -> bool {
        false
    }
    #[inline]
    fn join<A,R_A,B,R_B>(oper_a: A, oper_b: B) -> (R_A, R_B)
        where A: FnOnce() -> R_A + Send, B: FnOnce() -> R_B + Send
    {
        let a = oper_a();
        let b = oper_b();
        (a, b)
    }
}

fn quick_sort<J:Joiner, T:PartialOrd+Send>(v: &mut [T]) {
    if v.len() <= 1 {
        return;
    }

    if J::is_parallel() && v.len() <= 10*1024 {
        return quick_sort::<Sequential, T>(v);
    }

    let mid = partition(v);
    let (lo, hi) = v.split_at_mut(mid);
    J::join(|| quick_sort::<J,T>(lo),
            || quick_sort::<J,T>(hi));
}

fn partition<T:PartialOrd+Send>(v: &mut [T]) -> usize {
    let pivot = v.len() - 1;
    let mut i = 0;
    for j in 0..pivot {
        if v[j] <= v[pivot] {
            v.swap(i, j);
            i += 1;
        }
    }
    v.swap(i, pivot);
    i
}

fn main() {
    let mut kilo = 24;
    let mut run_par = true;
    let mut run_seq = true;
    let mut reps = 10;

    let mut args = env::args().skip(1);
    while let Some(arg) = args.next() {
        if arg == "--no-par" {
            run_par = false;
        } else if arg == "--no-seq" {
            run_seq = false;
        } else if arg == "--reps" {
            if let Some(reps_arg) = args.next() {
                match usize::from_str(&reps_arg) {
                    Ok(v) => reps = v,
                    Err(_) => {
                        println!("invalid argument `{}`, expected integer", reps_arg);
                    }
                }
            } else {
                println!("missing argument to --reps");
            }
        } else {
            match usize::from_str(&arg) {
                Ok(v) => kilo = v,
                Err(_) => {
                    println!("invalid argument `{}`, expected integer", arg);
                }
            }
        }
    }

    let mut rng = XorShiftRng::from_seed([0, 1, 2, 3]);
    let mut par_time = 0;
    let mut seq_time = 0;

    rayon::initialize();

    for _ in 0 .. reps {
        let data: Vec<_> = (0..kilo*1024).map(|_| rng.next_u32()).collect();

        if run_par {
            let mut data = data.clone();
            let par_start = time::precise_time_ns();
            quick_sort::<Parallel, u32>(&mut data);
            par_time += time::precise_time_ns() - par_start;
        }

        if run_seq {
            let mut data = data.clone();
            let seq_start = time::precise_time_ns();
            quick_sort::<Sequential, u32>(&mut data);
            seq_time += time::precise_time_ns() - seq_start;
        }
    }

    println!("Array length    : {}K 32-bit integers", kilo);
    println!("Repetitions     : {}", reps);
    if run_par { println!("Parallel time   : {}", par_time); }
    if run_seq { println!("Sequential time : {}", seq_time); }
    if run_par && run_seq {
        println!("Parallel speedup: {}", (seq_time as f64) / (par_time as f64));
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2017-2019 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 * option. This file may not be copied, modified, or distributed
 * except according to those terms.
 */

use std::{io, net::SocketAddr};

use tokio::net::tcp::TcpStream;
use tokio_util::codec::{Decoder, Framed};

use crate::resp;

pub type RespConnection = Framed<TcpStream, resp::RespCodec>;

/// Connect to a Redis server and return a Future that resolves to a
/// `RespConnection` for reading and writing asynchronously.
///
/// Each `RespConnection` implements both `Sink` and `Stream` and read and
/// writes `RESP` objects.
///
/// This is a low-level interface to enable the creation of higher-level
/// functionality.
///
/// The sink and stream sides behave independently of each other, it is the
/// responsibility of the calling application to determine what results are
/// paired to a particular command.
///
/// But since most Redis usages involve issue commands that result in one
/// single result, this library also implements `paired_connect`.
pub async fn connect(addr: &SocketAddr) -> Result<RespConnection, io::Error> {
    let tcp_stream = TcpStream::connect(addr).await?;
    Ok(resp::RespCodec.framed(tcp_stream))
}

#[cfg(test)]
mod test {
    use futures_util::{
        sink::SinkExt,
        stream::{self, StreamExt},
    };

    use crate::resp;

    #[tokio::test]
    async fn can_connect() {
        let addr = "127.0.0.1:6379".parse().unwrap();

        let mut connection = super::connect(&addr).await.expect("Cannot connect");
        connection
            .send(resp_array!["PING", "TEST"])
            .await
            .expect("Cannot send PING");
        let values: Vec<_> = connection
            .take(1)
            .map(|r| r.expect("Unexpected invalid data"))
            .collect()
            .await;

        assert_eq!(values.len(), 1);
        assert_eq!(values[0], "TEST".into());
    }

    // #[tokio::test]
    // async fn complex_test() {
    //     let addr = "127.0.0.1:6379".parse().unwrap();

    //     let mut connection = super::connect(&addr).await.expect("Cannot connect");
    //     let mut ops = Vec::new();
    //     ops.push(resp_array!["FLUSH"]);
    //     ops.extend((0..1000).map(|i| resp_array!["SADD", "test_set", format!("VALUE: {}", i)]));
    //     ops.push(resp_array!["SMEMBERS", "test_set"]);
    //     let mut ops_stream = stream::iter(ops);
    //     connection
    //         .send_all(&mut ops_stream)
    //         .await
    //         .expect("Cannot send");
    //     let values: Vec<_> = connection
    //         .skip(1001)
    //         .take(1)
    //         .map(|r| r.expect("Unexpected invalid data"))
    //         .collect()
    //         .await;

    //     assert_eq!(values.len(), 1);
    //     let values = match &values[0] {
    //         resp::RespValue::Array(ref values) => values.clone(),
    //         _ => panic!("Not an array"),
    //     };
    //     assert_eq!(values.len(), 1000);
    // }
}
<commit_msg>Update for the final released futures<commit_after>/*
 * Copyright 2017-2019 Ben Ashford
 *
 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
 * http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
 * <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 * option. This file may not be copied, modified, or distributed
 * except according to those terms.
 */

use std::{io, net::SocketAddr};

use tokio::net::tcp::TcpStream;
use tokio_util::codec::{Decoder, Framed};

use crate::resp;

pub type RespConnection = Framed<TcpStream, resp::RespCodec>;

/// Connect to a Redis server and return a Future that resolves to a
/// `RespConnection` for reading and writing asynchronously.
///
/// Each `RespConnection` implements both `Sink` and `Stream` and read and
/// writes `RESP` objects.
///
/// This is a low-level interface to enable the creation of higher-level
/// functionality.
///
/// The sink and stream sides behave independently of each other, it is the
/// responsibility of the calling application to determine what results are
/// paired to a particular command.
///
/// But since most Redis usages involve issue commands that result in one
/// single result, this library also implements `paired_connect`.
pub async fn connect(addr: &SocketAddr) -> Result<RespConnection, io::Error> {
    let tcp_stream = TcpStream::connect(addr).await?;
    Ok(resp::RespCodec.framed(tcp_stream))
}

#[cfg(test)]
mod test {
    use futures_util::{
        sink::SinkExt,
        stream::{self, StreamExt},
    };

    use crate::resp;

    #[tokio::test]
    async fn can_connect() {
        let addr = "127.0.0.1:6379".parse().unwrap();

        let mut connection = super::connect(&addr).await.expect("Cannot connect");
        connection
            .send(resp_array!["PING", "TEST"])
            .await
            .expect("Cannot send PING");
        let values: Vec<_> = connection
            .take(1)
            .map(|r| r.expect("Unexpected invalid data"))
            .collect()
            .await;

        assert_eq!(values.len(), 1);
        assert_eq!(values[0], "TEST".into());
    }

    #[tokio::test]
    async fn complex_test() {
        let addr = "127.0.0.1:6379".parse().unwrap();

        let mut connection = super::connect(&addr).await.expect("Cannot connect");
        let mut ops = Vec::new();
        ops.push(resp_array!["FLUSH"]);
        ops.extend((0..1000).map(|i| resp_array!["SADD", "test_set", format!("VALUE: {}", i)]));
        ops.push(resp_array!["SMEMBERS", "test_set"]);
        let mut ops_stream = stream::iter(ops).map(|o| Ok(o));
        connection
            .send_all(&mut ops_stream)
            .await
            .expect("Cannot send");
        let values: Vec<_> = connection
            .skip(1001)
            .take(1)
            .map(|r| r.expect("Unexpected invalid data"))
            .collect()
            .await;

        assert_eq!(values.len(), 1);
        let values = match &values[0] {
            resp::RespValue::Array(ref values) => values.clone(),
            _ => panic!("Not an array"),
        };
        assert_eq!(values.len(), 1000);
    }
}
<|endoftext|>


<commit_before>use ::position::Positional;
use super::annotations::{ Annotated
                        , ScopednessTypestate
                        };
use super::types::Type;
use std::rc::Rc;

pub type Ident = Positional<String>;

pub type Expr<'a, S: ScopednessTypestate>
    = Rc<Annotated< 'a
                  , Form<'a, S>
                  , S>>;

pub type Body<'a, S: ScopednessTypestate> = Vec<Expr<'a, S>>;

pub type Bindings<'a, S: ScopednessTypestate>
    = Vec<Annotated< 'a
                   , Binding<'a, S>
                   , S>>;

#[derive(PartialEq, Clone, Debug)]
pub enum Form<'a, S: ScopednessTypestate> {
    Define(DefForm<'a, S>)
  , If { condition: Expr<'a, S>
       , if_clause: Expr<'a, S>
       , else_clause: Option<Expr<'a, S>>
       }
  , Let(LetForm<'a, S>)
  , Call { fun: Ident
         , body: Body<'a, S>
         }
  , Lambda(Function<'a, S>)
}

#[derive(PartialEq, Clone, Debug)]
pub struct Formal { pub name: Ident
                  , pub annot: Ident
                  }

#[derive(PartialEq, Clone, Debug)]
pub enum DefForm<'a, S: ScopednessTypestate> {
    TopLevel { name: Ident
             , annot: Ident
             , value: Expr<'a, S>
             }
  , Function { name: Ident
             , fun: Function<'a,S>
             }
}

#[derive(PartialEq, Clone, Debug)]
pub enum LetForm<'a, S: ScopednessTypestate> {
    Let { bindings: Bindings<'a, S>
        , body: Body<'a, S>
        }
  , Invocation { proc_id: Ident
               , init: Binding<'a, S>
               , body: Body<'a, S>
               }
  , LetRec { bindings: Bindings<'a, S>
           , body: Body<'a, S>
           }
  , LetSplat { bindings: Bindings<'a, S>
             , body: Body<'a, S>
             }

}

#[derive(PartialEq, Clone, Debug)]
pub struct Binding<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub typ: Type
  , pub value: Expr<'a, S>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Function<'a, S: ScopednessTypestate> {
    pub formals: Vec<Annotated<'a, Formal, S>>
  , pub annot: Ident
  , pub body: Body<'a, S>
}
<commit_msg>Factored out heap allocation from types that go in vectors This is because elements in vectors are already on the heap. Moved the RC-nature to only places where there are single Exprs.<commit_after>use ::position::Positional;
use super::annotations::{ Annotated
                        , ScopednessTypestate
                        };
use super::types::Type;
use std::rc::Rc;

pub type Ident = Positional<String>;

pub type Expr<'a, S: ScopednessTypestate>
    = Annotated< 'a
                , Form<'a, S>
                , S>;

pub type Body<'a, S: ScopednessTypestate> = Vec<Expr<'a, S>>;

pub type Bindings<'a, S: ScopednessTypestate>
    = Vec<Annotated< 'a
                   , Binding<'a, S>
                   , S>>;

#[derive(PartialEq, Clone, Debug)]
pub enum Form<'a, S: ScopednessTypestate> {
    Define(DefForm<'a, S>)
  , If { condition: Rc<Expr<'a, S>>
       , if_clause: Rc<Expr<'a, S>>
       , else_clause: Option<Rc<Expr<'a, S>>>
       }
  , Let(LetForm<'a, S>)
  , Call { fun: Ident
         , body: Body<'a, S>
         }
  , Lambda(Function<'a, S>)
}

#[derive(PartialEq, Clone, Debug)]
pub struct Formal { pub name: Ident
                  , pub annot: Ident
                  }

#[derive(PartialEq, Clone, Debug)]
pub enum DefForm<'a, S: ScopednessTypestate> {
    TopLevel { name: Ident
             , annot: Ident
             , value: Rc<Expr<'a, S>>
             }
  , Function { name: Ident
             , fun: Function<'a,S>
             }
}

#[derive(PartialEq, Clone, Debug)]
pub enum LetForm<'a, S: ScopednessTypestate> {
    Let { bindings: Bindings<'a, S>
        , body: Body<'a, S>
        }
  , Invocation { proc_id: Ident
               , init: Binding<'a, S>
               , body: Body<'a, S>
               }
  , LetRec { bindings: Bindings<'a, S>
           , body: Body<'a, S>
           }
  , LetSplat { bindings: Bindings<'a, S>
             , body: Body<'a, S>
             }

}

#[derive(PartialEq, Clone, Debug)]
pub struct Binding<'a, S: ScopednessTypestate> {
    pub name: Ident
  , pub typ: Type
  , pub value: Rc<Expr<'a, S>>
}

#[derive(PartialEq, Clone, Debug)]
pub struct Function<'a, S: ScopednessTypestate> {
    pub formals: Vec<Annotated<'a, Formal, S>>
  , pub annot: Ident
  , pub body: Body<'a, S>
}
<|endoftext|>


<commit_before>use cocoa::base::{YES, id, nil};
use cocoa::foundation::NSString;
use drawable::_drawable_get_id;
use std::borrow::Cow;
use std::convert::AsRef;
use std::ffi::CStr;
#[cfg(feature = "time2")]
use std::time::Instant;
use sys::{MTLCommandBuffer, MTLCommandBufferStatus};
use Drawable;

pub struct CommandBuffer(id);

pub struct CommandQueueRef;

impl CommandBuffer {
    pub fn enqueue(&mut self) {
        unsafe { self.0.enqueue() }
    }

    pub fn commit(&mut self) {
        unsafe { self.0.commit() }
    }

    pub fn present_drawable(&mut self, drawable: Drawable) {
        unsafe { self.0.presentDrawable(_drawable_get_id(&drawable)) }
    }

    #[cfg(feature = "time2")]
    pub fn present_drawable_at_time(&mut self, drawable: &mut Drawable, time: Instant) {
        unsafe { self.0.presentDrawable(_drawable_get_id(&drawable), time.elapsed().as_seconds()) }
    }

    pub fn present_drawable_at_time_secs(&mut self, drawable: &mut Drawable, time: f64) {
        unsafe { self.0.presentDrawable_atTime(_drawable_get_id(&drawable), time) }
    }

    pub fn wait_until_scheduled(&mut self) {
        unsafe { self.0.waitUntilScheduled() }
    }

    pub fn wait_until_completed(&mut self) {
        unsafe { self.0.waitUntilCompleted() }
    }

    pub fn get_status(&self) -> CommandBufferStatus {
        unsafe { self.0.status().into() }
    }

    pub fn get_error(&self) -> id {
        unsafe { self.0.error() }
    }

    pub fn has_retained_references(&self) -> bool {
        unsafe { self.0.retainedReferences() == YES }
    }

    pub fn get_command_queue(&self) -> CommandQueueRef {
        unimplemented!();
    }

    pub fn set_label<S: AsRef<str>>(&mut self, label: S) {
        unsafe { MTLCommandBuffer::setLabel(self.0, NSString::alloc(nil).init_str(label.as_ref())) }
    }

    pub fn get_label(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(MTLCommandBuffer::label(self.0).UTF8String()).to_string_lossy() }
    }
}

/// Internal utility function to create a CommandQueue without exposing internals.
/// Not exported publicly from this crate.
#[doc(hidden)]
pub fn _make_command_buffer(command_buffer: id) -> CommandBuffer {
    CommandBuffer(command_buffer)
}

#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub enum CommandBufferStatus {
    CommandBufferStatusNotEnqueued,
    CommandBufferStatusEnqueued,
    CommandBufferStatusCommitted,
    CommandBufferStatusScheduled,
    CommandBufferStatusCompleted,
    CommandBufferStatusError
}

impl From<MTLCommandBufferStatus> for CommandBufferStatus {
    fn from(mtl_status: MTLCommandBufferStatus) -> Self {
        match mtl_status {
            MTLCommandBufferStatus::MTLCommandBufferStatusNotEnqueued =>
                CommandBufferStatus::CommandBufferStatusNotEnqueued,
            MTLCommandBufferStatus::MTLCommandBufferStatusEnqueued =>
                CommandBufferStatus::CommandBufferStatusEnqueued,
            MTLCommandBufferStatus::MTLCommandBufferStatusCommitted =>
                CommandBufferStatus::CommandBufferStatusCommitted,
            MTLCommandBufferStatus::MTLCommandBufferStatusScheduled =>
                CommandBufferStatus::CommandBufferStatusScheduled,
            MTLCommandBufferStatus::MTLCommandBufferStatusCompleted =>
                CommandBufferStatus::CommandBufferStatusCompleted,
            MTLCommandBufferStatus::MTLCommandBufferStatusError =>
                CommandBufferStatus::CommandBufferStatusError,
        }
    }
}

impl Into<MTLCommandBufferStatus> for CommandBufferStatus {
    fn into(self) -> MTLCommandBufferStatus {
        match self {
            CommandBufferStatus::CommandBufferStatusNotEnqueued =>
                MTLCommandBufferStatus::MTLCommandBufferStatusNotEnqueued,
            CommandBufferStatus::CommandBufferStatusEnqueued =>
                MTLCommandBufferStatus::MTLCommandBufferStatusEnqueued,
            CommandBufferStatus::CommandBufferStatusCommitted =>
                MTLCommandBufferStatus::MTLCommandBufferStatusCommitted,
            CommandBufferStatus::CommandBufferStatusScheduled =>
                MTLCommandBufferStatus::MTLCommandBufferStatusScheduled,
            CommandBufferStatus::CommandBufferStatusCompleted =>
                MTLCommandBufferStatus::MTLCommandBufferStatusCompleted,
            CommandBufferStatus::CommandBufferStatusError =>
                MTLCommandBufferStatus::MTLCommandBufferStatusError,
        }
    }
}
<commit_msg>Remove CommandQueueRef; it's not needed<commit_after>use cocoa::base::{YES, id, nil};
use cocoa::foundation::NSString;
use drawable::_drawable_get_id;
use std::borrow::Cow;
use std::convert::AsRef;
use std::ffi::CStr;
#[cfg(feature = "time2")]
use std::time::Instant;
use sys::{MTLCommandBuffer, MTLCommandBufferStatus};
use Drawable;

pub struct CommandBuffer(id);

impl CommandBuffer {
    pub fn enqueue(&mut self) {
        unsafe { self.0.enqueue() }
    }

    pub fn commit(&mut self) {
        unsafe { self.0.commit() }
    }

    pub fn present_drawable(&mut self, drawable: Drawable) {
        unsafe { self.0.presentDrawable(_drawable_get_id(&drawable)) }
    }

    #[cfg(feature = "time2")]
    pub fn present_drawable_at_time(&mut self, drawable: &mut Drawable, time: Instant) {
        unsafe { self.0.presentDrawable(_drawable_get_id(&drawable), time.elapsed().as_seconds()) }
    }

    pub fn present_drawable_at_time_secs(&mut self, drawable: &mut Drawable, time: f64) {
        unsafe { self.0.presentDrawable_atTime(_drawable_get_id(&drawable), time) }
    }

    pub fn wait_until_scheduled(&mut self) {
        unsafe { self.0.waitUntilScheduled() }
    }

    pub fn wait_until_completed(&mut self) {
        unsafe { self.0.waitUntilCompleted() }
    }

    pub fn get_status(&self) -> CommandBufferStatus {
        unsafe { self.0.status().into() }
    }

    pub fn get_error(&self) -> id {
        unsafe { self.0.error() }
    }

    pub fn has_retained_references(&self) -> bool {
        unsafe { self.0.retainedReferences() == YES }
    }

    pub fn set_label<S: AsRef<str>>(&mut self, label: S) {
        unsafe { MTLCommandBuffer::setLabel(self.0, NSString::alloc(nil).init_str(label.as_ref())) }
    }

    pub fn get_label(&self) -> Cow<str> {
        unsafe { CStr::from_ptr(MTLCommandBuffer::label(self.0).UTF8String()).to_string_lossy() }
    }
}

/// Internal utility function to create a CommandQueue without exposing internals.
/// Not exported publicly from this crate.
#[doc(hidden)]
pub fn _make_command_buffer(command_buffer: id) -> CommandBuffer {
    CommandBuffer(command_buffer)
}

#[derive(Clone, Copy, Eq, Hash, PartialEq)]
pub enum CommandBufferStatus {
    CommandBufferStatusNotEnqueued,
    CommandBufferStatusEnqueued,
    CommandBufferStatusCommitted,
    CommandBufferStatusScheduled,
    CommandBufferStatusCompleted,
    CommandBufferStatusError
}

impl From<MTLCommandBufferStatus> for CommandBufferStatus {
    fn from(mtl_status: MTLCommandBufferStatus) -> Self {
        match mtl_status {
            MTLCommandBufferStatus::MTLCommandBufferStatusNotEnqueued =>
                CommandBufferStatus::CommandBufferStatusNotEnqueued,
            MTLCommandBufferStatus::MTLCommandBufferStatusEnqueued =>
                CommandBufferStatus::CommandBufferStatusEnqueued,
            MTLCommandBufferStatus::MTLCommandBufferStatusCommitted =>
                CommandBufferStatus::CommandBufferStatusCommitted,
            MTLCommandBufferStatus::MTLCommandBufferStatusScheduled =>
                CommandBufferStatus::CommandBufferStatusScheduled,
            MTLCommandBufferStatus::MTLCommandBufferStatusCompleted =>
                CommandBufferStatus::CommandBufferStatusCompleted,
            MTLCommandBufferStatus::MTLCommandBufferStatusError =>
                CommandBufferStatus::CommandBufferStatusError,
        }
    }
}

impl Into<MTLCommandBufferStatus> for CommandBufferStatus {
    fn into(self) -> MTLCommandBufferStatus {
        match self {
            CommandBufferStatus::CommandBufferStatusNotEnqueued =>
                MTLCommandBufferStatus::MTLCommandBufferStatusNotEnqueued,
            CommandBufferStatus::CommandBufferStatusEnqueued =>
                MTLCommandBufferStatus::MTLCommandBufferStatusEnqueued,
            CommandBufferStatus::CommandBufferStatusCommitted =>
                MTLCommandBufferStatus::MTLCommandBufferStatusCommitted,
            CommandBufferStatus::CommandBufferStatusScheduled =>
                MTLCommandBufferStatus::MTLCommandBufferStatusScheduled,
            CommandBufferStatus::CommandBufferStatusCompleted =>
                MTLCommandBufferStatus::MTLCommandBufferStatusCompleted,
            CommandBufferStatus::CommandBufferStatusError =>
                MTLCommandBufferStatus::MTLCommandBufferStatusError,
        }
    }
}
<|endoftext|>


<commit_before>use super::printing;

pub fn next() {
    printing::heading("Follow feeds so that I'm aware of industry changes.");

    printing::subheading("Open the top recent items in each feed");

    printing::subheading("Programming");
    printing::list(vec![
        "https://www.reddit.com/r/programming/top/?t=month",
        "https://github.com/trending?since=monthly",
    ]);

    printing::subheading("Unix");
    printing::list(vec![
        "https://brew.sh/blog",
        "https://www.reddit.com/r/commandline/top/?t=month",
    ]);

    printing::subheading("Vim");
    printing::list(vec![
        "https://www.vim.org/news/news.php",
        "https://www.reddit.com/r/vim/top/?t=month",
    ]);

    printing::subheading("Git");
    printing::list(vec!["https://www.reddit.com/r/git/top/?t=month"]);

    printing::subheading("Rust");
    printing::list(vec![
        "https://blog.rust-lang.org",
        "https://www.reddit.com/r/rust/top/?t=month",
    ]);

    printing::subheading("JavaScript");
    printing::list(vec!["https://www.reddit.com/r/javascript/top/?t=month"]);
    printing::list(vec!["https://nodejs.org/en/blog/"]);
    printing::list(vec!["https://www.reddit.com/r/node/top/?t=month"]);
    printing::list(vec!["https://reactjs.org/blog/all.html"]);
    printing::list(vec!["https://nextjs.org/blog"]);

    printing::pause();
}
<commit_msg>Fix javascript study list<commit_after>use super::printing;

pub fn next() {
    printing::heading("Follow feeds so that I'm aware of industry changes.");

    printing::subheading("Open the top recent items in each feed");

    printing::subheading("Programming");
    printing::list(vec![
        "https://www.reddit.com/r/programming/top/?t=month",
        "https://github.com/trending?since=monthly",
    ]);

    printing::subheading("Unix");
    printing::list(vec![
        "https://brew.sh/blog",
        "https://www.reddit.com/r/commandline/top/?t=month",
    ]);

    printing::subheading("Vim");
    printing::list(vec![
        "https://www.vim.org/news/news.php",
        "https://www.reddit.com/r/vim/top/?t=month",
    ]);

    printing::subheading("Git");
    printing::list(vec!["https://www.reddit.com/r/git/top/?t=month"]);

    printing::subheading("Rust");
    printing::list(vec![
        "https://blog.rust-lang.org",
        "https://www.reddit.com/r/rust/top/?t=month",
    ]);

    printing::subheading("JavaScript");
    printing::list(vec![
        "https://www.reddit.com/r/javascript/top/?t=month",
        "https://nodejs.org/en/blog/",
        "https://www.reddit.com/r/node/top/?t=month",
        "https://reactjs.org/blog/all.html",
        "https://nextjs.org/blog",
    ]);

    printing::pause();
}
<|endoftext|>


<commit_before>
extern crate ndarray;
extern crate ndarray_odeint;
extern crate ndarray_linalg;
extern crate itertools;

use ndarray::*;
use ndarray_linalg::prelude::*;
use ndarray_odeint::prelude::*;
use ndarray_odeint::lyapunov::*;
use itertools::iterate;

fn main() {
    let dt = 0.01;
    let eom = Lorenz63::default();
    let teo = explicit::rk4(eom, dt);
    let ts = iterate(rcarr1(&[1.0, 0.0, 0.0]), |y| teo.iterate(y.clone()));
    let qr_series = ts.scan(Array::eye(3), |st, x| {
        let j = teo.jacobian(x.clone(), 1e-7);
        let (q_next, r) = j.dot(st).qr().unwrap();
        let q = std::mem::replace(st, q_next);
        Some((q, r))
    });
    let duration = 100000;
    let mut l = arr1(&[0.0, 0.0, 0.0]);
    for (_, r) in qr_series.skip(duration / 10).take(duration) {
        l = l + r.diag().map(|x| x.abs().ln());
    }
    println!("{:?}", l / (dt * duration as f64));
}
<commit_msg>Rewrite sample using iterator<commit_after>
extern crate ndarray;
extern crate ndarray_odeint;
extern crate ndarray_linalg;
extern crate itertools;

use ndarray::*;
use ndarray_linalg::prelude::*;
use ndarray_odeint::prelude::*;
use ndarray_odeint::lyapunov::*;
use itertools::iterate;

fn main() {
    let dt = 0.01;
    let eom = Lorenz63::default();
    let teo = explicit::rk4(eom, dt);
    let ts = iterate(rcarr1(&[1.0, 0.0, 0.0]), |y| teo.iterate(y.clone()));
    let qr_series = ts.scan(Array::eye(3), |st, x| {
        let j = teo.jacobian(x.clone(), 1e-7);
        let (q_next, r) = j.dot(st).qr().unwrap();
        let q = std::mem::replace(st, q_next);
        Some((q, r))
    });
    let duration = 100000;
    let exponents = qr_series.map(|(_, r)| r.diag().map(|x| x.abs().ln()))
        .skip(duration / 10)
        .take(duration)
        .fold(Array::zeros(3), |x, y| x + y) / (dt * duration as f64);
    println!("{:?}", exponents);
}
<|endoftext|>


<commit_before>//! HIR (previsouly known as descriptors) provides a high-level OO acess to Rust
//! code.
//!
//! The principal difference between HIR and syntax trees is that HIR is bound
//! to a particular crate instance. That is, it has cfg flags and features
//! applied. So, there relation between syntax and HIR is many-to-one.

macro_rules! ctry {
    ($expr:expr) => {
        match $expr {
            None => return Ok(None),
            Some(it) => it,
        }
    };
}

pub mod db;
#[cfg(test)]
mod mock;
mod query_definitions;
mod path;
mod arena;
pub mod source_binder;

mod krate;
mod module;
mod function;

use std::ops::Index;

use ra_syntax::{SyntaxNodeRef, SyntaxNode};
use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable};

use crate::{
    db::HirDatabase,
    arena::{Arena, Id},
};

pub use self::{
    path::{Path, PathKind},
    krate::Crate,
    module::{Module, ModuleId, Problem, nameres::ItemMap},
    function::{Function, FnScopes},
};

pub use self::function::FnSignatureInfo;

/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc)
/// in a specific module.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DefId(u32);
ra_db::impl_numeric_id!(DefId);

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) enum DefKind {
    Module,
    Function,
    Item,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct DefLoc {
    pub(crate) kind: DefKind,
    source_root_id: SourceRootId,
    module_id: ModuleId,
    source_item_id: SourceItemId,
}

impl DefId {
    pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
        db.as_ref().id2loc(self)
    }
}

impl DefLoc {
    pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
        db.as_ref().loc2id(&self)
    }
}

pub enum Def {
    Module(Module),
    Function(Function),
    Item,
}

impl DefId {
    pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
        let loc = self.loc(db);
        let res = match loc.kind {
            DefKind::Module => {
                let module = Module::new(db, loc.source_root_id, loc.module_id)?;
                Def::Module(module)
            }
            DefKind::Function => {
                let function = Function::new(self);
                Def::Function(function)
            }
            DefKind::Item => Def::Item,
        };
        Ok(res)
    }
}

/// Identifier of item within a specific file. This is stable over reparses, so
/// it's OK to use it as a salsa key/value.
pub(crate) type SourceFileItemId = Id<SyntaxNode>;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SourceItemId {
    file_id: FileId,
    item_id: SourceFileItemId,
}

/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
#[derive(Debug, PartialEq, Eq)]
pub struct SourceFileItems {
    file_id: FileId,
    arena: Arena<SyntaxNode>,
}

impl SourceFileItems {
    fn new(file_id: FileId) -> SourceFileItems {
        SourceFileItems {
            file_id,
            arena: Arena::default(),
        }
    }

    fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
        self.arena.alloc(item)
    }
    pub fn id_of(&self, file_id: FileId, item: SyntaxNodeRef) -> SourceFileItemId {
        assert_eq!(
            self.file_id, file_id,
            "SourceFileItems: wrong file, expected {:?}, got {:?}",
            self.file_id, file_id
        );
        self.id_of_unchecked(item)
    }
    fn id_of_unchecked(&self, item: SyntaxNodeRef) -> SourceFileItemId {
        let (id, _item) = self
            .arena
            .iter()
            .find(|(_id, i)| i.borrowed() == item)
            .unwrap();
        id
    }
    pub fn id_of_source_file(&self) -> SourceFileItemId {
        let (id, _syntax) = self.arena.iter().next().unwrap();
        id
    }
}

impl Index<SourceFileItemId> for SourceFileItems {
    type Output = SyntaxNode;
    fn index(&self, idx: SourceFileItemId) -> &SyntaxNode {
        &self.arena[idx]
    }
}
<commit_msg>verbose assertions in SourceFileItems<commit_after>//! HIR (previsouly known as descriptors) provides a high-level OO acess to Rust
//! code.
//!
//! The principal difference between HIR and syntax trees is that HIR is bound
//! to a particular crate instance. That is, it has cfg flags and features
//! applied. So, there relation between syntax and HIR is many-to-one.

macro_rules! ctry {
    ($expr:expr) => {
        match $expr {
            None => return Ok(None),
            Some(it) => it,
        }
    };
}

pub mod db;
#[cfg(test)]
mod mock;
mod query_definitions;
mod path;
mod arena;
pub mod source_binder;

mod krate;
mod module;
mod function;

use std::ops::Index;

use ra_syntax::{SyntaxNodeRef, SyntaxNode};
use ra_db::{LocationIntener, SourceRootId, FileId, Cancelable};

use crate::{
    db::HirDatabase,
    arena::{Arena, Id},
};

pub use self::{
    path::{Path, PathKind},
    krate::Crate,
    module::{Module, ModuleId, Problem, nameres::ItemMap},
    function::{Function, FnScopes},
};

pub use self::function::FnSignatureInfo;

/// Def's are a core concept of hir. A `Def` is an Item (function, module, etc)
/// in a specific module.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct DefId(u32);
ra_db::impl_numeric_id!(DefId);

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) enum DefKind {
    Module,
    Function,
    Item,
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct DefLoc {
    pub(crate) kind: DefKind,
    source_root_id: SourceRootId,
    module_id: ModuleId,
    source_item_id: SourceItemId,
}

impl DefId {
    pub(crate) fn loc(self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefLoc {
        db.as_ref().id2loc(self)
    }
}

impl DefLoc {
    pub(crate) fn id(&self, db: &impl AsRef<LocationIntener<DefLoc, DefId>>) -> DefId {
        db.as_ref().loc2id(&self)
    }
}

pub enum Def {
    Module(Module),
    Function(Function),
    Item,
}

impl DefId {
    pub fn resolve(self, db: &impl HirDatabase) -> Cancelable<Def> {
        let loc = self.loc(db);
        let res = match loc.kind {
            DefKind::Module => {
                let module = Module::new(db, loc.source_root_id, loc.module_id)?;
                Def::Module(module)
            }
            DefKind::Function => {
                let function = Function::new(self);
                Def::Function(function)
            }
            DefKind::Item => Def::Item,
        };
        Ok(res)
    }
}

/// Identifier of item within a specific file. This is stable over reparses, so
/// it's OK to use it as a salsa key/value.
pub(crate) type SourceFileItemId = Id<SyntaxNode>;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SourceItemId {
    file_id: FileId,
    item_id: SourceFileItemId,
}

/// Maps item's `SyntaxNode`s to `SourceFileItemId` and back.
#[derive(Debug, PartialEq, Eq)]
pub struct SourceFileItems {
    file_id: FileId,
    arena: Arena<SyntaxNode>,
}

impl SourceFileItems {
    fn new(file_id: FileId) -> SourceFileItems {
        SourceFileItems {
            file_id,
            arena: Arena::default(),
        }
    }

    fn alloc(&mut self, item: SyntaxNode) -> SourceFileItemId {
        self.arena.alloc(item)
    }
    pub fn id_of(&self, file_id: FileId, item: SyntaxNodeRef) -> SourceFileItemId {
        assert_eq!(
            self.file_id, file_id,
            "SourceFileItems: wrong file, expected {:?}, got {:?}",
            self.file_id, file_id
        );
        self.id_of_unchecked(item)
    }
    fn id_of_unchecked(&self, item: SyntaxNodeRef) -> SourceFileItemId {
        if let Some((id, _)) = self.arena.iter().find(|(_id, i)| i.borrowed() == item) {
            return id;
        }
        // This should not happen. Let's try to give a sensible diagnostics.
        if let Some((_, i)) = self.arena.iter().find(|(_id, i)| i.range() == item.range()) {
            panic!(
                "unequal syntax nodes with the same range:\n{:?}\n{:?}",
                item, i
            )
        }
        panic!(
            "Can't find {:?} in SourceFileItems:\n{:?}",
            item,
            self.arena.iter().map(|(_id, i)| i).collect::<Vec<_>>(),
        );
    }
    pub fn id_of_source_file(&self) -> SourceFileItemId {
        let (id, _syntax) = self.arena.iter().next().unwrap();
        id
    }
}

impl Index<SourceFileItemId> for SourceFileItems {
    type Output = SyntaxNode;
    fn index(&self, idx: SourceFileItemId) -> &SyntaxNode {
        &self.arena[idx]
    }
}
<|endoftext|>


<commit_before>use std::borrow::ToOwned;
use std::env;
use std::error::Error;
use std::fmt;
use std::fs;
use std::io::{Read,Write};
use std::io;
use std::path;
use std::process;

use clap::{Arg,App,SubCommand,AppSettings};
use atomicwrites::{AtomicFile,AllowOverwrite};

use utils;
use utils::CustomPathExt;

#[inline]
fn get_pwd() -> path::PathBuf {
    env::current_dir().ok().expect("Failed to get CWD")
}

#[inline]
fn get_envvar(key: &str) -> Option<String> {
    match env::var(key) {
        Ok(x) => Some(x),
        Err(env::VarError::NotPresent) => None,
        Err(env::VarError::NotUnicode(_)) => panic!(format!("{} is not unicode.", key)),
    }
}

fn build_index(outfile: &path::Path, dir: &path::Path) -> MainResult<()> {
    if !dir.is_dir() {
        return Err(MainError::new("MATES_DIR must be a directory.").into());
    };

    let af = AtomicFile::new(&outfile, AllowOverwrite);
    let mut errors = false;

    try!(af.write(|outf| {
        for entry in try!(fs::read_dir(dir)) {
            let entry = match entry {
                Ok(x) => x,
                Err(e) => {
                    println!("Error while listing directory: {}", e);
                    errors = true;
                    continue;
                }
            };

            let pathbuf = entry.path();

            if pathbuf.str_extension().unwrap_or("") != "vcf" || !pathbuf.is_file() {
                continue;
            };

            let contact = match utils::Contact::from_file(&pathbuf) {
                Ok(x) => x,
                Err(e) => {
                    println!("Error while reading {}: {}", pathbuf.display(), e);
                    errors = true;
                    continue
                }
            };

            match utils::index_item_from_contact(&contact) {
                Ok(index_string) => {
                    try!(outf.write_all(index_string.as_bytes()));
                },
                Err(e) => {
                    println!("Error while indexing {}: {}", pathbuf.display(), e);
                    errors = true;
                    continue
                }
            };
        };
        Ok(())
    }));

    if errors {
        Err(MainError::new("Several errors happened while generating the index.").into())
    } else {
        Ok(())
    }
}

pub fn cli_main() {
    match cli_main_raw() {
        Err(e) => {
            writeln!(&mut io::stderr(), "{}", e).unwrap();
            process::exit(1);
        },
        _ => ()
    };
}

pub fn cli_main_raw() -> MainResult<()> {
    let matches = App::new("mates")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Markus Unterwaditzer")
        .about("A simple commandline addressbook")
        .setting(AppSettings::SubcommandRequired)
        .subcommand(SubCommand::with_name("index")
                    .about("Rewrite/create the index"))
        .subcommand(SubCommand::with_name("mutt-query")
                    .about("Search for contact, output is usable for mutt's query_command.")
                    .arg(Arg::with_name("query").index(1)))
        .subcommand(SubCommand::with_name("file-query")
                    .about("Search for contact, return just the filename.")
                    .arg(Arg::with_name("query").index(1)))
        .subcommand(SubCommand::with_name("email-query")
                    .about("Search for contact, return \"name <email>\".")
                    .arg(Arg::with_name("query").index(1)))
        .subcommand(SubCommand::with_name("add")
                    .about("Take mail from stdin, add sender to contacts. Print filename."))
        .subcommand(SubCommand::with_name("edit")
                    .about(
                        "Open contact (given by filepath or search-string) in $MATES_EDITOR. If \
                        the file is cleared, the contact is removed. As a further convenience it \
                        also clears stdin, which is necessary for editors and most interactive \
                        programs to not act weird when piped to."
                    )
                    .arg(Arg::with_name("file-or-query").index(1)))
        .get_matches();

    let command = matches.subcommand_name().unwrap();

    let config = match Configuration::new() {
        Ok(x) => x,
        Err(e) => {
            return Err(MainError::new(format!("Error while reading configuration: {}", e)).into());
        }
    };

    let submatches = matches.subcommand_matches(command).expect("Internal error.");

    match command {
        "index" => {
            println!("Rebuilding index file \"{}\"...", config.index_path.display());
            try!(build_index(&config.index_path, &config.vdir_path));
        },
        "mutt-query" => {
            let query = submatches.value_of("query").unwrap_or("");
            try!(mutt_query(&config, &query[..]));
        },
        "file-query" => {
            let query = submatches.value_of("query").unwrap_or("");
            try!(file_query(&config, &query[..]));
        },
        "email-query" => {
            let query = submatches.value_of("query").unwrap_or("");
            try!(email_query(&config, &query[..]));
        },
        "add" => {
            let stdin = io::stdin();
            let mut email = String::new();
            try!(stdin.lock().read_to_string(&mut email));
            let contact = try!(utils::add_contact_from_email(
                &config.vdir_path,
                &email[..]
            ));
            println!("{}", contact.path.display());

            let mut index_fp = try!(fs::OpenOptions::new()
                                    .append(true)
                                    .write(true)
                                    .open(&config.index_path));

            let index_entry = try!(utils::index_item_from_contact(&contact));
            try!(index_fp.write_all(index_entry.as_bytes()));
        },
        "edit" => {
            let query = submatches.value_of("file-or-query").unwrap_or("");
            try!(edit_contact(&config, &query[..]));
        },
        _ => {
            return Err(MainError::new(format!("Invalid command: {}", command)).into());
        }
    };
    Ok(())
}

fn edit_contact(config: &Configuration, query: &str) -> MainResult<()> {
    let results = if get_pwd().join(query).is_file() {
        vec![path::PathBuf::from(query)]
    } else {
        try!(utils::file_query(config, query)).into_iter().collect()
    };

    if results.len() < 1 {
        return Err(MainError::new("No such contact.").into());
    } else if results.len() > 1 {
        return Err(MainError::new("Ambiguous query.").into());
    }

    let fpath = &results[0];
    let mut process = try!(process::Command::new("sh")
        .arg("-c")
        // clear stdin, http://unix.stackexchange.com/a/77593
        .arg("$0 \"$1\" < $2")
        .arg(&config.editor_cmd[..])
        .arg(fpath.as_os_str())
        .arg("/dev/tty")
        .stdin(process::Stdio::inherit())
        .stdout(process::Stdio::inherit())
        .stderr(process::Stdio::inherit())
        .spawn());

    try!(utils::handle_process(&mut process));

    let fcontent = {
        let mut fcontent = String::new();
        let mut file = try!(fs::File::open(fpath));
        try!(file.read_to_string(&mut fcontent));
        fcontent
    };

    if (&fcontent[..]).trim().len() == 0 {
        try!(fs::remove_file(fpath));
        return Err(MainError::new("Contact emptied, file removed.").into());
    };

    Ok(())
}

fn mutt_query<'a>(config: &Configuration, query: &str) -> MainResult<()> {
    println!("");  // For some reason mutt requires an empty line
    for item in try!(utils::index_query(config, query)) {
        if item.email.len() > 0 && item.name.len() > 0 {
            println!("{}\t{}", item.email, item.name);
        };
    };
    Ok(())
}

fn file_query<'a>(config: &Configuration, query: &str) -> MainResult<()> {
    for path in try!(utils::file_query(config, query)).iter() {
        println!("{}", path.display());
    };
    Ok(())
}

fn email_query<'a>(config: &Configuration, query: &str) -> MainResult<()> {
    for item in try!(utils::index_query(config, query)) {
        if item.name.len() > 0 && item.email.len() > 0 {
            println!("{} <{}>", item.name, item.email);
        };
    };
    Ok(())
}

pub struct Configuration {
    pub index_path: path::PathBuf,
    pub vdir_path: path::PathBuf,
    pub editor_cmd: String,
    pub grep_cmd: String
}

impl Configuration {
    pub fn new() -> Result<Configuration, String> {
        Ok(Configuration {
            index_path: match get_envvar("MATES_INDEX") {
                Some(x) => path::PathBuf::from(&x),
                None => match get_envvar("HOME") {
                    Some(home) => get_pwd().join(&home).join(".mates_index"),
                    None => return Err("Unable to determine user's home directory.".to_owned())
                }
            },
            vdir_path: match get_envvar("MATES_DIR") {
                Some(x) => path::PathBuf::from(&x),
                None => return Err("MATES_DIR must be set to your vdir path (directory of vcf-files).".to_owned())
            },
            editor_cmd: match get_envvar("MATES_EDITOR") {
                Some(x) => x,
                None => match get_envvar("EDITOR") {
                    Some(x) => x,
                    None => return Err("MATES_EDITOR or EDITOR must be set.".to_owned())
                }
            },
            grep_cmd: match get_envvar("MATES_GREP") {
                Some(x) => x,
                None => "grep -i".to_owned()
            }
        })
    }
}

#[derive(PartialEq, Eq, Debug)]
pub struct MainError {
    desc: String,
}

pub type MainResult<T> = Result<T, Box<Error>>;

impl Error for MainError {
    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl fmt::Display for MainError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.description().fmt(f)
    }
}

impl MainError {
    pub fn new<T: Into<String>>(desc: T) -> Self {
        MainError {
            desc: desc.into(),
        }
    }
}
<commit_msg>Avoid any error output for mutt queries<commit_after>use std::borrow::ToOwned;
use std::env;
use std::error::Error;
use std::fmt;
use std::fs;
use std::io::{Read,Write};
use std::io;
use std::path;
use std::process;

use clap::{Arg,App,SubCommand,AppSettings};
use atomicwrites::{AtomicFile,AllowOverwrite};

use utils;
use utils::CustomPathExt;

#[inline]
fn get_pwd() -> path::PathBuf {
    env::current_dir().ok().expect("Failed to get CWD")
}

#[inline]
fn get_envvar(key: &str) -> Option<String> {
    match env::var(key) {
        Ok(x) => Some(x),
        Err(env::VarError::NotPresent) => None,
        Err(env::VarError::NotUnicode(_)) => panic!(format!("{} is not unicode.", key)),
    }
}

fn build_index(outfile: &path::Path, dir: &path::Path) -> MainResult<()> {
    if !dir.is_dir() {
        return Err(MainError::new("MATES_DIR must be a directory.").into());
    };

    let af = AtomicFile::new(&outfile, AllowOverwrite);
    let mut errors = false;

    try!(af.write(|outf| {
        for entry in try!(fs::read_dir(dir)) {
            let entry = match entry {
                Ok(x) => x,
                Err(e) => {
                    println!("Error while listing directory: {}", e);
                    errors = true;
                    continue;
                }
            };

            let pathbuf = entry.path();

            if pathbuf.str_extension().unwrap_or("") != "vcf" || !pathbuf.is_file() {
                continue;
            };

            let contact = match utils::Contact::from_file(&pathbuf) {
                Ok(x) => x,
                Err(e) => {
                    println!("Error while reading {}: {}", pathbuf.display(), e);
                    errors = true;
                    continue
                }
            };

            match utils::index_item_from_contact(&contact) {
                Ok(index_string) => {
                    try!(outf.write_all(index_string.as_bytes()));
                },
                Err(e) => {
                    println!("Error while indexing {}: {}", pathbuf.display(), e);
                    errors = true;
                    continue
                }
            };
        };
        Ok(())
    }));

    if errors {
        Err(MainError::new("Several errors happened while generating the index.").into())
    } else {
        Ok(())
    }
}

pub fn cli_main() {
    match cli_main_raw() {
        Err(e) => {
            writeln!(&mut io::stderr(), "{}", e).unwrap();
            process::exit(1);
        },
        _ => ()
    };
}

pub fn cli_main_raw() -> MainResult<()> {
    let matches = App::new("mates")
        .version(env!("CARGO_PKG_VERSION"))
        .author("Markus Unterwaditzer")
        .about("A simple commandline addressbook")
        .setting(AppSettings::SubcommandRequired)
        .subcommand(SubCommand::with_name("index")
                    .about("Rewrite/create the index"))
        .subcommand(SubCommand::with_name("mutt-query")
                    .about("Search for contact, output is usable for mutt's query_command.")
                    .arg(Arg::with_name("query").index(1)))
        .subcommand(SubCommand::with_name("file-query")
                    .about("Search for contact, return just the filename.")
                    .arg(Arg::with_name("query").index(1)))
        .subcommand(SubCommand::with_name("email-query")
                    .about("Search for contact, return \"name <email>\".")
                    .arg(Arg::with_name("query").index(1)))
        .subcommand(SubCommand::with_name("add")
                    .about("Take mail from stdin, add sender to contacts. Print filename."))
        .subcommand(SubCommand::with_name("edit")
                    .about(
                        "Open contact (given by filepath or search-string) in $MATES_EDITOR. If \
                        the file is cleared, the contact is removed. As a further convenience it \
                        also clears stdin, which is necessary for editors and most interactive \
                        programs to not act weird when piped to."
                    )
                    .arg(Arg::with_name("file-or-query").index(1)))
        .get_matches();

    let command = matches.subcommand_name().unwrap();

    let config = match Configuration::new() {
        Ok(x) => x,
        Err(e) => {
            return Err(MainError::new(format!("Error while reading configuration: {}", e)).into());
        }
    };

    let submatches = matches.subcommand_matches(command).expect("Internal error.");

    match command {
        "index" => {
            println!("Rebuilding index file \"{}\"...", config.index_path.display());
            try!(build_index(&config.index_path, &config.vdir_path));
        },
        "mutt-query" => {
            let query = submatches.value_of("query").unwrap_or("");
            try!(mutt_query(&config, &query[..]));
        },
        "file-query" => {
            let query = submatches.value_of("query").unwrap_or("");
            try!(file_query(&config, &query[..]));
        },
        "email-query" => {
            let query = submatches.value_of("query").unwrap_or("");
            try!(email_query(&config, &query[..]));
        },
        "add" => {
            let stdin = io::stdin();
            let mut email = String::new();
            try!(stdin.lock().read_to_string(&mut email));
            let contact = try!(utils::add_contact_from_email(
                &config.vdir_path,
                &email[..]
            ));
            println!("{}", contact.path.display());

            let mut index_fp = try!(fs::OpenOptions::new()
                                    .append(true)
                                    .write(true)
                                    .open(&config.index_path));

            let index_entry = try!(utils::index_item_from_contact(&contact));
            try!(index_fp.write_all(index_entry.as_bytes()));
        },
        "edit" => {
            let query = submatches.value_of("file-or-query").unwrap_or("");
            try!(edit_contact(&config, &query[..]));
        },
        _ => {
            return Err(MainError::new(format!("Invalid command: {}", command)).into());
        }
    };
    Ok(())
}

fn edit_contact(config: &Configuration, query: &str) -> MainResult<()> {
    let results = if get_pwd().join(query).is_file() {
        vec![path::PathBuf::from(query)]
    } else {
        try!(utils::file_query(config, query)).into_iter().collect()
    };

    if results.len() < 1 {
        return Err(MainError::new("No such contact.").into());
    } else if results.len() > 1 {
        return Err(MainError::new("Ambiguous query.").into());
    }

    let fpath = &results[0];
    let mut process = try!(process::Command::new("sh")
        .arg("-c")
        // clear stdin, http://unix.stackexchange.com/a/77593
        .arg("$0 \"$1\" < $2")
        .arg(&config.editor_cmd[..])
        .arg(fpath.as_os_str())
        .arg("/dev/tty")
        .stdin(process::Stdio::inherit())
        .stdout(process::Stdio::inherit())
        .stderr(process::Stdio::inherit())
        .spawn());

    try!(utils::handle_process(&mut process));

    let fcontent = {
        let mut fcontent = String::new();
        let mut file = try!(fs::File::open(fpath));
        try!(file.read_to_string(&mut fcontent));
        fcontent
    };

    if (&fcontent[..]).trim().len() == 0 {
        try!(fs::remove_file(fpath));
        return Err(MainError::new("Contact emptied, file removed.").into());
    };

    Ok(())
}

fn mutt_query<'a>(config: &Configuration, query: &str) -> MainResult<()> {
    println!("");  // For some reason mutt requires an empty line
    // We need to ignore errors here, otherwise mutt's UI will glitch
    if let Ok(items) = utils::index_query(config, query) {
        for item in items {
            if item.email.len() > 0 && item.name.len() > 0 {
                println!("{}\t{}", item.email, item.name);
            };
        };
    };
    Ok(())
}

fn file_query<'a>(config: &Configuration, query: &str) -> MainResult<()> {
    for path in try!(utils::file_query(config, query)).iter() {
        println!("{}", path.display());
    };
    Ok(())
}

fn email_query<'a>(config: &Configuration, query: &str) -> MainResult<()> {
    for item in try!(utils::index_query(config, query)) {
        if item.name.len() > 0 && item.email.len() > 0 {
            println!("{} <{}>", item.name, item.email);
        };
    };
    Ok(())
}

pub struct Configuration {
    pub index_path: path::PathBuf,
    pub vdir_path: path::PathBuf,
    pub editor_cmd: String,
    pub grep_cmd: String
}

impl Configuration {
    pub fn new() -> Result<Configuration, String> {
        Ok(Configuration {
            index_path: match get_envvar("MATES_INDEX") {
                Some(x) => path::PathBuf::from(&x),
                None => match get_envvar("HOME") {
                    Some(home) => get_pwd().join(&home).join(".mates_index"),
                    None => return Err("Unable to determine user's home directory.".to_owned())
                }
            },
            vdir_path: match get_envvar("MATES_DIR") {
                Some(x) => path::PathBuf::from(&x),
                None => return Err("MATES_DIR must be set to your vdir path (directory of vcf-files).".to_owned())
            },
            editor_cmd: match get_envvar("MATES_EDITOR") {
                Some(x) => x,
                None => match get_envvar("EDITOR") {
                    Some(x) => x,
                    None => return Err("MATES_EDITOR or EDITOR must be set.".to_owned())
                }
            },
            grep_cmd: match get_envvar("MATES_GREP") {
                Some(x) => x,
                None => "grep -i".to_owned()
            }
        })
    }
}

#[derive(PartialEq, Eq, Debug)]
pub struct MainError {
    desc: String,
}

pub type MainResult<T> = Result<T, Box<Error>>;

impl Error for MainError {
    fn description(&self) -> &str {
        &self.desc[..]
    }

    fn cause(&self) -> Option<&Error> {
        None
    }
}

impl fmt::Display for MainError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.description().fmt(f)
    }
}

impl MainError {
    pub fn new<T: Into<String>>(desc: T) -> Self {
        MainError {
            desc: desc.into(),
        }
    }
}
<|endoftext|>


<commit_before>use meta::list::TypeList;

pub trait Prod: TypeList {
    fn split(self) -> (Self::Head, Self::Tail);
}

impl Prod for () {
    fn split(self) -> (Self::Head, Self::Tail) {
        ((), ())
    }
}

impl<A, B> Prod for (A, B)
    where B: Prod
{
    fn split(self) -> (Self::Head, Self::Tail) {
        self
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn split() {
        use super::Prod;

        let x = (1, ("Hello", ()));
        let (a, (b, ())) = x.split();
        assert_eq!(a, 1);
        assert_eq!(b, "Hello");
    }
}
<commit_msg>Implemen Prod for !<commit_after>use meta::list::TypeList;

pub trait Prod: TypeList {
    fn split(self) -> (Self::Head, Self::Tail);
}

impl Prod for () {
    fn split(self) -> (Self::Head, Self::Tail) {
        ((), ())
    }
}

impl Prod for ! {
    fn split(self) -> (Self::Head, Self::Tail) {
        unreachable!()
    }
}

impl<A, B> Prod for (A, B)
    where B: Prod
{
    fn split(self) -> (Self::Head, Self::Tail) {
        self
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn split() {
        use super::Prod;

        let x = (1, ("Hello", ()));
        let (a, (b, ())) = x.split();
        assert_eq!(a, 1);
        assert_eq!(b, "Hello");
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules, globs)]

extern crate conduit;
extern crate conduit_middleware = "conduit-middleware";
extern crate cookie;
extern crate serialize;
#[cfg(test)] extern crate test = "conduit-test";

use std::fmt::Show;
use std::any::AnyRefExt;
use conduit::{Request, Response};
use cookie::{CookieJar, Cookie};

pub use session::{RequestSession, SessionMiddleware};

mod session;

pub struct Middleware {
    key: Vec<u8>,
}

impl Middleware {
    pub fn new(key: &[u8]) -> Middleware {
        Middleware { key: key.to_owned() }
    }
}

impl conduit_middleware::Middleware for Middleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Show>> {
        let jar = {
            let headers = req.headers();
            let mut jar = CookieJar::new(self.key.as_slice());
            match headers.find("Cookie") {
                Some(cookies) => {
                    for cookie in cookies.iter() {
                        match Cookie::parse(*cookie) {
                            Ok(c) => jar.add_original(c),
                            Err(..) => {}
                        }
                    }
                }
                None => {}
            }
            jar
        };
        req.mut_extensions().insert("conduit.cookie", box jar);
        Ok(())
    }

    fn after(&self, req: &mut Request, res: Result<Response, Box<Show>>)
        -> Result<Response, Box<Show>>
    {
        let mut res = try!(res);
        {
            let jar = req.cookies();
            let cookies = res.headers.find_or_insert("Set-Cookie".to_string(),
                                                     Vec::new());
            for delta in jar.delta().move_iter() {
                cookies.push(delta);
            }
        }
        Ok(res)
    }
}

pub trait RequestCookies<'a> {
    fn cookies(self) -> &'a CookieJar<'static>;
}

impl<'a> RequestCookies<'a> for &'a mut Request {
    fn cookies(self) -> &'a CookieJar<'static> {
        self.mut_extensions().find_mut(&"conduit.cookie")
            .and_then(|a| a.as_ref::<CookieJar<'static>>())
            .expect("Missing cookie jar")
    }
}

#[cfg(test)]
mod tests {

    use conduit::{Request, Response, Handler, Post};
    use conduit_middleware::MiddlewareBuilder;
    use cookie::Cookie;
    use test::MockRequest;
    use std::collections::HashMap;
    use std::io::MemReader;

    use super::{RequestCookies, Middleware};

    #[test]
    fn request_headers() {
        let mut req = MockRequest::new(Post, "/articles");
        req.header("Cookie", "foo=bar");

        let mut app = MiddlewareBuilder::new(test);
        app.add(Middleware::new(b"foo"));
        assert!(app.call(&mut req).is_ok());

        fn test(req: &mut Request) -> Result<Response, String> {
            assert!(req.cookies().find("foo").is_some());
            Ok(Response {
                status: (200, "OK"),
                headers: HashMap::new(),
                body: box MemReader::new(Vec::new()),
            })
        }
    }

    #[test]
    fn set_cookie() {
        let mut req = MockRequest::new(Post, "/articles");
        let mut app = MiddlewareBuilder::new(test);
        app.add(Middleware::new(b"foo"));
        let response = app.call(&mut req).ok().unwrap();
        let v = response.headers.get(&"Set-Cookie".to_string());
        assert_eq!(v.as_slice(), &["foo=bar; Path=/".to_string()]);

        fn test(req: &mut Request) -> Result<Response, String> {
            let c = Cookie::new("foo".to_string(), "bar".to_string());
            req.cookies().add(c);
            Ok(Response {
                status: (200, "OK"),
                headers: HashMap::new(),
                body: box MemReader::new(Vec::new()),
            })
        }
    }
}
<commit_msg>Update to master<commit_after>#![feature(macro_rules, globs)]

extern crate conduit;
extern crate conduit_middleware = "conduit-middleware";
extern crate cookie;
extern crate serialize;
#[cfg(test)] extern crate test = "conduit-test";

use std::fmt::Show;
use std::any::AnyRefExt;
use conduit::{Request, Response};
use cookie::{CookieJar, Cookie};

pub use session::{RequestSession, SessionMiddleware};

mod session;

pub struct Middleware {
    key: Vec<u8>,
}

impl Middleware {
    pub fn new(key: &[u8]) -> Middleware {
        Middleware { key: key.to_vec() }
    }
}

impl conduit_middleware::Middleware for Middleware {
    fn before(&self, req: &mut Request) -> Result<(), Box<Show>> {
        let jar = {
            let headers = req.headers();
            let mut jar = CookieJar::new(self.key.as_slice());
            match headers.find("Cookie") {
                Some(cookies) => {
                    for cookie in cookies.iter() {
                        match Cookie::parse(*cookie) {
                            Ok(c) => jar.add_original(c),
                            Err(..) => {}
                        }
                    }
                }
                None => {}
            }
            jar
        };
        req.mut_extensions().insert("conduit.cookie", box jar);
        Ok(())
    }

    fn after(&self, req: &mut Request, res: Result<Response, Box<Show>>)
        -> Result<Response, Box<Show>>
    {
        let mut res = try!(res);
        {
            let jar = req.cookies();
            let cookies = res.headers.find_or_insert("Set-Cookie".to_string(),
                                                     Vec::new());
            for delta in jar.delta().move_iter() {
                cookies.push(delta);
            }
        }
        Ok(res)
    }
}

pub trait RequestCookies<'a> {
    fn cookies(self) -> &'a CookieJar<'static>;
}

impl<'a> RequestCookies<'a> for &'a mut Request {
    fn cookies(self) -> &'a CookieJar<'static> {
        self.mut_extensions().find_mut(&"conduit.cookie")
            .and_then(|a| a.as_ref::<CookieJar<'static>>())
            .expect("Missing cookie jar")
    }
}

#[cfg(test)]
mod tests {

    use conduit::{Request, Response, Handler, Post};
    use conduit_middleware::MiddlewareBuilder;
    use cookie::Cookie;
    use test::MockRequest;
    use std::collections::HashMap;
    use std::io::MemReader;

    use super::{RequestCookies, Middleware};

    #[test]
    fn request_headers() {
        let mut req = MockRequest::new(Post, "/articles");
        req.header("Cookie", "foo=bar");

        let mut app = MiddlewareBuilder::new(test);
        app.add(Middleware::new(b"foo"));
        assert!(app.call(&mut req).is_ok());

        fn test(req: &mut Request) -> Result<Response, String> {
            assert!(req.cookies().find("foo").is_some());
            Ok(Response {
                status: (200, "OK"),
                headers: HashMap::new(),
                body: box MemReader::new(Vec::new()),
            })
        }
    }

    #[test]
    fn set_cookie() {
        let mut req = MockRequest::new(Post, "/articles");
        let mut app = MiddlewareBuilder::new(test);
        app.add(Middleware::new(b"foo"));
        let response = app.call(&mut req).ok().unwrap();
        let v = response.headers.get(&"Set-Cookie".to_string());
        assert_eq!(v.as_slice(), &["foo=bar; Path=/".to_string()]);

        fn test(req: &mut Request) -> Result<Response, String> {
            let c = Cookie::new("foo".to_string(), "bar".to_string());
            req.cookies().add(c);
            Ok(Response {
                status: (200, "OK"),
                headers: HashMap::new(),
                body: box MemReader::new(Vec::new()),
            })
        }
    }
}
<|endoftext|>