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

use std::mem;
use smallvec::SmallVec;
use syntax::ast::CRATE_NODE_ID;
use ty::context::TyCtxt;
use ty::{DefId, DefIdTree};

/// Represents a forest of DefIds closed under the ancestor relation. That is,
/// if a DefId representing a module is contained in the forest then all
/// DefIds defined in that module or submodules are also implicitly contained
/// in the forest.
///
/// This is used to represent a set of modules in which a type is visibly
/// uninhabited.
#[derive(Clone)]
pub struct DefIdForest {
    /// The minimal set of DefIds required to represent the whole set.
    /// If A and B are DefIds in the DefIdForest, and A is a descendant
    /// of B, then only B will be in root_ids.
    /// We use a SmallVec here because (for its use for caching inhabitedness)
    /// its rare that this will contain even two ids.
    root_ids: SmallVec<[DefId; 1]>,
}

impl<'a, 'gcx, 'tcx> DefIdForest {
    /// Create an empty forest.
    pub fn empty() -> DefIdForest {
        DefIdForest {
            root_ids: SmallVec::new(),
        }
    }

    /// Create a forest consisting of a single tree representing the entire
    /// crate.
    #[inline]
    pub fn full(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest {
        let crate_id = tcx.hir().local_def_id(CRATE_NODE_ID);
        DefIdForest::from_id(crate_id)
    }

    /// Create a forest containing a DefId and all its descendants.
    pub fn from_id(id: DefId) -> DefIdForest {
        let mut root_ids = SmallVec::new();
        root_ids.push(id);
        DefIdForest {
            root_ids,
        }
    }

    /// Test whether the forest is empty.
    pub fn is_empty(&self) -> bool {
        self.root_ids.is_empty()
    }

    /// Test whether the forest contains a given DefId.
    pub fn contains(&self,
                    tcx: TyCtxt<'a, 'gcx, 'tcx>,
                    id: DefId) -> bool
    {
        self.root_ids.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
    }

    /// Calculate the intersection of a collection of forests.
    pub fn intersection<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                           iter: I) -> DefIdForest
            where I: IntoIterator<Item=DefIdForest>
    {
        let mut ret = DefIdForest::full(tcx);
        let mut next_ret = SmallVec::new();
        let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
        for next_forest in iter {
            for id in ret.root_ids.drain() {
                if next_forest.contains(tcx, id) {
                    next_ret.push(id);
                } else {
                    old_ret.push(id);
                }
            }
            ret.root_ids.extend(old_ret.drain());

            next_ret.extend(next_forest.root_ids.into_iter().filter(|&id| ret.contains(tcx, id)));

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain();
        }
        ret
    }

    /// Calculate the union of a collection of forests.
    pub fn union<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                    iter: I) -> DefIdForest
            where I: IntoIterator<Item=DefIdForest>
    {
        let mut ret = DefIdForest::empty();
        let mut next_ret = SmallVec::new();
        for next_forest in iter {
            next_ret.extend(ret.root_ids.drain().filter(|&id| !next_forest.contains(tcx, id)));

            for id in next_forest.root_ids {
                if !next_ret.contains(&id) {
                    next_ret.push(id);
                }
            }

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain();
        }
        ret
    }
}

<commit_msg>Auto merge of #57060 - nikic:inhabit-perf-2, r=varkor<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::mem;
use smallvec::SmallVec;
use syntax::ast::CRATE_NODE_ID;
use ty::context::TyCtxt;
use ty::{DefId, DefIdTree};

/// Represents a forest of DefIds closed under the ancestor relation. That is,
/// if a DefId representing a module is contained in the forest then all
/// DefIds defined in that module or submodules are also implicitly contained
/// in the forest.
///
/// This is used to represent a set of modules in which a type is visibly
/// uninhabited.
#[derive(Clone)]
pub struct DefIdForest {
    /// The minimal set of DefIds required to represent the whole set.
    /// If A and B are DefIds in the DefIdForest, and A is a descendant
    /// of B, then only B will be in root_ids.
    /// We use a SmallVec here because (for its use for caching inhabitedness)
    /// its rare that this will contain even two ids.
    root_ids: SmallVec<[DefId; 1]>,
}

impl<'a, 'gcx, 'tcx> DefIdForest {
    /// Create an empty forest.
    pub fn empty() -> DefIdForest {
        DefIdForest {
            root_ids: SmallVec::new(),
        }
    }

    /// Create a forest consisting of a single tree representing the entire
    /// crate.
    #[inline]
    pub fn full(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest {
        let crate_id = tcx.hir().local_def_id(CRATE_NODE_ID);
        DefIdForest::from_id(crate_id)
    }

    /// Create a forest containing a DefId and all its descendants.
    pub fn from_id(id: DefId) -> DefIdForest {
        let mut root_ids = SmallVec::new();
        root_ids.push(id);
        DefIdForest {
            root_ids,
        }
    }

    /// Test whether the forest is empty.
    pub fn is_empty(&self) -> bool {
        self.root_ids.is_empty()
    }

    /// Test whether the forest contains a given DefId.
    pub fn contains(&self,
                    tcx: TyCtxt<'a, 'gcx, 'tcx>,
                    id: DefId) -> bool
    {
        self.root_ids.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
    }

    /// Calculate the intersection of a collection of forests.
    pub fn intersection<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                           iter: I) -> DefIdForest
            where I: IntoIterator<Item=DefIdForest>
    {
        let mut iter = iter.into_iter();
        let mut ret = if let Some(first) = iter.next() {
            first
        } else {
            return DefIdForest::full(tcx);
        };

        let mut next_ret = SmallVec::new();
        let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
        for next_forest in iter {
            // No need to continue if the intersection is already empty.
            if ret.is_empty() {
                break;
            }

            for id in ret.root_ids.drain() {
                if next_forest.contains(tcx, id) {
                    next_ret.push(id);
                } else {
                    old_ret.push(id);
                }
            }
            ret.root_ids.extend(old_ret.drain());

            next_ret.extend(next_forest.root_ids.into_iter().filter(|&id| ret.contains(tcx, id)));

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain();
        }
        ret
    }

    /// Calculate the union of a collection of forests.
    pub fn union<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                    iter: I) -> DefIdForest
            where I: IntoIterator<Item=DefIdForest>
    {
        let mut ret = DefIdForest::empty();
        let mut next_ret = SmallVec::new();
        for next_forest in iter {
            next_ret.extend(ret.root_ids.drain().filter(|&id| !next_forest.contains(tcx, id)));

            for id in next_forest.root_ids {
                if !next_ret.contains(&id) {
                    next_ret.push(id);
                }
            }

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain();
        }
        ret
    }
}

<|endoftext|>


<commit_before>use error::ErrorCode;
use futures;
use futures::Stream;
use futures::future::Either;
use futures::future::Future;
use futures::stream::Collect;
use futures::stream::FuturesOrdered;
use futures::sync::oneshot;
use helper::{select_topic, ReqInfo, ReqSender, RpcMap, TransferType};
use hyper;
use hyper::{Method, StatusCode};
use hyper::server::{Http, NewService, Request, Response, Service};
use jsonrpc_types::{method, Call, Error, RpcRequest};
use jsonrpc_types::method::MethodHandler;
use jsonrpc_types::response::{RpcFailure, RpcResponse};
use jsonrpc_types::response::Output;
use libproto::request as reqlib;
use net2;
use serde_json;
use std::io;
use std::net::SocketAddr;
use std::sync::Arc;
use std::sync::mpsc;
use std::time::Duration;
use tokio_core::net::TcpListener;
use tokio_core::reactor::{Core, Handle};
use tokio_core::reactor::Timeout;
use util::Mutex;

const TCP_BACKLOG: i32 = 1024;

struct Inner {
    pub tx: ReqSender,
    pub responses: RpcMap,
    pub timeout: Duration,
    pub reactor_handle: Handle,
    pub method_handler: method::MethodHandler,
}

pub struct Server {
    inner: Arc<Inner>,
}

pub struct NewServer {
    inner: Arc<Inner>,
}

impl NewService for NewServer {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Instance = Server;

    fn new_service(&self) -> io::Result<Self::Instance> {
        Ok(Server {
            inner: Arc::clone(&self.inner),
        })
    }
}

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

    fn call(&self, req: Request) -> Self::Future {
        let sender = { self.inner.tx.lock().clone() };
        let responses = Arc::clone(&self.inner.responses);
        let timeout_responses = Arc::clone(&self.inner.responses);
        let method_handler = self.inner.method_handler;
        let timeout = self.inner.timeout;
        let reactor_handle = self.inner.reactor_handle.clone();

        match (req.method(), req.path()) {
            (&Method::Post, "/") => {
                let mapping = req.body().concat2().and_then(move |chunk| {
                    if let Ok(rpc) = serde_json::from_slice::<RpcRequest>(&chunk) {
                        match rpc {
                            RpcRequest::Single(call) => match read_single(&call, method_handler) {
                                Ok(req) => {
                                    if let Ok(timeout) = Timeout::new(timeout, &reactor_handle) {
                                        let id = call.id.clone();
                                        let jsonrpc_version = call.jsonrpc.clone();
                                        let request_id = req.request_id.clone();
                                        let future_result = handle_single(call, req, responses, sender);
                                        let mq_resp = future_result.map_err(|_| hyper::Error::Incomplete);

                                        let resp = mq_resp.select2(timeout).then(move |res| match res {
                                            Ok(Either::A((got, _timeout))) => Ok(got),
                                            Ok(Either::B((_timeout_error, _get))) => {
                                                {
                                                    timeout_responses.lock().remove(&request_id);
                                                }
                                                let failure = RpcFailure::from_options(
                                                    id,
                                                    jsonrpc_version,
                                                    Error::server_error(
                                                        ErrorCode::time_out_error(),
                                                        "system time out, please resend",
                                                    ),
                                                );
                                                let resp_body = serde_json::to_string(&failure)
                                                    .expect("should be serialize by serde_json");
                                                Ok(Response::new().with_body(resp_body))
                                            }
                                            Err(Either::A((get_error, _timeout))) => Err(get_error),
                                            Err(Either::B((timeout_error, _get))) => Err(From::from(timeout_error)),
                                        });

                                        Either::A(Either::A(resp))
                                    } else {
                                        Either::B(futures::future::ok(
                                            Response::new().with_status(StatusCode::InternalServerError),
                                        ))
                                    }
                                }
                                Err(resp) => Either::B(futures::future::ok(resp)),
                            },
                            RpcRequest::Batch(calls) => match read_batch(calls, method_handler) {
                                Ok(reqs) => {
                                    let request_ids: Vec<Vec<u8>> = reqs.iter()
                                        .map(|&(ref _call, ref req)| req.request_id.clone())
                                        .collect();

                                    let future_result = handle_batch(reqs, responses, sender);

                                    if let Ok(timeout) = Timeout::new(timeout, &reactor_handle) {
                                        let mq_resp = future_result.map_err(|_| hyper::Error::Incomplete);

                                        let resp = mq_resp.select2(timeout).then(move |res| match res {
                                            Ok(Either::A((got, _timeout))) => Ok(got),
                                            Ok(Either::B((_timeout_error, _get))) => {
                                                for request_id in request_ids {
                                                    timeout_responses.lock().remove(&request_id);
                                                }
                                                let failure = RpcFailure::from(Error::server_error(
                                                    ErrorCode::time_out_error(),
                                                    "system time out, please resend",
                                                ));
                                                let resp_body = serde_json::to_string(&failure)
                                                    .expect("should be serialize by serde_json");
                                                Ok(Response::new().with_body(resp_body))
                                            }
                                            Err(Either::A((get_error, _timeout))) => Err(get_error),
                                            Err(Either::B((timeout_error, _get))) => Err(From::from(timeout_error)),
                                        });

                                        Either::A(Either::B(resp))
                                    } else {
                                        Either::B(futures::future::ok(
                                            Response::new().with_status(StatusCode::InternalServerError),
                                        ))
                                    }
                                }
                                Err(resp) => Either::B(futures::future::ok(resp)),
                            },
                        }
                    } else {
                        Either::B(futures::future::ok(
                            Response::new().with_status(StatusCode::BadRequest),
                        ))
                    }
                });
                let resp: Box<Future<Error = hyper::Error, Item = hyper::Response>> = Box::new(mapping);
                resp
            }
            _ => Box::new(futures::future::ok(
                Response::new().with_status(StatusCode::NotFound),
            )),
        }
    }
}

fn read_single(call: &Call, method_handler: MethodHandler) -> Result<reqlib::Request, Response> {
    match method_handler.request(call) {
        Ok(req) => Ok(req),
        Err(e) => {
            let resp_body = serde_json::to_vec(&RpcFailure::from_options(
                call.id.clone(),
                call.jsonrpc.clone(),
                e,
            )).expect("should be serialize by serde_json");
            Err(Response::new().with_body(resp_body))
        }
    }
}

type SingleFutureMap = futures::future::Map<oneshot::Receiver<Output>, fn(Output) -> Response>;

fn handle_single(
    call: Call,
    req: reqlib::Request,
    responses: RpcMap,
    sender: mpsc::Sender<(String, reqlib::Request)>,
) -> SingleFutureMap {
    let request_id = req.request_id.clone();
    let (tx, rx) = oneshot::channel();
    let topic = select_topic(&call.method);
    let req_info = (ReqInfo::new(call.jsonrpc, call.id), tx);
    {
        responses
            .lock()
            .insert(request_id.clone(), TransferType::HTTP(req_info));
    }
    let _ = sender.send((topic, req));
    rx.map(|resp_body| Response::new().with_body(serde_json::to_vec(&resp_body).unwrap()))
}

fn read_batch(calls: Vec<Call>, method_handler: MethodHandler) -> Result<Vec<(Call, reqlib::Request)>, Response> {
    let mut reqs = Vec::with_capacity(calls.len());
    for call in calls {
        match method_handler.request(&call) {
            Ok(req) => {
                reqs.push((call, req));
            }
            Err(_) => return Err(Response::new().with_status(StatusCode::BadRequest)),
        }
    }
    Ok(reqs)
}

type BatchFutureMap = futures::future::Map<
    Collect<FuturesOrdered<oneshot::Receiver<Output>>>,
    fn(Vec<Output>) -> Response,
>;

fn handle_batch(
    reqs: Vec<(Call, reqlib::Request)>,
    responses: RpcMap,
    sender: mpsc::Sender<(String, reqlib::Request)>,
) -> BatchFutureMap {
    use std::iter::FromIterator;
    let mut rxs = Vec::with_capacity(reqs.len());
    for (call, req) in reqs {
        let request_id = req.request_id.clone();
        let topic = select_topic(&call.method);
        let (tx, rx) = oneshot::channel();
        let req_info = (ReqInfo::new(call.jsonrpc, call.id), tx);
        {
            responses
                .lock()
                .insert(request_id.clone(), TransferType::HTTP(req_info));
        }
        let _ = sender.send((topic, req));
        rxs.push(rx);
    }
    FuturesOrdered::from_iter(rxs)
        .collect()
        .map(|resp_body| Response::new().with_body(serde_json::to_vec(&RpcResponse::Batch(resp_body)).unwrap()))
}

impl Server {
    pub fn start(
        core: Core,
        listener: TcpListener,
        tx: mpsc::Sender<(String, reqlib::Request)>,
        responses: RpcMap,
        timeout: Duration,
    ) {
        let new_service = NewServer {
            inner: Arc::new(Inner {
                tx: Mutex::new(tx),
                responses: responses,
                timeout: timeout,
                reactor_handle: core.handle(),
                method_handler: method::MethodHandler,
            }),
        };
        let mut server = Http::new()
            .keep_alive(true)
            .bind_listener(core, listener, new_service)
            .unwrap();
        server.no_proto();
        server.run().unwrap();
    }
}

pub fn listener(addr: &SocketAddr, handle: &Handle) -> io::Result<TcpListener> {
    let listener = match *addr {
        SocketAddr::V4(_) => net2::TcpBuilder::new_v4()?,
        SocketAddr::V6(_) => net2::TcpBuilder::new_v6()?,
    };
    configure_tcp(&listener)?;
    listener.reuse_address(true)?;
    listener.bind(addr)?;
    listener
        .listen(TCP_BACKLOG)
        .and_then(|l| TcpListener::from_listener(l, addr, handle))
}

fn configure_tcp(tcp: &net2::TcpBuilder) -> io::Result<()> {
    use net2::unix::*;
    tcp.reuse_port(true)?;
    Ok(())
}
<commit_msg>remove redundant clone<commit_after>use error::ErrorCode;
use futures;
use futures::Stream;
use futures::future::Either;
use futures::future::Future;
use futures::stream::Collect;
use futures::stream::FuturesOrdered;
use futures::sync::oneshot;
use helper::{select_topic, ReqInfo, ReqSender, RpcMap, TransferType};
use hyper;
use hyper::{Method, StatusCode};
use hyper::server::{Http, NewService, Request, Response, Service};
use jsonrpc_types::{method, Call, Error, RpcRequest};
use jsonrpc_types::method::MethodHandler;
use jsonrpc_types::response::{RpcFailure, RpcResponse};
use jsonrpc_types::response::Output;
use libproto::request as reqlib;
use net2;
use serde_json;
use std::io;
use std::net::SocketAddr;
use std::sync::Arc;
use std::sync::mpsc;
use std::time::Duration;
use tokio_core::net::TcpListener;
use tokio_core::reactor::{Core, Handle};
use tokio_core::reactor::Timeout;
use util::Mutex;

const TCP_BACKLOG: i32 = 1024;

struct Inner {
    pub tx: ReqSender,
    pub responses: RpcMap,
    pub timeout: Duration,
    pub reactor_handle: Handle,
    pub method_handler: method::MethodHandler,
}

pub struct Server {
    inner: Arc<Inner>,
}

pub struct NewServer {
    inner: Arc<Inner>,
}

impl NewService for NewServer {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Instance = Server;

    fn new_service(&self) -> io::Result<Self::Instance> {
        Ok(Server {
            inner: Arc::clone(&self.inner),
        })
    }
}

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

    fn call(&self, req: Request) -> Self::Future {
        let sender = { self.inner.tx.lock().clone() };
        let responses = Arc::clone(&self.inner.responses);
        let timeout_responses = Arc::clone(&self.inner.responses);
        let method_handler = self.inner.method_handler;
        let timeout = self.inner.timeout;
        let reactor_handle = self.inner.reactor_handle.clone();

        match (req.method(), req.path()) {
            (&Method::Post, "/") => {
                let mapping = req.body().concat2().and_then(move |chunk| {
                    if let Ok(rpc) = serde_json::from_slice::<RpcRequest>(&chunk) {
                        match rpc {
                            RpcRequest::Single(call) => match read_single(&call, method_handler) {
                                Ok(req) => {
                                    if let Ok(timeout) = Timeout::new(timeout, &reactor_handle) {
                                        let id = call.id.clone();
                                        let jsonrpc_version = call.jsonrpc.clone();
                                        let request_id = req.request_id.clone();
                                        let future_result = handle_single(call, req, responses, sender);
                                        let mq_resp = future_result.map_err(|_| hyper::Error::Incomplete);

                                        let resp = mq_resp.select2(timeout).then(move |res| match res {
                                            Ok(Either::A((got, _timeout))) => Ok(got),
                                            Ok(Either::B((_timeout_error, _get))) => {
                                                {
                                                    timeout_responses.lock().remove(&request_id);
                                                }
                                                let failure = RpcFailure::from_options(
                                                    id,
                                                    jsonrpc_version,
                                                    Error::server_error(
                                                        ErrorCode::time_out_error(),
                                                        "system time out, please resend",
                                                    ),
                                                );
                                                let resp_body = serde_json::to_string(&failure)
                                                    .expect("should be serialize by serde_json");
                                                Ok(Response::new().with_body(resp_body))
                                            }
                                            Err(Either::A((get_error, _timeout))) => Err(get_error),
                                            Err(Either::B((timeout_error, _get))) => Err(From::from(timeout_error)),
                                        });

                                        Either::A(Either::A(resp))
                                    } else {
                                        Either::B(futures::future::ok(
                                            Response::new().with_status(StatusCode::InternalServerError),
                                        ))
                                    }
                                }
                                Err(resp) => Either::B(futures::future::ok(resp)),
                            },
                            RpcRequest::Batch(calls) => match read_batch(calls, method_handler) {
                                Ok(reqs) => {
                                    let request_ids: Vec<Vec<u8>> = reqs.iter()
                                        .map(|&(ref _call, ref req)| req.request_id.clone())
                                        .collect();

                                    let future_result = handle_batch(reqs, responses, sender);

                                    if let Ok(timeout) = Timeout::new(timeout, &reactor_handle) {
                                        let mq_resp = future_result.map_err(|_| hyper::Error::Incomplete);

                                        let resp = mq_resp.select2(timeout).then(move |res| match res {
                                            Ok(Either::A((got, _timeout))) => Ok(got),
                                            Ok(Either::B((_timeout_error, _get))) => {
                                                {
                                                    let mut guard = timeout_responses.lock();
                                                    for request_id in request_ids {
                                                        guard.remove(&request_id);
                                                    }
                                                }
                                                let failure = RpcFailure::from(Error::server_error(
                                                    ErrorCode::time_out_error(),
                                                    "system time out, please resend",
                                                ));
                                                let resp_body = serde_json::to_string(&failure)
                                                    .expect("should be serialize by serde_json");
                                                Ok(Response::new().with_body(resp_body))
                                            }
                                            Err(Either::A((get_error, _timeout))) => Err(get_error),
                                            Err(Either::B((timeout_error, _get))) => Err(From::from(timeout_error)),
                                        });

                                        Either::A(Either::B(resp))
                                    } else {
                                        Either::B(futures::future::ok(
                                            Response::new().with_status(StatusCode::InternalServerError),
                                        ))
                                    }
                                }
                                Err(resp) => Either::B(futures::future::ok(resp)),
                            },
                        }
                    } else {
                        Either::B(futures::future::ok(
                            Response::new().with_status(StatusCode::BadRequest),
                        ))
                    }
                });
                let resp: Box<Future<Error = hyper::Error, Item = hyper::Response>> = Box::new(mapping);
                resp
            }
            _ => Box::new(futures::future::ok(
                Response::new().with_status(StatusCode::NotFound),
            )),
        }
    }
}

fn read_single(call: &Call, method_handler: MethodHandler) -> Result<reqlib::Request, Response> {
    match method_handler.request(call) {
        Ok(req) => Ok(req),
        Err(e) => {
            let resp_body = serde_json::to_vec(&RpcFailure::from_options(
                call.id.clone(),
                call.jsonrpc.clone(),
                e,
            )).expect("should be serialize by serde_json");
            Err(Response::new().with_body(resp_body))
        }
    }
}

type SingleFutureMap = futures::future::Map<oneshot::Receiver<Output>, fn(Output) -> Response>;

fn handle_single(
    call: Call,
    req: reqlib::Request,
    responses: RpcMap,
    sender: mpsc::Sender<(String, reqlib::Request)>,
) -> SingleFutureMap {
    let request_id = req.request_id.clone();
    let (tx, rx) = oneshot::channel();
    let topic = select_topic(&call.method);
    let req_info = (ReqInfo::new(call.jsonrpc, call.id), tx);
    {
        responses
            .lock()
            .insert(request_id, TransferType::HTTP(req_info));
    }
    let _ = sender.send((topic, req));
    rx.map(|resp_body| Response::new().with_body(serde_json::to_vec(&resp_body).unwrap()))
}

fn read_batch(calls: Vec<Call>, method_handler: MethodHandler) -> Result<Vec<(Call, reqlib::Request)>, Response> {
    let mut reqs = Vec::with_capacity(calls.len());
    for call in calls {
        match method_handler.request(&call) {
            Ok(req) => {
                reqs.push((call, req));
            }
            Err(_) => return Err(Response::new().with_status(StatusCode::BadRequest)),
        }
    }
    Ok(reqs)
}

type BatchFutureMap = futures::future::Map<
    Collect<FuturesOrdered<oneshot::Receiver<Output>>>,
    fn(Vec<Output>) -> Response,
>;

fn handle_batch(
    reqs: Vec<(Call, reqlib::Request)>,
    responses: RpcMap,
    sender: mpsc::Sender<(String, reqlib::Request)>,
) -> BatchFutureMap {
    use std::iter::FromIterator;
    let mut rxs = Vec::with_capacity(reqs.len());
    for (call, req) in reqs {
        let request_id = req.request_id.clone();
        let topic = select_topic(&call.method);
        let (tx, rx) = oneshot::channel();
        let req_info = (ReqInfo::new(call.jsonrpc, call.id), tx);
        {
            responses
                .lock()
                .insert(request_id, TransferType::HTTP(req_info));
        }
        let _ = sender.send((topic, req));
        rxs.push(rx);
    }
    FuturesOrdered::from_iter(rxs)
        .collect()
        .map(|resp_body| Response::new().with_body(serde_json::to_vec(&RpcResponse::Batch(resp_body)).unwrap()))
}

impl Server {
    pub fn start(
        core: Core,
        listener: TcpListener,
        tx: mpsc::Sender<(String, reqlib::Request)>,
        responses: RpcMap,
        timeout: Duration,
    ) {
        let new_service = NewServer {
            inner: Arc::new(Inner {
                tx: Mutex::new(tx),
                responses: responses,
                timeout: timeout,
                reactor_handle: core.handle(),
                method_handler: method::MethodHandler,
            }),
        };
        let mut server = Http::new()
            .keep_alive(true)
            .bind_listener(core, listener, new_service)
            .unwrap();
        server.no_proto();
        server.run().unwrap();
    }
}

pub fn listener(addr: &SocketAddr, handle: &Handle) -> io::Result<TcpListener> {
    let listener = match *addr {
        SocketAddr::V4(_) => net2::TcpBuilder::new_v4()?,
        SocketAddr::V6(_) => net2::TcpBuilder::new_v6()?,
    };
    configure_tcp(&listener)?;
    listener.reuse_address(true)?;
    listener.bind(addr)?;
    listener
        .listen(TCP_BACKLOG)
        .and_then(|l| TcpListener::from_listener(l, addr, handle))
}

fn configure_tcp(tcp: &net2::TcpBuilder) -> io::Result<()> {
    use net2::unix::*;
    tcp.reuse_port(true)?;
    Ok(())
}
<|endoftext|>


<commit_before>use std::fmt;

/// Represents a distinct entry in the database schema.
pub enum Entry {
    /// An entry defining a database table.
    Table(Table),

    /// An entry defining type that is a union of other types.
    Union(Union),
}

/// A table in the database schema.
pub struct Table {
    pub name: String,
    pub columns: Vec<Column>,
    pub keysets: Option<Vec<String>>,
}

/// A union in the database schema.
pub struct Union {
    pub name: String,
    pub members: Vec<String>,
}

/// A column in a table.
pub struct Column {
    pub db_type: DbColumnType,
    pub name: String,
    pub unique: bool,
    pub ql_type: QlColumnType,
    pub ql_type_is_ref: bool,
}

/// The database column type.
pub enum DbColumnType {
    Int,
    String,
}

// The QL type of a column.
pub enum QlColumnType {
    /// Primitive `int` type.
    Int,

    /// Primitive `string` type.
    String,

    /// A custom type, defined elsewhere by a table or union.
    Custom(String),
}

const RESERVED_KEYWORDS: [&'static str; 14] = [
    "boolean", "case", "date", "float", "int", "key", "of", "order", "ref", "string", "subtype",
    "type", "unique", "varchar",
];

/// Returns a string that's a copy of `name` but suitably escaped to be a valid
/// QL identifier.
pub fn escape_name(name: &str) -> String {
    let mut result = String::new();

    // If there's a leading underscore, replace it with 'underscore_'.
    if let Some(c) = name.chars().next() {
        if c == '_' {
            result.push_str("underscore");
        }
    }
    for c in name.chars() {
        match c {
            '{' => result.push_str("lbrace"),
            '}' => result.push_str("rbrace"),
            '<' => result.push_str("langle"),
            '>' => result.push_str("rangle"),
            '[' => result.push_str("lbracket"),
            ']' => result.push_str("rbracket"),
            '(' => result.push_str("lparen"),
            ')' => result.push_str("rparen"),
            '|' => result.push_str("pipe"),
            '=' => result.push_str("equal"),
            '~' => result.push_str("tilde"),
            '?' => result.push_str("question"),
            '`' => result.push_str("backtick"),
            '^' => result.push_str("caret"),
            '!' => result.push_str("bang"),
            '#' => result.push_str("hash"),
            '%' => result.push_str("percent"),
            '&' => result.push_str("ampersand"),
            '.' => result.push_str("dot"),
            ',' => result.push_str("comma"),
            '/' => result.push_str("slash"),
            ':' => result.push_str("colon"),
            ';' => result.push_str("semicolon"),
            '"' => result.push_str("dquote"),
            '*' => result.push_str("star"),
            '+' => result.push_str("plus"),
            '-' => result.push_str("minus"),
            '@' => result.push_str("at"),
            _ => result.push_str(&c.to_lowercase().to_string()),
        }
    }

    for &keyword in &RESERVED_KEYWORDS {
        if result == keyword {
            result.push_str("__");
            break;
        }
    }

    result
}

impl fmt::Display for Table {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for keyset in &self.keysets {
            write!(f, "#keyset[")?;
            for (key_index, key) in keyset.iter().enumerate() {
                if key_index > 0 {
                    write!(f, ", ")?;
                }
                write!(f, "{}", key)?;
            }
            write!(f, "]\n")?;
        }

        write!(f, "{}(\n", self.name)?;
        for (column_index, column) in self.columns.iter().enumerate() {
            write!(f, "  ")?;
            if column.unique {
                write!(f, "unique ")?;
            }
            write!(
                f,
                "{} ",
                match column.db_type {
                    DbColumnType::Int => "int",
                    DbColumnType::String => "string",
                }
            )?;
            write!(f, "{}: ", column.name)?;
            match &column.ql_type {
                QlColumnType::Int => write!(f, "int")?,
                QlColumnType::String => write!(f, "string")?,
                QlColumnType::Custom(name) => write!(f, "@{}", name)?,
            }
            if column.ql_type_is_ref {
                write!(f, " ref")?;
            }
            if column_index + 1 != self.columns.len() {
                write!(f, ",")?;
            }
            write!(f, "\n")?;
        }
        write!(f, ");")?;

        Ok(())
    }
}

impl fmt::Display for Union {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "@{} = ", self.name)?;
        let mut first = true;
        for member in &self.members {
            if first {
                first = false;
            } else {
                write!(f, " | ")?;
            }
            write!(f, "@{}", member)?;
        }
        Ok(())
    }
}

/// Generates the dbscheme by writing the given dbscheme `entries` to the `file`.
pub fn write(
    language_name: &str,
    file: &mut dyn std::io::Write,
    entries: &[Entry],
) -> std::io::Result<()> {
    write!(file, "// CodeQL database schema for {}\n", language_name)?;
    write!(
        file,
        "// Automatically generated from the tree-sitter grammar; do not edit\n\n"
    )?;

    for entry in entries {
        match entry {
            Entry::Table(table) => write!(file, "{}\n\n", table)?,
            Entry::Union(union) => write!(file, "{}\n\n", union)?,
        }
    }

    Ok(())
}
<commit_msg>Use `if let` instead of iterating over Option<commit_after>use std::fmt;

/// Represents a distinct entry in the database schema.
pub enum Entry {
    /// An entry defining a database table.
    Table(Table),

    /// An entry defining type that is a union of other types.
    Union(Union),
}

/// A table in the database schema.
pub struct Table {
    pub name: String,
    pub columns: Vec<Column>,
    pub keysets: Option<Vec<String>>,
}

/// A union in the database schema.
pub struct Union {
    pub name: String,
    pub members: Vec<String>,
}

/// A column in a table.
pub struct Column {
    pub db_type: DbColumnType,
    pub name: String,
    pub unique: bool,
    pub ql_type: QlColumnType,
    pub ql_type_is_ref: bool,
}

/// The database column type.
pub enum DbColumnType {
    Int,
    String,
}

// The QL type of a column.
pub enum QlColumnType {
    /// Primitive `int` type.
    Int,

    /// Primitive `string` type.
    String,

    /// A custom type, defined elsewhere by a table or union.
    Custom(String),
}

const RESERVED_KEYWORDS: [&'static str; 14] = [
    "boolean", "case", "date", "float", "int", "key", "of", "order", "ref", "string", "subtype",
    "type", "unique", "varchar",
];

/// Returns a string that's a copy of `name` but suitably escaped to be a valid
/// QL identifier.
pub fn escape_name(name: &str) -> String {
    let mut result = String::new();

    // If there's a leading underscore, replace it with 'underscore_'.
    if let Some(c) = name.chars().next() {
        if c == '_' {
            result.push_str("underscore");
        }
    }
    for c in name.chars() {
        match c {
            '{' => result.push_str("lbrace"),
            '}' => result.push_str("rbrace"),
            '<' => result.push_str("langle"),
            '>' => result.push_str("rangle"),
            '[' => result.push_str("lbracket"),
            ']' => result.push_str("rbracket"),
            '(' => result.push_str("lparen"),
            ')' => result.push_str("rparen"),
            '|' => result.push_str("pipe"),
            '=' => result.push_str("equal"),
            '~' => result.push_str("tilde"),
            '?' => result.push_str("question"),
            '`' => result.push_str("backtick"),
            '^' => result.push_str("caret"),
            '!' => result.push_str("bang"),
            '#' => result.push_str("hash"),
            '%' => result.push_str("percent"),
            '&' => result.push_str("ampersand"),
            '.' => result.push_str("dot"),
            ',' => result.push_str("comma"),
            '/' => result.push_str("slash"),
            ':' => result.push_str("colon"),
            ';' => result.push_str("semicolon"),
            '"' => result.push_str("dquote"),
            '*' => result.push_str("star"),
            '+' => result.push_str("plus"),
            '-' => result.push_str("minus"),
            '@' => result.push_str("at"),
            _ => result.push_str(&c.to_lowercase().to_string()),
        }
    }

    for &keyword in &RESERVED_KEYWORDS {
        if result == keyword {
            result.push_str("__");
            break;
        }
    }

    result
}

impl fmt::Display for Table {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        if let Some(keyset) = &self.keysets {
            write!(f, "#keyset[")?;
            for (key_index, key) in keyset.iter().enumerate() {
                if key_index > 0 {
                    write!(f, ", ")?;
                }
                write!(f, "{}", key)?;
            }
            write!(f, "]\n")?;
        }

        write!(f, "{}(\n", self.name)?;
        for (column_index, column) in self.columns.iter().enumerate() {
            write!(f, "  ")?;
            if column.unique {
                write!(f, "unique ")?;
            }
            write!(
                f,
                "{} ",
                match column.db_type {
                    DbColumnType::Int => "int",
                    DbColumnType::String => "string",
                }
            )?;
            write!(f, "{}: ", column.name)?;
            match &column.ql_type {
                QlColumnType::Int => write!(f, "int")?,
                QlColumnType::String => write!(f, "string")?,
                QlColumnType::Custom(name) => write!(f, "@{}", name)?,
            }
            if column.ql_type_is_ref {
                write!(f, " ref")?;
            }
            if column_index + 1 != self.columns.len() {
                write!(f, ",")?;
            }
            write!(f, "\n")?;
        }
        write!(f, ");")?;

        Ok(())
    }
}

impl fmt::Display for Union {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "@{} = ", self.name)?;
        let mut first = true;
        for member in &self.members {
            if first {
                first = false;
            } else {
                write!(f, " | ")?;
            }
            write!(f, "@{}", member)?;
        }
        Ok(())
    }
}

/// Generates the dbscheme by writing the given dbscheme `entries` to the `file`.
pub fn write(
    language_name: &str,
    file: &mut dyn std::io::Write,
    entries: &[Entry],
) -> std::io::Result<()> {
    write!(file, "// CodeQL database schema for {}\n", language_name)?;
    write!(
        file,
        "// Automatically generated from the tree-sitter grammar; do not edit\n\n"
    )?;

    for entry in entries {
        match entry {
            Entry::Table(table) => write!(file, "{}\n\n", table)?,
            Entry::Union(union) => write!(file, "{}\n\n", union)?,
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Echo server with a bounded buffer pool.

extern crate gj;
use std::net::ToSocketAddrs;
use std::cell::RefCell;
use std::rc::Rc;
use gj::io::{AsyncRead, AsyncWrite};

struct BufferPool {
    buffers: Vec<Vec<u8>>,
    fulfiller: Option<Box<gj::PromiseFulfiller<Vec<u8>, ::std::io::Error>>>,
}

impl BufferPool {
    pub fn new(num_buffers: usize) -> BufferPool {
        let mut buffers = Vec::with_capacity(num_buffers);
        for _ in 0..num_buffers {
            buffers.push(vec![0; 1024]);
        }
        BufferPool { buffers: buffers, fulfiller: None }
    }

    pub fn pop(&mut self) -> gj::Promise<Vec<u8>, ::std::io::Error> {
        match self.buffers.pop() {
            Some(buf) => gj::Promise::fulfilled(buf),
            None => {
                let (promise, fulfiller) = gj::new_promise_and_fulfiller();
                assert!(self.fulfiller.is_none(), "only supports one waiting task");
                self.fulfiller = Some(fulfiller);
                promise
            }
        }
    }

    pub fn push(&mut self, buf: Vec<u8>) {
        match self.fulfiller.take() {
            Some(fulfiller) => fulfiller.fulfill(buf),
            None => self.buffers.push(buf),
        }
    }
}

struct Reaper {
    buffer_pool: Rc<RefCell<BufferPool>>,
}

impl gj::TaskReaper<ThreadedState, gj::io::Error<ThreadedState>> for Reaper {
    fn task_succeeded(&mut self, (_, buf): ThreadedState) {
        self.buffer_pool.borrow_mut().push(buf);
    }
    fn task_failed(&mut self, error: gj::io::Error<ThreadedState>) {
        self.buffer_pool.borrow_mut().push(error.state.1);
        println!("Task failed: {}", error.error);
    }
}

type ThreadedState = (::gj::io::tcp::Stream, Vec<u8>);

fn echo<S,B>(stream: S, buf: B) -> gj::Promise<(S, B), gj::io::Error<(S, B)>>
    where S: AsyncRead + AsyncWrite, B: ::std::ops::DerefMut<Target=[u8]> + 'static
{
    stream.try_read(buf, 1).then(move |(stream, buf, n)| {
        if n == 0 {
            // EOF
            Ok(gj::Promise::fulfilled((stream, buf)))
        } else {
            Ok(stream.write(gj::io::Slice::new(buf, n)).then_else(move |r| match r {
                Ok((stream, slice)) => Ok(echo(stream, slice.buf)),
                Err(gj::io::Error {state: (stream, slice), error}) =>
                    Err(gj::io::Error::new((stream, slice.buf), error)),
            }))
        }
    })
}

fn accept_loop(receiver: gj::io::tcp::Listener,
               mut task_set: gj::TaskSet<ThreadedState, gj::io::Error<ThreadedState>>,
               buffer_pool: Rc<RefCell<BufferPool>>)
               -> gj::Promise<(), ::std::io::Error>
{
    let buf_promise = buffer_pool.borrow_mut().pop();
    buf_promise.then(move |buf| {
        Ok(receiver.accept().lift().then(move |(receiver, stream)| {
            task_set.add(echo(stream, buf));
            Ok(accept_loop(receiver, task_set, buffer_pool))
        }))
    })
}

pub fn main() {
    let args: Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }
    let buffer_pool = Rc::new(RefCell::new(BufferPool::new(1)));

    gj::EventLoop::top_level(move |wait_scope| {

        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let listener = try!(::gj::io::tcp::Listener::bind(addr));
        let reaper = Box::new(Reaper { buffer_pool: buffer_pool.clone() });
        accept_loop(listener, gj::TaskSet::new(reaper), buffer_pool).lift().wait(wait_scope)
    }).unwrap();
}
<commit_msg>empithen<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

//! Echo server with a bounded buffer pool.

extern crate gj;
use std::net::ToSocketAddrs;
use std::cell::RefCell;
use std::rc::Rc;
use gj::io::{AsyncRead, AsyncWrite};

struct BufferPool {
    buffers: Vec<Vec<u8>>,
    fulfiller: Option<Box<gj::PromiseFulfiller<Vec<u8>, ::std::io::Error>>>,
}

impl BufferPool {
    pub fn new(num_buffers: usize) -> BufferPool {
        BufferPool { buffers: vec![vec![0; 1024]; num_buffers], fulfiller: None }
    }

    pub fn pop(&mut self) -> gj::Promise<Vec<u8>, ::std::io::Error> {
        match self.buffers.pop() {
            Some(buf) => gj::Promise::fulfilled(buf),
            None => {
                let (promise, fulfiller) = gj::new_promise_and_fulfiller();
                assert!(self.fulfiller.is_none(), "only supports one waiting task");
                self.fulfiller = Some(fulfiller);
                promise
            }
        }
    }

    pub fn push(&mut self, buf: Vec<u8>) {
        match self.fulfiller.take() {
            Some(fulfiller) => fulfiller.fulfill(buf),
            None => self.buffers.push(buf),
        }
    }
}

struct Reaper {
    buffer_pool: Rc<RefCell<BufferPool>>,
}

impl gj::TaskReaper<ThreadedState, gj::io::Error<ThreadedState>> for Reaper {
    fn task_succeeded(&mut self, (_, buf): ThreadedState) {
        self.buffer_pool.borrow_mut().push(buf);
    }
    fn task_failed(&mut self, error: gj::io::Error<ThreadedState>) {
        self.buffer_pool.borrow_mut().push(error.state.1);
        println!("Task failed: {}", error.error);
    }
}

type ThreadedState = (::gj::io::tcp::Stream, Vec<u8>);

fn echo<S,B>(stream: S, buf: B) -> gj::Promise<(S, B), gj::io::Error<(S, B)>>
    where S: AsyncRead + AsyncWrite, B: ::std::ops::DerefMut<Target=[u8]> + 'static
{
    stream.try_read(buf, 1).then(move |(stream, buf, n)| {
        if n == 0 {
            // EOF
            Ok(gj::Promise::fulfilled((stream, buf)))
        } else {
            Ok(stream.write(gj::io::Slice::new(buf, n)).then_else(move |r| match r {
                Ok((stream, slice)) => Ok(echo(stream, slice.buf)),
                Err(gj::io::Error {state: (stream, slice), error}) =>
                    Err(gj::io::Error::new((stream, slice.buf), error)),
            }))
        }
    })
}

fn accept_loop(receiver: gj::io::tcp::Listener,
               mut task_set: gj::TaskSet<ThreadedState, gj::io::Error<ThreadedState>>,
               buffer_pool: Rc<RefCell<BufferPool>>)
               -> gj::Promise<(), ::std::io::Error>
{
    let buf_promise = buffer_pool.borrow_mut().pop();
    buf_promise.then(move |buf| {
        Ok(receiver.accept().lift().then(move |(receiver, stream)| {
            task_set.add(echo(stream, buf));
            Ok(accept_loop(receiver, task_set, buffer_pool))
        }))
    })
}

pub fn main() {
    let args: Vec<String> = ::std::env::args().collect();
    if args.len() != 2 {
        println!("usage: {} HOST:PORT", args[0]);
        return;
    }
    let buffer_pool = Rc::new(RefCell::new(BufferPool::new(64)));

    gj::EventLoop::top_level(move |wait_scope| {

        let addr = try!(args[1].to_socket_addrs()).next().expect("could not parse address");
        let listener = try!(::gj::io::tcp::Listener::bind(addr));
        let reaper = Box::new(Reaper { buffer_pool: buffer_pool.clone() });
        accept_loop(listener, gj::TaskSet::new(reaper), buffer_pool).lift().wait(wait_scope)
    }).unwrap();
}
<|endoftext|>


<commit_before>//! Assign unique identifiers to records.

use timely::dataflow::Scope;

use ::{Collection, Data, Hashable};
use ::lattice::Lattice;
use ::operators::*;
use ::difference::Abelian;

/// Assign unique identifiers to elements of a collection.
pub trait Identifiers<G: Scope, D: Data, R: Abelian> {
    /// Assign unique identifiers to elements of a collection.
    ///
    /// # Example
    /// ```
    /// extern crate timely;
    /// extern crate differential_dataflow;
    ///
    /// use differential_dataflow::input::Input;
    /// use differential_dataflow::algorithms::identifiers::Identifiers;
    /// use differential_dataflow::operators::Threshold;
    ///
    /// fn main() {
    ///     ::timely::example(|scope| {
    ///
    ///         let identifiers =
    ///         scope.new_collection_from(1 .. 10).1
    ///              .identifiers()
    ///              // assert no conflicts
    ///              .map(|(data, id)| id)
    ///              .threshold(|_id,cnt| if cnt > 1 { 1 } else { 0 })
    ///              .assert_empty();
    ///     });
    /// }
    /// ```
    fn identifiers(&self) -> Collection<G, (D, u64), R>;
}

impl<G, D, R> Identifiers<G, D, R> for Collection<G, D, R>
where
    G: Scope,
    G::Timestamp: Lattice,
    D: Data+::std::hash::Hash,
    R: Abelian,
{
    fn identifiers(&self) -> Collection<G, (D, u64), R> {

        // The design here is that we iteratively develop a collection
        // of pairs (round, record), where each pair is a proposal that
        // the hash for record should be (round, record).hashed().
        //
        // Iteratively, any colliding pairs establish a winner (the one
        // with the lower round, breaking ties by record), and indicate
        // that the losers should increment their round and try again.
        //
        // Non-obviously, this happens via a `group` operator that yields
        // additions and subtractions of losers, rather than reproducing
        // the winners. This is done under the premise that losers are
        // very rare, and maintaining winners in both the input and output
        // of `group` is an unneccesary duplication.

        use collection::AsCollection;

        let init = self.map(|record| (0, record));
        timely::dataflow::operators::generic::operator::empty(&init.scope())
            .as_collection()
            .iterate(|diff|
                init.enter(&diff.scope())
                    .concat(&diff)
                    .map(|pair| (pair.hashed(), pair))
                    .group(|_hash, input, output| {
                        // keep round-positive records as changes.
                        let ((round, record), count) = &input[0];
                        if *round > 0 {
                            output.push(((0, record.clone()), -count.clone()));
                            output.push(((*round, record.clone()), count.clone()));
                        }
                        // if any losers, increment their rounds.
                        for ((round, record), count) in input[1..].iter() {
                            output.push(((0, record.clone()), -count.clone()));
                            output.push(((*round+1, record.clone()), count.clone()));
                        }
                    })
                    .map(|(_hash, pair)| pair)
            )
            .concat(&init)
            .map(|pair| { let hash = pair.hashed(); (pair.1, hash) })
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn are_unique() {

        // It is hard to test the above method, because we would want
        // to exercise the case with hash collisions. Instead, we test
        // a version with a crippled hash function to see that even if
        // there are collisions, everyone gets a unique identifier.

        use ::input::Input;
        use ::operators::{Threshold, Group};
        use ::operators::iterate::Iterate;

        ::timely::example(|scope| {

            let input = scope.new_collection_from(1 .. 10).1;

            use collection::AsCollection;

            let init = input.map(|record| (0, record));
            timely::dataflow::operators::generic::operator::empty(&init.scope())
                .as_collection()
                .iterate(|diff|
                    init.enter(&diff.scope())
                        .concat(&diff)
                        .map(|(round, num)| ((round + num) / 10, (round, num)))
                        .group(|_hash, input, output| {
                            // keep round-positive records as changes.
                            let ((round, record), count) = &input[0];
                            if *round > 0 {
                                output.push(((0, record.clone()), -*count));
                                output.push(((*round, record.clone()), *count));
                            }
                            // if any losers, increment their rounds.
                            for ((round, record), count) in input[1..].iter() {
                                output.push(((0, record.clone()), -*count));
                                output.push(((*round+1, record.clone()), *count));
                            }
                        })
                        .map(|(_hash, pair)| pair)
                )
                .concat(&init)
                .map(|(round, num)| { (num, (round + num) / 10) })
                .map(|(_data, id)| id)
                .threshold(|_id,cnt| if cnt > 1 { 1 } else { 0 })
                .assert_empty();
        });
    }
}<commit_msg>update threshold use<commit_after>//! Assign unique identifiers to records.

use timely::dataflow::Scope;

use ::{Collection, Data, Hashable};
use ::lattice::Lattice;
use ::operators::*;
use ::difference::Abelian;

/// Assign unique identifiers to elements of a collection.
pub trait Identifiers<G: Scope, D: Data, R: Abelian> {
    /// Assign unique identifiers to elements of a collection.
    ///
    /// # Example
    /// ```
    /// extern crate timely;
    /// extern crate differential_dataflow;
    ///
    /// use differential_dataflow::input::Input;
    /// use differential_dataflow::algorithms::identifiers::Identifiers;
    /// use differential_dataflow::operators::Threshold;
    ///
    /// fn main() {
    ///     ::timely::example(|scope| {
    ///
    ///         let identifiers =
    ///         scope.new_collection_from(1 .. 10).1
    ///              .identifiers()
    ///              // assert no conflicts
    ///              .map(|(data, id)| id)
    ///              .threshold(|_id,cnt| if cnt > &1 { 1 } else { 0 })
    ///              .assert_empty();
    ///     });
    /// }
    /// ```
    fn identifiers(&self) -> Collection<G, (D, u64), R>;
}

impl<G, D, R> Identifiers<G, D, R> for Collection<G, D, R>
where
    G: Scope,
    G::Timestamp: Lattice,
    D: Data+::std::hash::Hash,
    R: Abelian,
{
    fn identifiers(&self) -> Collection<G, (D, u64), R> {

        // The design here is that we iteratively develop a collection
        // of pairs (round, record), where each pair is a proposal that
        // the hash for record should be (round, record).hashed().
        //
        // Iteratively, any colliding pairs establish a winner (the one
        // with the lower round, breaking ties by record), and indicate
        // that the losers should increment their round and try again.
        //
        // Non-obviously, this happens via a `group` operator that yields
        // additions and subtractions of losers, rather than reproducing
        // the winners. This is done under the premise that losers are
        // very rare, and maintaining winners in both the input and output
        // of `group` is an unneccesary duplication.

        use collection::AsCollection;

        let init = self.map(|record| (0, record));
        timely::dataflow::operators::generic::operator::empty(&init.scope())
            .as_collection()
            .iterate(|diff|
                init.enter(&diff.scope())
                    .concat(&diff)
                    .map(|pair| (pair.hashed(), pair))
                    .group(|_hash, input, output| {
                        // keep round-positive records as changes.
                        let ((round, record), count) = &input[0];
                        if *round > 0 {
                            output.push(((0, record.clone()), -count.clone()));
                            output.push(((*round, record.clone()), count.clone()));
                        }
                        // if any losers, increment their rounds.
                        for ((round, record), count) in input[1..].iter() {
                            output.push(((0, record.clone()), -count.clone()));
                            output.push(((*round+1, record.clone()), count.clone()));
                        }
                    })
                    .map(|(_hash, pair)| pair)
            )
            .concat(&init)
            .map(|pair| { let hash = pair.hashed(); (pair.1, hash) })
    }
}

#[cfg(test)]
mod tests {

    #[test]
    fn are_unique() {

        // It is hard to test the above method, because we would want
        // to exercise the case with hash collisions. Instead, we test
        // a version with a crippled hash function to see that even if
        // there are collisions, everyone gets a unique identifier.

        use ::input::Input;
        use ::operators::{Threshold, Group};
        use ::operators::iterate::Iterate;

        ::timely::example(|scope| {

            let input = scope.new_collection_from(1 .. 10).1;

            use collection::AsCollection;

            let init = input.map(|record| (0, record));
            timely::dataflow::operators::generic::operator::empty(&init.scope())
                .as_collection()
                .iterate(|diff|
                    init.enter(&diff.scope())
                        .concat(&diff)
                        .map(|(round, num)| ((round + num) / 10, (round, num)))
                        .group(|_hash, input, output| {
                            // keep round-positive records as changes.
                            let ((round, record), count) = &input[0];
                            if *round > 0 {
                                output.push(((0, record.clone()), -*count));
                                output.push(((*round, record.clone()), *count));
                            }
                            // if any losers, increment their rounds.
                            for ((round, record), count) in input[1..].iter() {
                                output.push(((0, record.clone()), -*count));
                                output.push(((*round+1, record.clone()), *count));
                            }
                        })
                        .map(|(_hash, pair)| pair)
                )
                .concat(&init)
                .map(|(round, num)| { (num, (round + num) / 10) })
                .map(|(_data, id)| id)
                .threshold(|_id,cnt| if cnt > &1 { 1 } else { 0 })
                .assert_empty();
        });
    }
}<|endoftext|>


<commit_before>use crate::{
    analysis::{
        bounds::Bounds,
        imports::Imports,
        properties::{get_property_ref_modes, Property},
        rust_type::*,
    },
    config::{self, GObject},
    env::Env,
    library,
    traits::*,
};
use std::collections::HashSet;

pub fn analyze(
    env: &Env,
    props: &[library::Property],
    type_tid: library::TypeId,
    obj: &GObject,
    imports: &mut Imports,
) -> Vec<Property> {
    if !obj.generate_builder {
        return Vec::new();
    }

    let mut names = HashSet::<String>::new();
    let mut builder_properties = analyze_properties(env, props, obj, imports, &mut names);

    for &super_tid in env.class_hierarchy.supertypes(type_tid) {
        let type_ = env.type_(super_tid);

        let super_properties = match type_ {
            library::Type::Class(class) => &class.properties,
            library::Type::Interface(iface) => &iface.properties,
            _ => continue,
        };
        let super_obj =
            if let Some(super_obj) = env.config.objects.get(&super_tid.full_name(&env.library)) {
                super_obj
            } else {
                continue;
            };

        let new_builder_properties =
            analyze_properties(env, super_properties, super_obj, imports, &mut names);
        builder_properties.extend(new_builder_properties);
    }

    builder_properties
}

fn analyze_properties(
    env: &Env,
    props: &[library::Property],
    obj: &GObject,
    imports: &mut Imports,
    names: &mut HashSet<String>,
) -> Vec<Property> {
    let mut builder_properties = Vec::new();

    for prop in props {
        if names.contains(&prop.name) {
            continue;
        }
        let configured_properties = obj.properties.matched(&prop.name);
        if configured_properties.iter().any(|f| f.ignore) {
            continue;
        }

        if env.is_totally_deprecated(prop.deprecated_version) {
            continue;
        }
        let builder = analyze_property(env, prop, &configured_properties, imports);
        if let Some(builder) = builder {
            builder_properties.push(builder);
            names.insert(prop.name.clone());
        }
    }

    builder_properties
}

fn analyze_property(
    env: &Env,
    prop: &library::Property,
    configured_properties: &[&config::properties::Property],
    imports: &mut Imports,
) -> Option<Property> {
    let prop_version = configured_properties
        .iter()
        .filter_map(|f| f.version)
        .min()
        .or(prop.version)
        .or_else(|| Some(env.config.min_cfg_version));

    let for_builder = prop.construct_only || prop.construct || prop.writable;
    if !for_builder {
        return None;
    }
    imports.set_defaults(prop_version, &None);
    let type_str = used_rust_type(env, prop.typ, false);
    if let Ok(ref s) = type_str {
        if !s.contains("GString") {
            imports.add_used_type(s);
        }
    }

    let (get_out_ref_mode, set_in_ref_mode, nullable) = get_property_ref_modes(env, prop);

    let mut bounds = Bounds::default();
    if let Some(bound) = Bounds::type_for(env, prop.typ, nullable) {
        imports.add("glib::object::IsA");
        bounds.add_parameter(&name, &type_str.into_string(), bound, false);
    }

    Some(Property {
        name: prop.name.clone(),
        var_name: String::new(),
        typ: prop.typ,
        is_get: false,
        func_name: String::new(),
        nullable,
        get_out_ref_mode,
        set_in_ref_mode,
        set_bound: None,
        bounds,
        version: prop_version,
        deprecated_version: prop.deprecated_version,
    })
}
<commit_msg>Fix merge conflict<commit_after>use crate::{
    analysis::{
        bounds::Bounds,
        imports::Imports,
        properties::{get_property_ref_modes, Property},
        rust_type::*,
    },
    config::{self, GObject},
    env::Env,
    library,
    traits::*,
};
use std::collections::HashSet;

pub fn analyze(
    env: &Env,
    props: &[library::Property],
    type_tid: library::TypeId,
    obj: &GObject,
    imports: &mut Imports,
) -> Vec<Property> {
    if !obj.generate_builder {
        return Vec::new();
    }

    let mut names = HashSet::<String>::new();
    let mut builder_properties = analyze_properties(env, props, obj, imports, &mut names);

    for &super_tid in env.class_hierarchy.supertypes(type_tid) {
        let type_ = env.type_(super_tid);

        let super_properties = match type_ {
            library::Type::Class(class) => &class.properties,
            library::Type::Interface(iface) => &iface.properties,
            _ => continue,
        };
        let super_obj =
            if let Some(super_obj) = env.config.objects.get(&super_tid.full_name(&env.library)) {
                super_obj
            } else {
                continue;
            };

        let new_builder_properties =
            analyze_properties(env, super_properties, super_obj, imports, &mut names);
        builder_properties.extend(new_builder_properties);
    }

    builder_properties
}

fn analyze_properties(
    env: &Env,
    props: &[library::Property],
    obj: &GObject,
    imports: &mut Imports,
    names: &mut HashSet<String>,
) -> Vec<Property> {
    let mut builder_properties = Vec::new();

    for prop in props {
        if names.contains(&prop.name) {
            continue;
        }
        let configured_properties = obj.properties.matched(&prop.name);
        if configured_properties.iter().any(|f| f.ignore) {
            continue;
        }

        if env.is_totally_deprecated(prop.deprecated_version) {
            continue;
        }
        let builder = analyze_property(env, prop, &configured_properties, imports);
        if let Some(builder) = builder {
            builder_properties.push(builder);
            names.insert(prop.name.clone());
        }
    }

    builder_properties
}

fn analyze_property(
    env: &Env,
    prop: &library::Property,
    configured_properties: &[&config::properties::Property],
    imports: &mut Imports,
) -> Option<Property> {
    let prop_version = configured_properties
        .iter()
        .filter_map(|f| f.version)
        .min()
        .or(prop.version)
        .or_else(|| Some(env.config.min_cfg_version));

    let for_builder = prop.construct_only || prop.construct || prop.writable;
    if !for_builder {
        return None;
    }
    imports.set_defaults(prop_version, &None);
    let type_str = used_rust_type(env, prop.typ, false);
    if let Ok(ref s) = type_str {
        if !s.contains("GString") {
            imports.add_used_type(s);
        }
    }

    let (get_out_ref_mode, set_in_ref_mode, nullable) = get_property_ref_modes(env, prop);

    let mut bounds = Bounds::default();
    if let Some(bound) = Bounds::type_for(env, prop.typ, nullable) {
        imports.add("glib::object::IsA");
        bounds.add_parameter(&prop.name, &type_str.into_string(), bound, false);
    }

    Some(Property {
        name: prop.name.clone(),
        var_name: String::new(),
        typ: prop.typ,
        is_get: false,
        func_name: String::new(),
        nullable,
        get_out_ref_mode,
        set_in_ref_mode,
        set_bound: None,
        bounds,
        version: prop_version,
        deprecated_version: prop.deprecated_version,
    })
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

pub mod serial;
pub mod processor;
pub mod task;
pub mod irq;
pub mod switch;
mod gdt;
mod pit;
mod start;
mod syscall;

use core::ptr::read_volatile;
use consts::*;
use logging::*;
pub use arch::x86_64::kernel::syscall::syscall_handler;

#[repr(C)]
struct KernelHeader {
	magic_number: u32,
	version: u32,
	mem_limit: u64,
	num_cpus: u32,
	file_addr: u64,
	file_length: u64
}

/// Kernel header to announce machine features
#[link_section = ".kheader"]
static KERNEL_HEADER: KernelHeader = KernelHeader {
	magic_number: 0xDEADC0DEu32,
	version: 1,
	mem_limit: 0,
	num_cpus: 1,
	file_addr: 0,
	file_length: 0
};

pub fn get_memfile() -> (u64, u64) {
	let addr = unsafe { read_volatile(&KERNEL_HEADER.file_addr) };
	let len = unsafe { read_volatile(&KERNEL_HEADER.file_length) };

	(addr, len)
}

pub fn get_memory_size() -> usize {
		unsafe { read_volatile(&KERNEL_HEADER.mem_limit) as usize }
}

pub fn register_task() {
	let sel: u16 = 6u16 << 3;

	unsafe { asm!("ltr $0" :: "r"(sel) :: "volatile"); }
}

#[inline(never)]
#[naked]
pub fn jump_to_user_land(entry: u64) -> !
{
	let ds = 0x23u64;
	let cs = 0x2bu64;
	let stack = USER_STACK - 0x100;

	info!("Set user space stack to 0x{:x}", stack);

	unsafe {
		asm!("swapgs; mov $0, %ds; mov $0, %es; push $0; push $3; pushfq; push $1; push $2; iretq"
			:: "r"(ds), "r"(cs), "r"(entry as u64), "r"(stack)
			:: "volatile");
	}

	loop {
		processor::halt();
	}
}

/// This macro can be used to call system functions from user-space
#[macro_export]
macro_rules! syscall {
	($arg0:expr)
		=> ( arch::x86_64::kernel::syscall0($arg0 as u64) );

	($arg0:expr, $arg1:expr)
		=> ( arch::x86_64::kernel::syscall1($arg0 as u64, $arg1 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr)
		=> ( arch::x86_64::kernel::syscall2($arg0 as u64, $arg1 as u64, $arg2 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr)
		=> ( arch::x86_64::kernel::syscall3($arg0 as u64, $arg1 as u64, $arg2 as u64, $arg3 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr)
		=> ( arch::x86_64::kernel::syscall4($arg0 as u64, $arg1 as u64, $arg2 as u64, $arg3 as u64, $arg4 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr)
		=> ( arch::x86_64::kernel::syscall5($arg0 as u64, $arg1 as u64, $arg2 as u64, $arg3 as u64, $arg4 as u64, $arg5 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr)
		=> ( arch::x86_64::kernel::syscall6($arg0 as u64, $arg1 as u64, $arg2 as u64, $arg3 as u64, $arg4 as u64, $arg5 as u64, $arg6 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr, $arg7:expr)
		=> ( arch::x86_64::kernel::syscall7($arg0 as u64, $arg1 as u64, $arg2 as u64, $arg3 as u64, $arg4 as u64, $arg5 as u64, $arg6 as u64, $arg7 as u64) );
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall0(arg0: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall" : "={rax}" (ret) : "{rax}" (arg0) : "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall1(arg0: u64, arg1: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret) : "{rax}" (arg0), "{rdi}" (arg1)
						: "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall2(arg0: u64, arg1: u64, arg2: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret) : "{rax}" (arg0), "{rdi}" (arg1), "{rsi}" (arg2)
						: "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall3(arg0: u64, arg1: u64, arg2: u64, arg3: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret) : "{rax}" (arg0), "{rdi}" (arg1), "{rsi}" (arg2),
						"{rdx}" (arg3) : "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall4(arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret)
						: "{rax}"  (arg0), "{rdi}"  (arg1), "{rsi}"  (arg2), "{rdx}"  (arg3),
						"{r10}"  (arg4) : "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall5(arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret)
						: "{rax}" (arg0), "{rdi}" (arg1), "{rsi}" (arg2), "{rdx}" (arg3),
						"{r10}" (arg4), "{r8}" (arg5) : "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall6(arg0: u64,
	arg1: u64,
	arg2: u64,
	arg3: u64,
	arg4: u64,
	arg5: u64,
	arg6: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret) : "{rax}" (arg0), "{rdi}" (arg1), "{rsi}" (arg2),
						"{rdx}" (arg3), "{r10}" (arg4), "{r8}" (arg5), "{r9}" (arg6)
						: "rcx", "r11", "memory" : "volatile");
	}
	ret
}

/// Initialize module, must be called once, and only once
pub fn init() {
	processor::init();
	gdt::init();
	irq::init();
	pit::init();
}
<commit_msg>add check if we use the right kernel header<commit_after>// Copyright (c) 2017-2018 Stefan Lankes, RWTH Aachen University
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

pub mod serial;
pub mod processor;
pub mod task;
pub mod irq;
pub mod switch;
mod gdt;
mod pit;
mod start;
mod syscall;

use core::ptr::read_volatile;
use consts::*;
use logging::*;
pub use arch::x86_64::kernel::syscall::syscall_handler;

#[repr(C)]
struct KernelHeader {
	magic_number: u32,
	version: u32,
	mem_limit: u64,
	num_cpus: u32,
	file_addr: u64,
	file_length: u64
}

/// Kernel header to announce machine features
#[link_section = ".kheader"]
static KERNEL_HEADER: KernelHeader = KernelHeader {
	magic_number: 0xDEADC0DEu32,
	version: 0,
	mem_limit: 0,
	num_cpus: 1,
	file_addr: 0,
	file_length: 0
};

pub fn get_memfile() -> (u64, u64) {
	let version = unsafe { read_volatile(&KERNEL_HEADER.version) };
	let addr = unsafe { read_volatile(&KERNEL_HEADER.file_addr) };
	let len = unsafe { read_volatile(&KERNEL_HEADER.file_length) };

	if version > 0 {
		(addr, len)
	} else {
		(0, 0)
	}
}

pub fn get_memory_size() -> usize {
		unsafe { read_volatile(&KERNEL_HEADER.mem_limit) as usize }
}

pub fn register_task() {
	let sel: u16 = 6u16 << 3;

	unsafe { asm!("ltr $0" :: "r"(sel) :: "volatile"); }
}

#[inline(never)]
#[naked]
pub fn jump_to_user_land(entry: u64) -> !
{
	let ds = 0x23u64;
	let cs = 0x2bu64;
	let stack = USER_STACK - 0x100;

	info!("Set user space stack to 0x{:x}", stack);

	unsafe {
		asm!("swapgs; mov $0, %ds; mov $0, %es; push $0; push $3; pushfq; push $1; push $2; iretq"
			:: "r"(ds), "r"(cs), "r"(entry as u64), "r"(stack)
			:: "volatile");
	}

	loop {
		processor::halt();
	}
}

/// This macro can be used to call system functions from user-space
#[macro_export]
macro_rules! syscall {
	($arg0:expr)
		=> ( arch::x86_64::kernel::syscall0($arg0 as u64) );

	($arg0:expr, $arg1:expr)
		=> ( arch::x86_64::kernel::syscall1($arg0 as u64, $arg1 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr)
		=> ( arch::x86_64::kernel::syscall2($arg0 as u64, $arg1 as u64, $arg2 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr)
		=> ( arch::x86_64::kernel::syscall3($arg0 as u64, $arg1 as u64, $arg2 as u64, $arg3 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr)
		=> ( arch::x86_64::kernel::syscall4($arg0 as u64, $arg1 as u64, $arg2 as u64, $arg3 as u64, $arg4 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr)
		=> ( arch::x86_64::kernel::syscall5($arg0 as u64, $arg1 as u64, $arg2 as u64, $arg3 as u64, $arg4 as u64, $arg5 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr)
		=> ( arch::x86_64::kernel::syscall6($arg0 as u64, $arg1 as u64, $arg2 as u64, $arg3 as u64, $arg4 as u64, $arg5 as u64, $arg6 as u64) );

	($arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr, $arg6:expr, $arg7:expr)
		=> ( arch::x86_64::kernel::syscall7($arg0 as u64, $arg1 as u64, $arg2 as u64, $arg3 as u64, $arg4 as u64, $arg5 as u64, $arg6 as u64, $arg7 as u64) );
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall0(arg0: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall" : "={rax}" (ret) : "{rax}" (arg0) : "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall1(arg0: u64, arg1: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret) : "{rax}" (arg0), "{rdi}" (arg1)
						: "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall2(arg0: u64, arg1: u64, arg2: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret) : "{rax}" (arg0), "{rdi}" (arg1), "{rsi}" (arg2)
						: "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall3(arg0: u64, arg1: u64, arg2: u64, arg3: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret) : "{rax}" (arg0), "{rdi}" (arg1), "{rsi}" (arg2),
						"{rdx}" (arg3) : "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall4(arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret)
						: "{rax}"  (arg0), "{rdi}"  (arg1), "{rsi}"  (arg2), "{rdx}"  (arg3),
						"{r10}"  (arg4) : "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall5(arg0: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret)
						: "{rax}" (arg0), "{rdi}" (arg1), "{rsi}" (arg2), "{rdx}" (arg3),
						"{r10}" (arg4), "{r8}" (arg5) : "rcx", "r11", "memory" : "volatile");
	}
	ret
}

#[inline(always)]
#[allow(unused_mut)]
pub fn syscall6(arg0: u64,
	arg1: u64,
	arg2: u64,
	arg3: u64,
	arg4: u64,
	arg5: u64,
	arg6: u64) -> u64 {
	let mut ret: u64;
	unsafe {
		asm!("syscall"	: "={rax}" (ret) : "{rax}" (arg0), "{rdi}" (arg1), "{rsi}" (arg2),
						"{rdx}" (arg3), "{r10}" (arg4), "{r8}" (arg5), "{r9}" (arg6)
						: "rcx", "r11", "memory" : "volatile");
	}
	ret
}

/// Initialize module, must be called once, and only once
pub fn init() {
	processor::init();
	gdt::init();
	irq::init();
	pit::init();
}
<|endoftext|>


<commit_before>use Sink;
use executor;

/// A sink combinator which converts an asynchronous sink to a **blocking
/// sink**.
///
/// Created by the `Sink::wait` method, this function transforms any sink into a
/// blocking version. This is implemented by blocking the current thread when a
/// sink is otherwise unable to make progress.
#[must_use = "sinks do nothing unless polled"]
#[derive(Debug)]
pub struct Wait<Si> {
    sink: executor::Spawn<Si>,
}

pub fn new<Si: Sink>(s: Si) -> Wait<Si> {
    Wait {
        sink: executor::spawn(s),
    }
}

impl<Si: Sink> Wait<Si> {
    /// Sends a value to this sink, blocking the current thread until it's able
    /// to do so.
    ///
    /// This function will take the `value` provided and call the underlying
    /// sink's `start_send` function until it's ready to accept the value. If
    /// the function returns `Pending` then the current thread is blocked
    /// until it is otherwise ready to accept the value.
    ///
    /// # Return value
    ///
    /// If `Ok(())` is returned then the `value` provided was successfully sent
    /// along the sink, and if `Err(e)` is returned then an error occurred
    /// which prevented the value from being sent.
    pub fn send(&mut self, value: Si::SinkItem) -> Result<(), Si::SinkError> {
        self.sink.wait_send(value)
    }

    /// Flushes any buffered data in this sink, blocking the current thread
    /// until it's entirely flushed.
    ///
    /// This function will call the underlying sink's `flush` method
    /// until it returns that it's ready to proceed. If the method returns
    /// `Pending` the current thread will be blocked until it's otherwise
    /// ready to proceed.
    pub fn flush(&mut self) -> Result<(), Si::SinkError> {
        self.sink.wait_flush()
    }

    /// Close this sink, blocking the current thread until it's entirely closed.
    ///
    /// This function will call the underlying sink's `close` method
    /// until it returns that it's closed. If the method returns
    /// `Pending` the current thread will be blocked until it's otherwise
    /// closed.
    pub fn close(&mut self) -> Result<(), Si::SinkError> {
        self.sink.wait_close()
    }
}
<commit_msg>Remove unused sink/wait.rs<commit_after><|endoftext|>