<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    counters,
    errors::JsonRpcError,
    methods::{build_registry, JsonRpcRequest, JsonRpcService, RpcRegistry},
};
use futures::future::join_all;
use libra_config::config::{NodeConfig, RoleType};
use libra_mempool::MempoolClientSender;
use libra_types::ledger_info::LedgerInfoWithSignatures;
use serde_json::{map::Map, Value};
use std::{net::SocketAddr, sync::Arc};
use storage_interface::DbReader;
use tokio::runtime::{Builder, Runtime};
use warp::{
    reject::{self, Reject},
    Filter,
};

/// Creates HTTP server (warp-based) that serves JSON RPC requests
/// Returns handle to corresponding Tokio runtime
pub fn bootstrap(
    address: SocketAddr,
    libra_db: Arc<dyn DbReader>,
    mp_sender: MempoolClientSender,
    role: RoleType,
) -> Runtime {
    let runtime = Builder::new()
        .thread_name("rpc-")
        .threaded_scheduler()
        .enable_all()
        .build()
        .expect("[rpc] failed to create runtime");

    let registry = Arc::new(build_registry());
    let service = JsonRpcService::new(libra_db, mp_sender, role);

    let handler = warp::any()
        .and(warp::path::end())
        .and(warp::post())
        .and(warp::header::exact("content-type", "application/json"))
        .and(warp::body::json())
        .and(warp::any().map(move || service.clone()))
        .and(warp::any().map(move || Arc::clone(&registry)))
        .and_then(rpc_endpoint);

    // Ensure that we actually bind to the socket first before spawning the
    // server tasks. This helps in tests to prevent races where a client attempts
    // to make a request before the server task is actually listening on the
    // socket.
    //
    // Note: we need to enter the runtime context first to actually bind, since
    //       tokio TcpListener can only be bound inside a tokio context.
    let server = runtime.enter(move || warp::serve(handler).bind(address));
    runtime.handle().spawn(server);
    runtime
}

/// Creates JSON RPC endpoint by given node config
pub fn bootstrap_from_config(
    config: &NodeConfig,
    libra_db: Arc<dyn DbReader>,
    mp_sender: MempoolClientSender,
) -> Runtime {
    bootstrap(config.rpc.address, libra_db, mp_sender, config.base.role)
}

/// JSON RPC entry point
/// Handles all incoming rpc requests
/// Performs routing based on methods defined in `registry`
async fn rpc_endpoint(
    data: Value,
    service: JsonRpcService,
    registry: Arc<RpcRegistry>,
) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
    // take snapshot of latest version of DB to be used across all requests, especially for batched requests
    let ledger_info = service
        .get_latest_ledger_info()
        .map_err(|_| reject::custom(DatabaseError))?;
    if let Value::Array(requests) = data {
        // batch API call
        let futures = requests.into_iter().map(|req| {
            rpc_request_handler(
                req,
                service.clone(),
                Arc::clone(&registry),
                ledger_info.clone(),
            )
        });
        let responses = join_all(futures).await;
        Ok(Box::new(warp::reply::json(&Value::Array(responses))))
    } else {
        // single API call
        let resp = rpc_request_handler(data, service, registry, ledger_info).await;
        Ok(Box::new(warp::reply::json(&resp)))
    }
}

/// Handler of single RPC request
/// Performs validation and executes corresponding rpc handler
async fn rpc_request_handler(
    req: Value,
    service: JsonRpcService,
    registry: Arc<RpcRegistry>,
    ledger_info: LedgerInfoWithSignatures,
) -> Value {
    let request: Map<String, Value>;
    let mut response = Map::new();

    // set defaults: protocol version to 2.0, request id to null
    response.insert("jsonrpc".to_string(), Value::String("2.0".to_string()));
    response.insert("id".to_string(), Value::Null);

    match req {
        Value::Object(data) => {
            request = data;
        }
        _ => {
            response.insert(
                "error".to_string(),
                JsonRpcError::invalid_request().serialize(),
            );
            counters::INVALID_REQUESTS
                .with_label_values(&["invalid_format"])
                .inc();
            return Value::Object(response);
        }
    }

    // parse request id
    match parse_request_id(&request) {
        Ok(request_id) => {
            response.insert("id".to_string(), request_id);
        }
        Err(err) => {
            response.insert("error".to_string(), err.serialize());
            counters::INVALID_REQUESTS
                .with_label_values(&["invalid_format"])
                .inc();
            return Value::Object(response);
        }
    };

    // verify protocol version
    if let Err(err) = verify_protocol(&request) {
        response.insert("error".to_string(), err.serialize());
        counters::INVALID_REQUESTS
            .with_label_values(&["invalid_format"])
            .inc();
        return Value::Object(response);
    }

    // parse parameters
    let params;
    match request.get("params") {
        Some(Value::Array(parameters)) => {
            params = parameters.to_vec();
        }
        _ => {
            response.insert(
                "error".to_string(),
                JsonRpcError::invalid_params().serialize(),
            );
            counters::INVALID_REQUESTS
                .with_label_values(&["invalid_params"])
                .inc();
            return Value::Object(response);
        }
    }

    let request_params = JsonRpcRequest {
        ledger_info,
        params,
    };
    // get rpc handler
    match request.get("method") {
        Some(Value::String(name)) => match registry.get(name) {
            Some(handler) => match handler(service, request_params).await {
                Ok(result) => {
                    response.insert("result".to_string(), result);
                    counters::REQUESTS
                        .with_label_values(&[name, "success"])
                        .inc();
                }
                Err(err) => {
                    // check for custom error
                    if let Some(custom_error) = err.downcast_ref::<JsonRpcError>() {
                        response.insert("error".to_string(), custom_error.clone().serialize());
                    } else {
                        response.insert(
                            "error".to_string(),
                            JsonRpcError::internal_error(err.to_string()).serialize(),
                        );
                    }
                    counters::REQUESTS.with_label_values(&[name, "fail"]).inc();
                }
            },
            None => {
                response.insert(
                    "error".to_string(),
                    JsonRpcError::method_not_found().serialize(),
                );
                counters::INVALID_REQUESTS
                    .with_label_values(&["method_not_found"])
                    .inc();
            }
        },
        _ => {
            response.insert(
                "error".to_string(),
                JsonRpcError::invalid_request().serialize(),
            );
            counters::INVALID_REQUESTS
                .with_label_values(&["invalid_method"])
                .inc();
        }
    }

    Value::Object(response)
}

fn parse_request_id(request: &Map<String, Value>) -> Result<Value, JsonRpcError> {
    match request.get("id") {
        Some(req_id) => {
            if req_id.is_string() || req_id.is_number() || req_id.is_null() {
                Ok(req_id.clone())
            } else {
                Err(JsonRpcError::invalid_request())
            }
        }
        None => Ok(Value::Null),
    }
}

fn verify_protocol(request: &Map<String, Value>) -> Result<(), JsonRpcError> {
    if let Some(Value::String(protocol)) = request.get("jsonrpc") {
        if protocol == "2.0" {
            return Ok(());
        }
    }
    Err(JsonRpcError::invalid_request())
}

/// Warp rejection types
#[derive(Debug)]
struct DatabaseError;

impl Reject for DatabaseError {}
<commit_msg>[JSON RPC] Refactor set_error_response()<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{
    counters,
    errors::JsonRpcError,
    methods::{build_registry, JsonRpcRequest, JsonRpcService, RpcRegistry},
};
use futures::future::join_all;
use libra_config::config::{NodeConfig, RoleType};
use libra_mempool::MempoolClientSender;
use libra_types::ledger_info::LedgerInfoWithSignatures;
use serde_json::{map::Map, Value};
use std::{net::SocketAddr, sync::Arc};
use storage_interface::DbReader;
use tokio::runtime::{Builder, Runtime};
use warp::{
    reject::{self, Reject},
    Filter,
};

// Counter labels for runtime metrics
const LABEL_FAIL: &str = "fail";
const LABEL_INVALID_FORMAT: &str = "invalid_format";
const LABEL_INVALID_METHOD: &str = "invalid_method";
const LABEL_INVALID_PARAMS: &str = "invalid_params";
const LABEL_MISSING_METHOD: &str = "method_not_found";
const LABEL_SUCCESS: &str = "success";

/// Creates HTTP server (warp-based) that serves JSON RPC requests
/// Returns handle to corresponding Tokio runtime
pub fn bootstrap(
    address: SocketAddr,
    libra_db: Arc<dyn DbReader>,
    mp_sender: MempoolClientSender,
    role: RoleType,
) -> Runtime {
    let runtime = Builder::new()
        .thread_name("rpc-")
        .threaded_scheduler()
        .enable_all()
        .build()
        .expect("[rpc] failed to create runtime");

    let registry = Arc::new(build_registry());
    let service = JsonRpcService::new(libra_db, mp_sender, role);

    let handler = warp::any()
        .and(warp::path::end())
        .and(warp::post())
        .and(warp::header::exact("content-type", "application/json"))
        .and(warp::body::json())
        .and(warp::any().map(move || service.clone()))
        .and(warp::any().map(move || Arc::clone(&registry)))
        .and_then(rpc_endpoint);

    // Ensure that we actually bind to the socket first before spawning the
    // server tasks. This helps in tests to prevent races where a client attempts
    // to make a request before the server task is actually listening on the
    // socket.
    //
    // Note: we need to enter the runtime context first to actually bind, since
    //       tokio TcpListener can only be bound inside a tokio context.
    let server = runtime.enter(move || warp::serve(handler).bind(address));
    runtime.handle().spawn(server);
    runtime
}

/// Creates JSON RPC endpoint by given node config
pub fn bootstrap_from_config(
    config: &NodeConfig,
    libra_db: Arc<dyn DbReader>,
    mp_sender: MempoolClientSender,
) -> Runtime {
    bootstrap(config.rpc.address, libra_db, mp_sender, config.base.role)
}

/// JSON RPC entry point
/// Handles all incoming rpc requests
/// Performs routing based on methods defined in `registry`
async fn rpc_endpoint(
    data: Value,
    service: JsonRpcService,
    registry: Arc<RpcRegistry>,
) -> Result<Box<dyn warp::Reply>, warp::Rejection> {
    // take snapshot of latest version of DB to be used across all requests, especially for batched requests
    let ledger_info = service
        .get_latest_ledger_info()
        .map_err(|_| reject::custom(DatabaseError))?;
    if let Value::Array(requests) = data {
        // batch API call
        let futures = requests.into_iter().map(|req| {
            rpc_request_handler(
                req,
                service.clone(),
                Arc::clone(&registry),
                ledger_info.clone(),
            )
        });
        let responses = join_all(futures).await;
        Ok(Box::new(warp::reply::json(&Value::Array(responses))))
    } else {
        // single API call
        let resp = rpc_request_handler(data, service, registry, ledger_info).await;
        Ok(Box::new(warp::reply::json(&resp)))
    }
}

/// Handler of single RPC request
/// Performs validation and executes corresponding rpc handler
async fn rpc_request_handler(
    req: Value,
    service: JsonRpcService,
    registry: Arc<RpcRegistry>,
    ledger_info: LedgerInfoWithSignatures,
) -> Value {
    let request: Map<String, Value>;
    let mut response = Map::new();

    // set defaults: protocol version to 2.0, request id to null
    response.insert("jsonrpc".to_string(), Value::String("2.0".to_string()));
    response.insert("id".to_string(), Value::Null);

    match req {
        Value::Object(data) => {
            request = data;
        }
        _ => {
            set_response_error(
                &mut response,
                JsonRpcError::invalid_request(),
                Some(LABEL_INVALID_FORMAT),
            );
            return Value::Object(response);
        }
    }

    // parse request id
    match parse_request_id(&request) {
        Ok(request_id) => {
            response.insert("id".to_string(), request_id);
        }
        Err(err) => {
            set_response_error(&mut response, err, Some(LABEL_INVALID_FORMAT));
            return Value::Object(response);
        }
    };

    // verify protocol version
    if let Err(err) = verify_protocol(&request) {
        set_response_error(&mut response, err, Some(LABEL_INVALID_FORMAT));
        return Value::Object(response);
    }

    // parse parameters
    let params;
    match request.get("params") {
        Some(Value::Array(parameters)) => {
            params = parameters.to_vec();
        }
        _ => {
            set_response_error(
                &mut response,
                JsonRpcError::invalid_params(),
                Some(LABEL_INVALID_PARAMS),
            );
            return Value::Object(response);
        }
    }

    let request_params = JsonRpcRequest {
        ledger_info,
        params,
    };
    // get rpc handler
    match request.get("method") {
        Some(Value::String(name)) => match registry.get(name) {
            Some(handler) => match handler(service, request_params).await {
                Ok(result) => {
                    response.insert("result".to_string(), result);
                    counters::REQUESTS
                        .with_label_values(&[name, LABEL_SUCCESS])
                        .inc();
                }
                Err(err) => {
                    // check for custom error
                    if let Some(custom_error) = err.downcast_ref::<JsonRpcError>() {
                        set_response_error(&mut response, custom_error.clone(), None);
                    } else {
                        set_response_error(
                            &mut response,
                            JsonRpcError::internal_error(err.to_string()),
                            None,
                        );
                    }
                    counters::REQUESTS
                        .with_label_values(&[name, LABEL_FAIL])
                        .inc();
                }
            },
            None => {
                set_response_error(
                    &mut response,
                    JsonRpcError::method_not_found(),
                    Some(LABEL_MISSING_METHOD),
                );
            }
        },
        _ => {
            set_response_error(
                &mut response,
                JsonRpcError::invalid_request(),
                Some(LABEL_INVALID_METHOD),
            );
        }
    }

    Value::Object(response)
}

// Sets the JSON RPC error value for a given response.
// If a counter label is supplied, also increments the invalid request counter using the label,
fn set_response_error(response: &mut Map<String, Value>, error: JsonRpcError, label: Option<&str>) {
    response.insert("error".to_string(), error.serialize());

    if let Some(label) = label {
        counters::INVALID_REQUESTS.with_label_values(&[label]).inc();
    }
}

fn parse_request_id(request: &Map<String, Value>) -> Result<Value, JsonRpcError> {
    match request.get("id") {
        Some(req_id) => {
            if req_id.is_string() || req_id.is_number() || req_id.is_null() {
                Ok(req_id.clone())
            } else {
                Err(JsonRpcError::invalid_request())
            }
        }
        None => Ok(Value::Null),
    }
}

fn verify_protocol(request: &Map<String, Value>) -> Result<(), JsonRpcError> {
    if let Some(Value::String(protocol)) = request.get("jsonrpc") {
        if protocol == "2.0" {
            return Ok(());
        }
    }
    Err(JsonRpcError::invalid_request())
}

/// Warp rejection types
#[derive(Debug)]
struct DatabaseError;

impl Reject for DatabaseError {}
<|endoftext|>


<commit_before>use llvm_sys::core::LLVMAddIncoming;
use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMValueRef};

use std::ffi::CStr;

use basic_block::BasicBlock;
use values::traits::AsValueRef;
use values::{BasicValue, InstructionValue, Value};

// REVIEW: Metadata for phi values?
#[derive(Debug, PartialEq, Eq)]
pub struct PhiValue {
    phi_value: Value
}

impl PhiValue {
    pub(crate) fn new(value: LLVMValueRef) -> Self {
        assert!(!value.is_null());

        PhiValue {
            phi_value: Value::new(value),
        }
    }

    fn add_incoming(&self, incoming: &[(&BasicValue, &BasicBlock)]) {
        let (mut values, mut basic_blocks): (Vec<LLVMValueRef>, Vec<LLVMBasicBlockRef>) = {
            incoming.iter()
                    .map(|&(v, bb)| (v.as_value_ref(), bb.basic_block))
                    .unzip()
        };

        unsafe {
            LLVMAddIncoming(self.as_value_ref(), values.as_mut_ptr(), basic_blocks.as_mut_ptr(), incoming.len() as u32);
        }
    }

    pub fn get_name(&self) -> &CStr {
        self.phi_value.get_name()
    }

    pub fn is_null(&self) -> bool {
        self.phi_value.is_null()
    }

    pub fn is_undef(&self) -> bool {
        self.phi_value.is_undef()
    }

    pub fn print_to_string(&self) -> &CStr {
        self.phi_value.print_to_string()
    }

    pub fn print_to_stderr(&self) {
        self.phi_value.print_to_stderr()
    }

    // REVIEW: Maybe this is should always return InstructionValue?
    pub fn as_instruction(&self) -> Option<InstructionValue> {
        self.phi_value.as_instruction()
    }
}

impl AsValueRef for PhiValue {
    fn as_value_ref(&self) -> LLVMValueRef {
        self.phi_value.value
    }
}
<commit_msg>Made PhiValue.add_incoming public, added count/get_incoming support<commit_after>use llvm_sys::core::{LLVMAddIncoming, LLVMCountIncoming, LLVMGetIncomingBlock, LLVMGetIncomingValue};
use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMValueRef};

use std::ffi::CStr;

use basic_block::BasicBlock;
use values::traits::AsValueRef;
use values::{BasicValue, BasicValueEnum, InstructionValue, Value};

// REVIEW: Metadata for phi values?
#[derive(Debug, PartialEq, Eq)]
pub struct PhiValue {
    phi_value: Value
}

impl PhiValue {
    pub(crate) fn new(value: LLVMValueRef) -> Self {
        assert!(!value.is_null());

        PhiValue {
            phi_value: Value::new(value),
        }
    }

    pub fn add_incoming(&self, incoming: &[(&BasicValue, &BasicBlock)]) {
        let (mut values, mut basic_blocks): (Vec<LLVMValueRef>, Vec<LLVMBasicBlockRef>) = {
            incoming.iter()
                    .map(|&(v, bb)| (v.as_value_ref(), bb.basic_block))
                    .unzip()
        };

        unsafe {
            LLVMAddIncoming(self.as_value_ref(), values.as_mut_ptr(), basic_blocks.as_mut_ptr(), incoming.len() as u32);
        }
    }

    pub fn count_incoming(&self) -> u32 {
        unsafe {
            LLVMCountIncoming(self.as_value_ref())
        }
    }

    pub fn get_incoming(&self, index: u32) -> Option<(BasicValueEnum, BasicBlock)> {
        if index >= self.count_incoming() {
            return None;
        }

        let basic_block = unsafe {
            LLVMGetIncomingBlock(self.as_value_ref(), index)
        };
        let value = unsafe {
            LLVMGetIncomingValue(self.as_value_ref(), index)
        };

        Some((BasicValueEnum::new(value), BasicBlock::new(basic_block).expect("Invalid BasicBlock")))
    }

    pub fn get_name(&self) -> &CStr {
        self.phi_value.get_name()
    }

    pub fn is_null(&self) -> bool {
        self.phi_value.is_null()
    }

    pub fn is_undef(&self) -> bool {
        self.phi_value.is_undef()
    }

    pub fn print_to_string(&self) -> &CStr {
        self.phi_value.print_to_string()
    }

    pub fn print_to_stderr(&self) {
        self.phi_value.print_to_stderr()
    }

    // REVIEW: Maybe this is should always return InstructionValue?
    pub fn as_instruction(&self) -> Option<InstructionValue> {
        self.phi_value.as_instruction()
    }
}

impl AsValueRef for PhiValue {
    fn as_value_ref(&self) -> LLVMValueRef {
        self.phi_value.value
    }
}
<|endoftext|>


<commit_before>use Printer;
use With;
use direction::Direction;
use event::{Event, EventResult};
use std::any::Any;
use std::ops::Deref;
use theme::ColorStyle;
use vec::Vec2;
use view::{Offset, Position, Selector, View};
use views::{Layer, ShadowView};

/// Simple stack of views.
/// Only the top-most view is active and can receive input.
pub struct StackView {
    layers: Vec<Child>,
    last_size: Vec2,
}

enum Placement {
    Floating(Position),
    Fullscreen,
}

impl Placement {
    pub fn compute_offset<S, A, P>(
        &self, size: S, available: A, parent: P
    ) -> Vec2
    where
        S: Into<Vec2>,
        A: Into<Vec2>,
        P: Into<Vec2>,
    {
        match *self {
            Placement::Floating(ref position) => {
                position.compute_offset(size, available, parent)
            }
            Placement::Fullscreen => Vec2::zero(),
        }
    }
}

struct Child {
    view: Box<View>,
    size: Vec2,
    placement: Placement,

    // We cannot call `take_focus` until we've called `layout()`
    // (for instance, a textView must know it will scroll to be focusable).
    // So we want to call `take_focus` right after the first call to `layout`.
    // This flag remembers when we've done that.
    virgin: bool,
}

new_default!(StackView);

impl StackView {
    /// Creates a new empty StackView
    pub fn new() -> Self {
        StackView {
            layers: Vec::new(),
            last_size: Vec2::zero(),
        }
    }

    /// Adds a new full-screen layer on top of the stack.
    ///
    /// Fullscreen layers have no shadow.
    pub fn add_fullscreen_layer<T>(&mut self, view: T)
    where
        T: 'static + View,
    {
        self.layers.push(Child {
            view: Box::new(Layer::new(view)),
            size: Vec2::zero(),
            placement: Placement::Fullscreen,
            virgin: true,
        });
    }

    /// Adds new view on top of the stack in the center of the screen.
    pub fn add_layer<T>(&mut self, view: T)
    where
        T: 'static + View,
    {
        self.add_layer_at(Position::center(), view);
    }

    /// Adds new view on top of the stack in the center of the screen.
    ///
    /// Chainable variant.
    pub fn layer<T>(self, view: T) -> Self
    where
        T: 'static + View,
    {
        self.with(|s| s.add_layer(view))
    }

    /// Adds a new full-screen layer on top of the stack.
    ///
    /// Chainable variant.
    pub fn fullscreen_layer<T>(self, view: T) -> Self
    where
        T: 'static + View,
    {
        self.with(|s| s.add_fullscreen_layer(view))
    }

    /// Adds a view on top of the stack.
    pub fn add_layer_at<T>(&mut self, position: Position, view: T)
    where
        T: 'static + View,
    {
        self.layers.push(Child {
            // Skip padding for absolute/parent-placed views
            view: Box::new(
                ShadowView::new(Layer::new(view))
                    .top_padding(position.y == Offset::Center)
                    .left_padding(position.x == Offset::Center),
            ),
            size: Vec2::new(0, 0),
            placement: Placement::Floating(position),
            virgin: true,
        });
    }

    /// Adds a view on top of the stack.
    ///
    /// Chainable variant.
    pub fn layer_at<T>(self, position: Position, view: T) -> Self
    where
        T: 'static + View,
    {
        self.with(|s| s.add_layer_at(position, view))
    }

    /// Remove the top-most layer.
    pub fn pop_layer(&mut self) {
        self.layers.pop();
    }

    /// Computes the offset of the current top view.
    pub fn offset(&self) -> Vec2 {
        let mut previous = Vec2::zero();
        for layer in &self.layers {
            let offset = layer.placement.compute_offset(
                layer.size,
                self.last_size,
                previous,
            );
            previous = offset;
        }
        previous
    }

    /// Returns the size for each layer in this view.
    pub fn layer_sizes(&self) -> Vec<Vec2> {
        self.layers.iter().map(|layer| layer.size).collect()
    }
}

struct StackPositionIterator<R: Deref<Target = Child>, I: Iterator<Item = R>> {
    inner: I,
    previous: Vec2,
    total_size: Vec2,
}

impl<R: Deref<Target = Child>, I: Iterator<Item = R>>
    StackPositionIterator<R, I> {
    /// Returns a new StackPositionIterator
    pub fn new(inner: I, total_size: Vec2) -> Self {
        let previous = Vec2::zero();
        StackPositionIterator {
            inner,
            previous,
            total_size,
        }
    }
}

impl<R: Deref<Target = Child>, I: Iterator<Item = R>> Iterator
    for StackPositionIterator<R, I> {
    type Item = (R, Vec2);

    fn next(&mut self) -> Option<(R, Vec2)> {
        self.inner.next().map(|v| {
            let offset = v.placement.compute_offset(
                v.size,
                self.total_size,
                self.previous,
            );

            self.previous = offset;

            // eprintln!("{:?}", offset);
            (v, offset)
        })
    }
}

impl View for StackView {
    fn draw(&self, printer: &Printer) {
        let last = self.layers.len();
        printer.with_color(ColorStyle::Primary, |printer| {
            for (i, (v, offset)) in
                StackPositionIterator::new(self.layers.iter(), printer.size)
                    .enumerate()
            {
                v.view
                    .draw(&printer.sub_printer(offset, v.size, i + 1 == last));
            }
        });
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        // Use the stack position iterator to get the offset of the top layer.
        // TODO: save it instead when drawing?
        match StackPositionIterator::new(
            self.layers.iter_mut(),
            self.last_size,
        ).last()
        {
            None => EventResult::Ignored,
            Some((v, offset)) => v.view.on_event(event.relativized(offset)),
        }
    }

    fn layout(&mut self, size: Vec2) {
        self.last_size = size;

        // The call has been made, we can't ask for more space anymore.
        // Let's make do with what we have.

        for layer in &mut self.layers {
            // Give each guy what he asks for, within the budget constraints.
            let size = Vec2::min(size, layer.view.required_size(size));
            layer.size = size;
            layer.view.layout(layer.size);

            // We need to call `layout()` on the view before giving it focus
            // for the first time. Otherwise it will not be properly set up.
            // Ex: examples/lorem.rs: the text view takes focus because it's
            // scrolling, but it only knows that after a call to `layout()`.
            if layer.virgin {
                layer.view.take_focus(Direction::none());
                layer.virgin = false;
            }
        }
    }

    fn required_size(&mut self, size: Vec2) -> Vec2 {
        // The min size is the max of all children's

        self.layers
            .iter_mut()
            .map(|layer| layer.view.required_size(size))
            .fold(Vec2::new(1, 1), Vec2::max)
    }

    fn take_focus(&mut self, source: Direction) -> bool {
        match self.layers.last_mut() {
            None => false,
            Some(v) => v.view.take_focus(source),
        }
    }

    fn call_on_any<'a>(
        &mut self, selector: &Selector,
        mut callback: Box<FnMut(&mut Any) + 'a>,
    ) {
        for layer in &mut self.layers {
            layer
                .view
                .call_on_any(selector, Box::new(|any| callback(any)));
        }
    }

    fn focus_view(&mut self, selector: &Selector) -> Result<(), ()> {
        for layer in &mut self.layers {
            if layer.view.focus_view(selector).is_ok() {
                return Ok(());
            }
        }

        Err(())
    }
}
<commit_msg>StackView: store Layer<Box<V>> rather than Box<Layer<V>><commit_after>use Printer;
use With;
use direction::Direction;
use event::{Event, EventResult};
use std::any::Any;
use std::ops::Deref;
use theme::ColorStyle;
use vec::Vec2;
use view::{Offset, Position, Selector, View};
use views::{Layer, ShadowView};

/// Simple stack of views.
/// Only the top-most view is active and can receive input.
pub struct StackView {
    layers: Vec<Child>,
    last_size: Vec2,
}

enum Placement {
    Floating(Position),
    Fullscreen,
}

impl Placement {
    pub fn compute_offset<S, A, P>(
        &self, size: S, available: A, parent: P
    ) -> Vec2
    where
        S: Into<Vec2>,
        A: Into<Vec2>,
        P: Into<Vec2>,
    {
        match *self {
            Placement::Floating(ref position) => {
                position.compute_offset(size, available, parent)
            }
            Placement::Fullscreen => Vec2::zero(),
        }
    }
}

// A child view can be wrapped in multiple ways.
enum ChildWrapper<T: View> {
    // Some views include a shadow around.
    Shadow(ShadowView<Layer<T>>),
    // Some views don't (fullscreen views mostly)
    Plain(Layer<T>),
}

// TODO: use macros to make this less ugly?
impl <T: View> View for ChildWrapper<T> {

    fn draw(&self, printer: &Printer) {
        match *self {
            ChildWrapper::Shadow(ref v) => v.draw(printer),
            ChildWrapper::Plain(ref v) => v.draw(printer),
        }
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        match *self {
            ChildWrapper::Shadow(ref mut v) => v.on_event(event),
            ChildWrapper::Plain(ref mut v) => v.on_event(event),
        }
    }

    fn layout(&mut self, size: Vec2) {
        match *self {
            ChildWrapper::Shadow(ref mut v) => v.layout(size),
            ChildWrapper::Plain(ref mut v) => v.layout(size),
        }
    }

    fn required_size(&mut self, size: Vec2) -> Vec2 {
        match *self {
            ChildWrapper::Shadow(ref mut v) => v.required_size(size),
            ChildWrapper::Plain(ref mut v) => v.required_size(size),
        }
    }

    fn take_focus(&mut self, source: Direction) -> bool {
        match *self {
            ChildWrapper::Shadow(ref mut v) => v.take_focus(source),
            ChildWrapper::Plain(ref mut v) => v.take_focus(source),
        }
    }

    fn call_on_any<'a>(
        &mut self, selector: &Selector,
        callback: Box<FnMut(&mut Any) + 'a>,
    ) {
        match *self {
            ChildWrapper::Shadow(ref mut v) => v.call_on_any(selector, callback),
            ChildWrapper::Plain(ref mut v) => v.call_on_any(selector, callback),
        }
    }

    fn focus_view(&mut self, selector: &Selector) -> Result<(), ()> {
        match *self {
            ChildWrapper::Shadow(ref mut v) => v.focus_view(selector),
            ChildWrapper::Plain(ref mut v) => v.focus_view(selector),
        }
    }

}

struct Child {
    view: ChildWrapper<Box<View>>,
    size: Vec2,
    placement: Placement,

    // We cannot call `take_focus` until we've called `layout()`
    // (for instance, a textView must know it will scroll to be focusable).
    // So we want to call `take_focus` right after the first call to `layout`.
    // This flag remembers when we've done that.
    virgin: bool,
}

new_default!(StackView);

impl StackView {
    /// Creates a new empty StackView
    pub fn new() -> Self {
        StackView {
            layers: Vec::new(),
            last_size: Vec2::zero(),
        }
    }

    /// Adds a new full-screen layer on top of the stack.
    ///
    /// Fullscreen layers have no shadow.
    pub fn add_fullscreen_layer<T>(&mut self, view: T)
    where
        T: 'static + View,
    {
        let boxed: Box<View> = Box::new(view);
        self.layers.push(Child {
            view: ChildWrapper::Plain(Layer::new(boxed)),
            size: Vec2::zero(),
            placement: Placement::Fullscreen,
            virgin: true,
        });
    }

    /// Adds new view on top of the stack in the center of the screen.
    pub fn add_layer<T>(&mut self, view: T)
    where
        T: 'static + View,
    {
        self.add_layer_at(Position::center(), view);
    }

    /// Adds new view on top of the stack in the center of the screen.
    ///
    /// Chainable variant.
    pub fn layer<T>(self, view: T) -> Self
    where
        T: 'static + View,
    {
        self.with(|s| s.add_layer(view))
    }

    /// Adds a new full-screen layer on top of the stack.
    ///
    /// Chainable variant.
    pub fn fullscreen_layer<T>(self, view: T) -> Self
    where
        T: 'static + View,
    {
        self.with(|s| s.add_fullscreen_layer(view))
    }

    /// Adds a view on top of the stack.
    pub fn add_layer_at<T>(&mut self, position: Position, view: T)
    where
        T: 'static + View,
    {
        let boxed: Box<View> = Box::new(view);
        self.layers.push(Child {
            // Skip padding for absolute/parent-placed views
            view: ChildWrapper::Shadow(
                ShadowView::new(Layer::new(boxed))
                    .top_padding(position.y == Offset::Center)
                    .left_padding(position.x == Offset::Center),
            ),
            size: Vec2::new(0, 0),
            placement: Placement::Floating(position),
            virgin: true,
        });
    }

    /// Adds a view on top of the stack.
    ///
    /// Chainable variant.
    pub fn layer_at<T>(self, position: Position, view: T) -> Self
    where
        T: 'static + View,
    {
        self.with(|s| s.add_layer_at(position, view))
    }

    /// Remove the top-most layer.
    pub fn pop_layer(&mut self) {
        self.layers.pop();
    }

    /// Computes the offset of the current top view.
    pub fn offset(&self) -> Vec2 {
        let mut previous = Vec2::zero();
        for layer in &self.layers {
            let offset = layer.placement.compute_offset(
                layer.size,
                self.last_size,
                previous,
            );
            previous = offset;
        }
        previous
    }

    /// Returns the size for each layer in this view.
    pub fn layer_sizes(&self) -> Vec<Vec2> {
        self.layers.iter().map(|layer| layer.size).collect()
    }
}

struct StackPositionIterator<R: Deref<Target = Child>, I: Iterator<Item = R>> {
    inner: I,
    previous: Vec2,
    total_size: Vec2,
}

impl<R: Deref<Target = Child>, I: Iterator<Item = R>>
    StackPositionIterator<R, I> {
    /// Returns a new StackPositionIterator
    pub fn new(inner: I, total_size: Vec2) -> Self {
        let previous = Vec2::zero();
        StackPositionIterator {
            inner,
            previous,
            total_size,
        }
    }
}

impl<R: Deref<Target = Child>, I: Iterator<Item = R>> Iterator
    for StackPositionIterator<R, I> {
    type Item = (R, Vec2);

    fn next(&mut self) -> Option<(R, Vec2)> {
        self.inner.next().map(|v| {
            let offset = v.placement.compute_offset(
                v.size,
                self.total_size,
                self.previous,
            );

            self.previous = offset;

            // eprintln!("{:?}", offset);
            (v, offset)
        })
    }
}

impl View for StackView {
    fn draw(&self, printer: &Printer) {
        let last = self.layers.len();
        printer.with_color(ColorStyle::Primary, |printer| {
            for (i, (v, offset)) in
                StackPositionIterator::new(self.layers.iter(), printer.size)
                    .enumerate()
            {
                v.view
                    .draw(&printer.sub_printer(offset, v.size, i + 1 == last));
            }
        });
    }

    fn on_event(&mut self, event: Event) -> EventResult {
        // Use the stack position iterator to get the offset of the top layer.
        // TODO: save it instead when drawing?
        match StackPositionIterator::new(
            self.layers.iter_mut(),
            self.last_size,
        ).last()
        {
            None => EventResult::Ignored,
            Some((v, offset)) => v.view.on_event(event.relativized(offset)),
        }
    }

    fn layout(&mut self, size: Vec2) {
        self.last_size = size;

        // The call has been made, we can't ask for more space anymore.
        // Let's make do with what we have.

        for layer in &mut self.layers {
            // Give each guy what he asks for, within the budget constraints.
            let size = Vec2::min(size, layer.view.required_size(size));
            layer.size = size;
            layer.view.layout(layer.size);

            // We need to call `layout()` on the view before giving it focus
            // for the first time. Otherwise it will not be properly set up.
            // Ex: examples/lorem.rs: the text view takes focus because it's
            // scrolling, but it only knows that after a call to `layout()`.
            if layer.virgin {
                layer.view.take_focus(Direction::none());
                layer.virgin = false;
            }
        }
    }

    fn required_size(&mut self, size: Vec2) -> Vec2 {
        // The min size is the max of all children's

        self.layers
            .iter_mut()
            .map(|layer| layer.view.required_size(size))
            .fold(Vec2::new(1, 1), Vec2::max)
    }

    fn take_focus(&mut self, source: Direction) -> bool {
        match self.layers.last_mut() {
            None => false,
            Some(v) => v.view.take_focus(source),
        }
    }

    fn call_on_any<'a>(
        &mut self, selector: &Selector,
        mut callback: Box<FnMut(&mut Any) + 'a>,
    ) {
        for layer in &mut self.layers {
            layer
                .view
                .call_on_any(selector, Box::new(|any| callback(any)));
        }
    }

    fn focus_view(&mut self, selector: &Selector) -> Result<(), ()> {
        for layer in &mut self.layers {
            if layer.view.focus_view(selector).is_ok() {
                return Ok(());
            }
        }

        Err(())
    }
}
<|endoftext|>


<commit_before>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use datasource::postgis::PostgisInput;
use core::grid::Grid;
use mvt::tile::Tile;
use mvt::vector_tile;
use service::mvt::MvtService;

use nickel::{Nickel, Options, HttpRouter, MediaType, Request, Responder, Response, MiddlewareResult };
use nickel_mustache::Render;
use hyper::header;
use std::collections::HashMap;
use clap::ArgMatches;

fn log_request<'mw>(req: &mut Request, res: Response<'mw>) -> MiddlewareResult<'mw> {
    info!("{} {}", req.origin.method, req.origin.uri);
    res.next_middleware()
}

fn maybe_set_type<D>(res: &mut Response<D>, mime: MediaType) {
    res.set_header_fallback(|| header::ContentType(mime.into()));
}

impl<D> Responder<D> for vector_tile::Tile {
    fn respond<'a>(self, mut res: Response<'a, D>) -> MiddlewareResult<'a, D> {
        maybe_set_type(&mut res, MediaType::Bin);
        let vec = Tile::binary_tile(&self);
        res.send(vec)
    }
}

pub fn webserver(args: &ArgMatches) {
    let mut server = Nickel::new();
    server.options = Options::default()
                     .thread_count(Some(1));
    server.utilize(log_request);

    let dbconn = args.value_of("dbconn").unwrap();
    let pg = PostgisInput { connection_url: dbconn.to_string() };
    let grid = Grid::web_mercator();
    let layers = pg.detect_layers();
    let layers_display: Vec<HashMap<&str,String>> = layers.iter().map(|l| {
        let mut h = HashMap::new();
        h.insert("name", l.name.clone());
        h.insert("geomtype", l.geometry_type.as_ref().unwrap().clone());
        h
    }).collect();
    let service = MvtService {input: pg, grid: grid, layers: layers, topics: Vec::new()};

    server.get("/:topic/:z/:x/:y.pbf", middleware! { |req|
        let topic = req.param("topic").unwrap();
        let z = req.param("z").unwrap().parse::<u16>().unwrap();
        let x = req.param("x").unwrap().parse::<u16>().unwrap();
        let y = req.param("y").unwrap().parse::<u16>().unwrap();

        let mvt_tile = service.tile(topic, x, y, z);

        mvt_tile
    });
    server.get("/", middleware! { |req, res|
        let mut data = HashMap::new();
        data.insert("layer", &layers_display);
        return res.render("src/webserver/templates/index.tpl", &data)
    });
    server.get("/:topic/", middleware! { |req, res|
        let topic = req.param("topic").unwrap();
        let mut data = HashMap::new();
        data.insert("baseurl", "http://127.0.0.1:6767");
        data.insert("topic", topic);
        return res.render("src/webserver/templates/olviewer.tpl", &data)
    });
    server.listen("127.0.0.1:6767");
}
<commit_msg>Use hostname from HTTP headers in map viewer<commit_after>//
// Copyright (c) Pirmin Kalberer. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

use datasource::postgis::PostgisInput;
use core::grid::Grid;
use mvt::tile::Tile;
use mvt::vector_tile;
use service::mvt::MvtService;

use nickel::{Nickel, Options, HttpRouter, MediaType, Request, Responder, Response, MiddlewareResult };
use nickel_mustache::Render;
use hyper::header;
use std::collections::HashMap;
use clap::ArgMatches;

fn log_request<'mw>(req: &mut Request, res: Response<'mw>) -> MiddlewareResult<'mw> {
    info!("{} {}", req.origin.method, req.origin.uri);
    res.next_middleware()
}

fn maybe_set_type<D>(res: &mut Response<D>, mime: MediaType) {
    res.set_header_fallback(|| header::ContentType(mime.into()));
}

impl<D> Responder<D> for vector_tile::Tile {
    fn respond<'a>(self, mut res: Response<'a, D>) -> MiddlewareResult<'a, D> {
        maybe_set_type(&mut res, MediaType::Bin);
        let vec = Tile::binary_tile(&self);
        res.send(vec)
    }
}

pub fn webserver(args: &ArgMatches) {
    let mut server = Nickel::new();
    server.options = Options::default()
                     .thread_count(Some(1));
    server.utilize(log_request);

    let dbconn = args.value_of("dbconn").unwrap();
    let pg = PostgisInput { connection_url: dbconn.to_string() };
    let grid = Grid::web_mercator();
    let layers = pg.detect_layers();
    let layers_display: Vec<HashMap<&str,String>> = layers.iter().map(|l| {
        let mut h = HashMap::new();
        h.insert("name", l.name.clone());
        h.insert("geomtype", l.geometry_type.as_ref().unwrap().clone());
        h
    }).collect();
    let service = MvtService {input: pg, grid: grid, layers: layers, topics: Vec::new()};

    server.get("/:topic/:z/:x/:y.pbf", middleware! { |req|
        let topic = req.param("topic").unwrap();
        let z = req.param("z").unwrap().parse::<u16>().unwrap();
        let x = req.param("x").unwrap().parse::<u16>().unwrap();
        let y = req.param("y").unwrap().parse::<u16>().unwrap();

        let mvt_tile = service.tile(topic, x, y, z);

        mvt_tile
    });
    server.get("/", middleware! { |req, res|
        let mut data = HashMap::new();
        data.insert("layer", &layers_display);
        return res.render("src/webserver/templates/index.tpl", &data)
    });
    server.get("/:topic/", middleware! { |req, res|
        let topic = req.param("topic").unwrap();
        let host = req.origin.headers.get::<header::Host>().unwrap();
        let baseurl = format!("http://{}:{}", host.hostname, host.port.unwrap_or(80));
        let mut data = HashMap::new();
        data.insert("baseurl", baseurl);
        data.insert("topic", topic.to_string());
        return res.render("src/webserver/templates/olviewer.tpl", &data)
    });
    server.listen("127.0.0.1:6767");
}
<|endoftext|>


<commit_before>const NEXT: *mut u64 = 0x200010 as *mut u64;

/// Generate pseudo random number
pub fn rand() -> usize {
    unsafe {
        (*NEXT) = (*NEXT) * 1103515245 + 12345;
        ((*NEXT) / 65536) as usize
    }
}

/// Generate pseudo random number via seed
pub fn srand(seed: usize) {
    unsafe {
        (*NEXT) = seed as u64;
    }
}
<commit_msg>Make PRNG in the kernel more random<commit_after>static mut seed: u64 = 19940046431; //259261034506304368955239; //1706322144714608529217229883707268827757977089;

/// Generate pseudo random number
pub fn rand() -> usize {
    seed ^= seed << 12;
    seed ^= seed << 25;
    seed ^= seed << 27;
    seed = seed * 82724793451 + 12345;
    seed as usize % ::core::usize::MAX
}

/// Generate pseudo random number via seed
pub fn srand(s: usize) {
    seed = s as u64;
}
<|endoftext|>


<commit_before>use super::{Tok, Tokenizer};
use super::Tok::*;

fn test(input: &str,
        expected: Vec<(&str, Tok)>)
{
    // use $ to signal EOL because it can be replaced with a single space
    // for spans, and because it applies also to r#XXX# style strings:
    let input = input.replace("$", "\n");

    let tokenizer = Tokenizer::new(&input, 0);
    let len = expected.len();
    for (token, (expected_span, expected_tok)) in tokenizer.zip(expected.into_iter()) {
        println!("token: {:?}", token);
        let expected_start = expected_span.find("~").unwrap();
        let expected_end = expected_span.rfind("~").unwrap() + 1;
        assert_eq!(Ok((expected_start, expected_tok, expected_end)), token);
    }

    let tokenizer = Tokenizer::new(&input, 0);
    assert_eq!(None, tokenizer.skip(len).next());
}

#[test]
fn basic() {
    test("extern foo", vec![
        ("~~~~~~    ", Extern),
        ("       ~~~", Id("foo")),
    ]);
}

#[test]
fn eol_comment() {
    test("extern // This is a comment$ foo", vec![
        ("~~~~~~                          ", Extern),
        ("                             ~~~", Id("foo")),
    ]);
}

#[test]
fn code1() {
    test("=> a(b, c),", vec![
        ("~~~~~~~~~~ ", EqualsGreaterThanCode(" a(b, c)")),
        ("          ~", Comma),
    ]);
}

#[test]
fn rule_id_then_equalsgreaterthancode_functioncall() {
    test("id => a(b, c),", vec![
        ("~~            ", Id("id")),
        ("   ~~~~~~~~~~ ", EqualsGreaterThanCode(" a(b, c)")),
        ("             ~", Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_dot_then_equalsgreaterthancode_functioncall() {
    test(r#" "\." => a(b, c),"#, vec![
        (r#" ~~~~            "#, StringLiteral(r#"\."#)),
        (r#"      ~~~~~~~~~~ "#, EqualsGreaterThanCode(" a(b, c)")),
        (r#"                ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_dot_then_equalsgreaterthancode_many_characters_in_stringliteral() {
    test(r#" "\." => "Planet Earth" ,"#, vec![
        (r#" ~~~~                    "#, StringLiteral(r#"\."#)),
        (r#"      ~~~~~~~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" "Planet Earth" "#)),
        (r#"                        ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_dot_then_equalsgreaterthancode_one_character_dot_in_stringliteral() {
    test(r#" "\." => "." ,"#, vec![
        (r#" ~~~~         "#, StringLiteral(r#"\."#)),
        (r#"      ~~~~~~~ "#, EqualsGreaterThanCode(r#" "." "#)),
        (r#"             ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_openningbracket_then_equalsgreaterthancode_one_character_openningbracket_in_stringliteral() {
    test(r#" "\(" => "(" ,"#, vec![
        (r#" ~~~~         "#, StringLiteral(r#"\("#)),
        (r#"      ~~~~~~~ "#, EqualsGreaterThanCode(r#" "(" "#)),
        (r#"             ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_openningbracket_then_equalsgreaterthancode_empty_stringliteral() {
    test(r#" "\(" => "" ,"#, vec![
        (r#" ~~~~        "#, StringLiteral(r#"\("#)),
        (r#"      ~~~~~~ "#, EqualsGreaterThanCode(r#" "" "#)),
        (r#"            ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_dot_then_equalsgreaterthancode_one_character_dot() {
    test(r#" "\." => '.' ,"#, vec![
        (r#" ~~~~         "#, StringLiteral(r#"\."#)),
        (r#"      ~~~~~~~ "#, EqualsGreaterThanCode(r#" '.' "#)),
        (r#"             ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_openningbracket_then_equalsgreaterthancode_one_character_openningbracket() {
    test(r#" "\(" => '(' ,"#, vec![
        (r#" ~~~~         "#, StringLiteral(r#"\("#)),
        (r#"      ~~~~~~~ "#, EqualsGreaterThanCode(r#" '(' "#)),
        (r#"             ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_openningbracket() {
    test(r#"=> '(' ,"#, vec![
        (r#"~~~~~~~ "#, EqualsGreaterThanCode(r#" '(' "#)),
        (r#"       ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_escaped_n() {
    test(r#"=> '\n' ,"#, vec![
        (r#"~~~~~~~~ "#, EqualsGreaterThanCode(r#" '\n' "#)),
        (r#"        ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_escaped_w() {
    test(r#"=> '\w' ,"#, vec![
        (r#"~~~~~~~~ "#, EqualsGreaterThanCode(r#" '\w' "#)),
        (r#"        ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_escaped_planet123() {
    test(r#"=> '\planet123' ,"#, vec![
        (r#"~~~~~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" '\planet123' "#)),
        (r#"                ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_openningcurlybracket() {
    test(r#"=> '{' ,"#, vec![
        (r#"~~~~~~~ "#, EqualsGreaterThanCode(r#" '{' "#)),
        (r#"       ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_openningsquarebracket() {
    test(r#"=> '[' ,"#, vec![
        (r#"~~~~~~~ "#, EqualsGreaterThanCode(r#" '[' "#)),
        (r#"       ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_openningbracket_wrapped_by_brackets() {
    test(r#"=> ('(') ,"#, vec![
        (r#"~~~~~~~~~ "#, EqualsGreaterThanCode(r#" ('(') "#)),
        (r#"         ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_closingbracket_wrapped_by_brackets() {
    test(r#"=> (')') ,"#, vec![
        (r#"~~~~~~~~~ "#, EqualsGreaterThanCode(r#" (')') "#)),
        (r#"         ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_tuple() {
    test(r#"=> (1,2,3) ,"#, vec![
        (r#"~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" (1,2,3) "#)),
        (r#"           ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_statement_with_lifetime() {
    test(r#"=> HuffmanTable::<Code<'a>>::new() ,"#, vec![
        (r#"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" HuffmanTable::<Code<'a>>::new() "#)),
        (r#"                                   ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_statement_with_many_lifetimes() {
    test(r#"=> (HuffmanTable::<Code<'a, 'b>>::new()),"#, vec![
        (r#"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" (HuffmanTable::<Code<'a, 'b>>::new())"#)),
        (r#"                                        ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_nested_function_with_lifetimes() {
    test(r#"=> fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {} ,"#, vec![
        (r#"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {} "#)),
        (r#"                                                    ~"#, Comma),
    ]);
}

#[test]
fn where_with_lifetimes() {
    test(r#"where <'a,bar<'b,'c>>,baz;"#, vec![
        (r#"~~~~~~~~~~~~~~~~~~~~~~~~~ "#, Where(vec![" <'a,bar<'b,'c>>", "baz"])),
        (r#"                         ~"#, Semi),
    ]);
}

#[test]
fn code_paren() { // Issue #25
    test(r#"=> a("(", c),"#, vec![
        (r#"~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" a("(", c)"#)),
        (r#"            ~"#, Comma),
    ]);
}

#[test]
fn code_regex_paren() { // Issue #25
    test(r###"=> a(r##"("#""##, c),"###, vec![
        (r###"~~~~~~~~~~~~~~~~~~~~ "###, EqualsGreaterThanCode(r###" a(r##"("#""##, c)"###)),
        (r###"                    ~"###, Comma),
    ]);
}

#[test]
fn code_comment_eol() {
    test("=> a(// (
),", vec![
        ("~~~~~~~~~
~,", EqualsGreaterThanCode(" a(// (\n)")),
        ("=> a(// (
)~", Comma)]);
}

#[test]
fn code2() {
    test("=>? a(b, c),", vec![
        ("~~~~~~~~~~~ ", EqualsGreaterThanQuestionCode(" a(b, c)")),
        ("           ~", Comma),
    ]);
}

#[test]
#[should_panic]
fn code_forgot_comma() {
    test("=> a(b, c),", vec![
        ("~~~~~~~~~~ ", EqualsGreaterThanCode(" a(b, c)")),
        // intentionally forget the comma token; this is more of a test of `test`
    ]);
}

#[test]
fn various_kinds_of_ids() {
    test("foo<T<'a,U,`Z*{}`>>", vec![
        ("~~~                ", MacroId("foo")),
        ("   ~               ", LessThan),
        ("    ~              ", MacroId("T")),
        ("     ~             ", LessThan),
        ("      ~~           ", Lifetime("'a")),
        ("        ~          ", Comma),
        ("         ~         ", Id("U")),
        ("          ~        ", Comma),
        ("           ~~~~~~  ", Escape("Z*{}")),
        ("                 ~ ", GreaterThan),
        ("                  ~", GreaterThan),
    ]);
}

#[test]
fn string_literals() {
    test(r#"foo "bar\"\n" baz"#, vec![
        (r#"~~~              "#, Id("foo")),
        (r#"    ~~~~~~~~~    "#, StringLiteral(r#"bar\"\n"#)),
        (r#"              ~~~"#, Id("baz")),
    ]);
}

#[test]
fn use1() {
    test(r#"use foo::bar; baz"#, vec![
        (r#"~~~~~~~~~~~~     "#, Use(" foo::bar")),
        (r#"            ~    "#, Semi),
        (r#"              ~~~"#, Id("baz")),
    ]);
}

#[test]
fn use2() {
    test(r#"use {foo,bar}; baz"#, vec![
        (r#"~~~~~~~~~~~~~     "#, Use(" {foo,bar}")),
        (r#"             ~    "#, Semi),
        (r#"               ~~~"#, Id("baz")),
    ]);
}

#[test]
fn where1() {
    test(r#"where <foo,bar>,baz;"#, vec![
        (r#"~~~~~~~~~~~~~~~~~~~ "#, Where(vec![" <foo,bar>", "baz"])),
        (r#"                   ~"#, Semi),
    ]);
}

#[test]
fn regex1() {
    test(r#####"raa r##" #"#"" "#"##rrr"#####, vec![
        (r#####"~~~                    "#####, Id("raa")),
        (r#####"    ~~~~~~~~~~~~~~~~   "#####, RegexLiteral(r##" #"#"" "#"##)),
        (r#####"                    ~~~"#####, Id("rrr")),
    ]);
}

#[test]
fn regex2() {
    test(r#"r"(123""#, vec![
        (r#"~~~~~~~"#, RegexLiteral(r"(123")),
    ]);
}

<commit_msg>Added tests for error-cases for tokenizer<commit_after>use super::{Tok, ErrorCode, Error, Tokenizer};
use super::Tok::*;

enum Expectation<'a> {
    ExpectTok(Tok<'a>),
    ExpectErr(ErrorCode)
}

use self::Expectation::*;

fn gen_test(input: &str, expected: Vec<(&str, Expectation)>)
{
    // use $ to signal EOL because it can be replaced with a single space
    // for spans, and because it applies also to r#XXX# style strings:
    let input = input.replace("$", "\n");

    let tokenizer = Tokenizer::new(&input, 0);
    let len = expected.len();
    for (token, (expected_span, expectation)) in tokenizer.zip(expected.into_iter()) {
        let expected_start = expected_span.find("~").unwrap();
        let expected_end = expected_span.rfind("~").unwrap() + 1;
        println!("token: {:?}", token);
        match expectation {
            ExpectTok(expected_tok) => {
                assert_eq!(Ok((expected_start, expected_tok, expected_end)), token);
            }
            ExpectErr(expected_ec) => {
                assert_eq!(Err(Error{ location: expected_start, code: expected_ec }), token)
            }
        }
    }

    let tokenizer = Tokenizer::new(&input, 0);
    assert_eq!(None, tokenizer.skip(len).next());
}

fn test(input: &str, expected: Vec<(&str, Tok)>)
{
    let generic_expected = expected.into_iter().map( | (span, tok) | (span, ExpectTok(tok)) ).collect();
    gen_test(input, generic_expected);
}

fn test_err(input: &str, expected: (&str, ErrorCode))
{
    let (span, ec) = expected;
    gen_test(input, vec![(span, ExpectErr(ec))])
}

#[test]
fn basic() {
    test("extern foo", vec![
        ("~~~~~~    ", Extern),
        ("       ~~~", Id("foo")),
    ]);
}

#[test]
fn eol_comment() {
    test("extern // This is a comment$ foo", vec![
        ("~~~~~~                          ", Extern),
        ("                             ~~~", Id("foo")),
    ]);
}

#[test]
fn code1() {
    test("=> a(b, c),", vec![
        ("~~~~~~~~~~ ", EqualsGreaterThanCode(" a(b, c)")),
        ("          ~", Comma),
    ]);
}

#[test]
fn rule_id_then_equalsgreaterthancode_functioncall() {
    test("id => a(b, c),", vec![
        ("~~            ", Id("id")),
        ("   ~~~~~~~~~~ ", EqualsGreaterThanCode(" a(b, c)")),
        ("             ~", Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_dot_then_equalsgreaterthancode_functioncall() {
    test(r#" "\." => a(b, c),"#, vec![
        (r#" ~~~~            "#, StringLiteral(r#"\."#)),
        (r#"      ~~~~~~~~~~ "#, EqualsGreaterThanCode(" a(b, c)")),
        (r#"                ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_dot_then_equalsgreaterthancode_many_characters_in_stringliteral() {
    test(r#" "\." => "Planet Earth" ,"#, vec![
        (r#" ~~~~                    "#, StringLiteral(r#"\."#)),
        (r#"      ~~~~~~~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" "Planet Earth" "#)),
        (r#"                        ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_dot_then_equalsgreaterthancode_one_character_dot_in_stringliteral() {
    test(r#" "\." => "." ,"#, vec![
        (r#" ~~~~         "#, StringLiteral(r#"\."#)),
        (r#"      ~~~~~~~ "#, EqualsGreaterThanCode(r#" "." "#)),
        (r#"             ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_openningbracket_then_equalsgreaterthancode_one_character_openningbracket_in_stringliteral() {
    test(r#" "\(" => "(" ,"#, vec![
        (r#" ~~~~         "#, StringLiteral(r#"\("#)),
        (r#"      ~~~~~~~ "#, EqualsGreaterThanCode(r#" "(" "#)),
        (r#"             ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_openningbracket_then_equalsgreaterthancode_empty_stringliteral() {
    test(r#" "\(" => "" ,"#, vec![
        (r#" ~~~~        "#, StringLiteral(r#"\("#)),
        (r#"      ~~~~~~ "#, EqualsGreaterThanCode(r#" "" "#)),
        (r#"            ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_dot_then_equalsgreaterthancode_one_character_dot() {
    test(r#" "\." => '.' ,"#, vec![
        (r#" ~~~~         "#, StringLiteral(r#"\."#)),
        (r#"      ~~~~~~~ "#, EqualsGreaterThanCode(r#" '.' "#)),
        (r#"             ~"#, Comma),
    ]);
}

#[test]
fn rule_stringliteral_slash_openningbracket_then_equalsgreaterthancode_one_character_openningbracket() {
    test(r#" "\(" => '(' ,"#, vec![
        (r#" ~~~~         "#, StringLiteral(r#"\("#)),
        (r#"      ~~~~~~~ "#, EqualsGreaterThanCode(r#" '(' "#)),
        (r#"             ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_openningbracket() {
    test(r#"=> '(' ,"#, vec![
        (r#"~~~~~~~ "#, EqualsGreaterThanCode(r#" '(' "#)),
        (r#"       ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_escaped_n() {
    test(r#"=> '\n' ,"#, vec![
        (r#"~~~~~~~~ "#, EqualsGreaterThanCode(r#" '\n' "#)),
        (r#"        ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_escaped_w() {
    test(r#"=> '\w' ,"#, vec![
        (r#"~~~~~~~~ "#, EqualsGreaterThanCode(r#" '\w' "#)),
        (r#"        ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_escaped_planet123() {
    test(r#"=> '\planet123' ,"#, vec![
        (r#"~~~~~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" '\planet123' "#)),
        (r#"                ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_openningcurlybracket() {
    test(r#"=> '{' ,"#, vec![
        (r#"~~~~~~~ "#, EqualsGreaterThanCode(r#" '{' "#)),
        (r#"       ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_openningsquarebracket() {
    test(r#"=> '[' ,"#, vec![
        (r#"~~~~~~~ "#, EqualsGreaterThanCode(r#" '[' "#)),
        (r#"       ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_openningbracket_wrapped_by_brackets() {
    test(r#"=> ('(') ,"#, vec![
        (r#"~~~~~~~~~ "#, EqualsGreaterThanCode(r#" ('(') "#)),
        (r#"         ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_one_character_closingbracket_wrapped_by_brackets() {
    test(r#"=> (')') ,"#, vec![
        (r#"~~~~~~~~~ "#, EqualsGreaterThanCode(r#" (')') "#)),
        (r#"         ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_tuple() {
    test(r#"=> (1,2,3) ,"#, vec![
        (r#"~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" (1,2,3) "#)),
        (r#"           ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_statement_with_lifetime() {
    test(r#"=> HuffmanTable::<Code<'a>>::new() ,"#, vec![
        (r#"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" HuffmanTable::<Code<'a>>::new() "#)),
        (r#"                                   ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_statement_with_many_lifetimes() {
    test(r#"=> (HuffmanTable::<Code<'a, 'b>>::new()),"#, vec![
        (r#"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" (HuffmanTable::<Code<'a, 'b>>::new())"#)),
        (r#"                                        ~"#, Comma),
    ]);
}

#[test]
fn equalsgreaterthancode_nested_function_with_lifetimes() {
    test(r#"=> fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {} ,"#, vec![
        (r#"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {} "#)),
        (r#"                                                    ~"#, Comma),
    ]);
}

#[test]
fn where_with_lifetimes() {
    test(r#"where <'a,bar<'b,'c>>,baz;"#, vec![
        (r#"~~~~~~~~~~~~~~~~~~~~~~~~~ "#, Where(vec![" <'a,bar<'b,'c>>", "baz"])),
        (r#"                         ~"#, Semi),
    ]);
}

#[test]
fn equalsgreaterthancode_error_unbalanced() {
    test_err(r#"=> (,"#,
            (r#"~    "#, ErrorCode::UnterminatedCode)
    )
}

#[test]
fn equalsgreaterthancode_error_unbalanced_closingbracket_character() {
    test_err(r#"=> (,')',"#,
            (r#"~        "#, ErrorCode::UnterminatedCode)
    )
}

#[test]
fn equalsgreaterthancode_error_unterminated_string_literal() {
    test_err(r#"=>  "Jan III Sobieski"#,
            (r#"    ~                "#, ErrorCode::UnterminatedStringLiteral)
    )
}

#[test]
fn equalsgreaterthancode_error_unterminated_character_literal() {
    test_err(r#"=>  '\x233  "#,
            (r#"    ~       "#, ErrorCode::UnterminatedCharacterLiteral)
    )
}

#[test]
fn equalsgreaterthancode_error_end_of_input_instead_of_closing_normal_character_literal() {
    test_err(r#"=>  'x"#,
            (r#"    ~ "#, ErrorCode::UnterminatedCharacterLiteral)
    )
}

#[test]
fn code_paren() { // Issue #25
    test(r#"=> a("(", c),"#, vec![
        (r#"~~~~~~~~~~~~ "#, EqualsGreaterThanCode(r#" a("(", c)"#)),
        (r#"            ~"#, Comma),
    ]);
}

#[test]
fn code_regex_paren() { // Issue #25
    test(r###"=> a(r##"("#""##, c),"###, vec![
        (r###"~~~~~~~~~~~~~~~~~~~~ "###, EqualsGreaterThanCode(r###" a(r##"("#""##, c)"###)),
        (r###"                    ~"###, Comma),
    ]);
}

#[test]
fn code_comment_eol() {
    test("=> a(// (
),", vec![
        ("~~~~~~~~~
~,", EqualsGreaterThanCode(" a(// (\n)")),
        ("=> a(// (
)~", Comma)]);
}

#[test]
fn code2() {
    test("=>? a(b, c),", vec![
        ("~~~~~~~~~~~ ", EqualsGreaterThanQuestionCode(" a(b, c)")),
        ("           ~", Comma),
    ]);
}

#[test]
#[should_panic]
fn code_forgot_comma() {
    test("=> a(b, c),", vec![
        ("~~~~~~~~~~ ", EqualsGreaterThanCode(" a(b, c)")),
        // intentionally forget the comma token; this is more of a test of `test`
    ]);
}

#[test]
fn various_kinds_of_ids() {
    test("foo<T<'a,U,`Z*{}`>>", vec![
        ("~~~                ", MacroId("foo")),
        ("   ~               ", LessThan),
        ("    ~              ", MacroId("T")),
        ("     ~             ", LessThan),
        ("      ~~           ", Lifetime("'a")),
        ("        ~          ", Comma),
        ("         ~         ", Id("U")),
        ("          ~        ", Comma),
        ("           ~~~~~~  ", Escape("Z*{}")),
        ("                 ~ ", GreaterThan),
        ("                  ~", GreaterThan),
    ]);
}

#[test]
fn string_literals() {
    test(r#"foo "bar\"\n" baz"#, vec![
        (r#"~~~              "#, Id("foo")),
        (r#"    ~~~~~~~~~    "#, StringLiteral(r#"bar\"\n"#)),
        (r#"              ~~~"#, Id("baz")),
    ]);
}

#[test]
fn use1() {
    test(r#"use foo::bar; baz"#, vec![
        (r#"~~~~~~~~~~~~     "#, Use(" foo::bar")),
        (r#"            ~    "#, Semi),
        (r#"              ~~~"#, Id("baz")),
    ]);
}

#[test]
fn use2() {
    test(r#"use {foo,bar}; baz"#, vec![
        (r#"~~~~~~~~~~~~~     "#, Use(" {foo,bar}")),
        (r#"             ~    "#, Semi),
        (r#"               ~~~"#, Id("baz")),
    ]);
}

#[test]
fn where1() {
    test(r#"where <foo,bar>,baz;"#, vec![
        (r#"~~~~~~~~~~~~~~~~~~~ "#, Where(vec![" <foo,bar>", "baz"])),
        (r#"                   ~"#, Semi),
    ]);
}

#[test]
fn regex1() {
    test(r#####"raa r##" #"#"" "#"##rrr"#####, vec![
        (r#####"~~~                    "#####, Id("raa")),
        (r#####"    ~~~~~~~~~~~~~~~~   "#####, RegexLiteral(r##" #"#"" "#"##)),
        (r#####"                    ~~~"#####, Id("rrr")),
    ]);
}

#[test]
fn regex2() {
    test(r#"r"(123""#, vec![
        (r#"~~~~~~~"#, RegexLiteral(r"(123")),
    ]);
}

<|endoftext|>


<commit_before>use fall_tree::{File, TextEdit, TextRange, TextUnit, FileEdit, AstNode};
use fall_tree::visitor::{process_subtree_bottom_up, visitor};
use fall_tree::search::ast;
use fall_editor::{EditorFileImpl, gen_syntax_tree, FileStructureNode};
use fall_editor::hl::{self, Highlights};
use *;

pub struct RustEditorFile {
    file: File
}

impl RustEditorFile {
    fn new(file: File) -> RustEditorFile {
        RustEditorFile { file }
    }
}

impl EditorFileImpl for RustEditorFile {
    fn parse(text: &str) -> Self {
        RustEditorFile::new(lang_rust().parse(text))
    }

    fn edit(&self, edit: &TextEdit) -> Self {
        RustEditorFile::new(self.file.edit(edit))
    }

    fn file(&self) -> &File {
        &self.file
    }

    fn syntax_tree(&self) -> String {
        gen_syntax_tree(&self.file)
    }

    fn highlight(&self) -> Highlights {
        process_subtree_bottom_up(
            self.file.root(),
            hl::visitor(
                &[]
            ),
        )
    }

    fn structure(&self) -> Vec<FileStructureNode> {
        fn process_name_owner<'f, D: NameOwner<'f>>(def: D, nodes: &mut Vec<FileStructureNode>) {
            if let Some(name_ident) = def.name_ident() {
                nodes.push(FileStructureNode {
                    name: name_ident.text().to_string(),
                    range: def.node().range(),
                    children: Vec::new(),
                })
            }
        }
        process_subtree_bottom_up(
            self.file().root(),
            visitor(Vec::new())
                .visit::<FnDef, _>(|nodes, def| process_name_owner(def, nodes))
                .visit::<StructDef, _>(|nodes, def| process_name_owner(def, nodes))
                .visit::<EnumDef, _>(|nodes, def| process_name_owner(def, nodes))
                .visit::<TraitDef, _>(|nodes, def| process_name_owner(def, nodes)),
        )
    }

    fn context_actions(&self, range: TextRange) -> Vec<&'static str> {
        if add_use_braces(self.file(), range.start(), false).is_some() {
            return vec!["Add braces"];
        }
        vec!["DUMMY"]
    }

    fn apply_context_action(&self, range: TextRange, id: &str) -> Option<TextEdit> {
        if id == "Add braces" {
            let edit = add_use_braces(self.file(), range.start(), true)?.into_edit();
            return Some(edit);
        }
        None
    }
}

fn add_use_braces(file: &File, offset: TextUnit, apply: bool) -> Option<ActionResult> {
    let use_decl: UseDecl = ast::node_at_offset(file.root(), offset)?;
    let path = use_decl.path()?;
    let last_segment = path.segment()?.node();
    if use_decl.spec().is_some() {
        return None;
    }
    if !apply {
        return Some(ActionResult::Available);
    }
    let mut edit = FileEdit::new(&file);
    edit.replace_with_text(last_segment, format!("{{{}}}", last_segment.text()));
    Some(ActionResult::Applied(edit.into_text_edit()))
}

enum ActionResult {
    Available,
    Applied(TextEdit),
}

impl ActionResult {
    fn into_edit(self) -> TextEdit {
        match self {
            ActionResult::Available =>
                panic!("Context action should provide edit when apply is set to true"),
            ActionResult::Applied(edit) => edit,
        }
    }
}

#[test]
fn test_extract_sub_seq() {
    use fall_editor::check_context_action;

    check_context_action::<RustEditorFile>("Add braces", r"
use foo::^^bar;
", r"
use foo::{bar};
");
}<commit_msg>Debug pring<commit_after>use fall_tree::{File, TextEdit, TextRange, TextUnit, FileEdit, AstNode};
use fall_tree::visitor::{process_subtree_bottom_up, visitor};
use fall_tree::search::ast;
use fall_editor::{EditorFileImpl, gen_syntax_tree, FileStructureNode};
use fall_editor::hl::{self, Highlights};
use *;

pub struct RustEditorFile {
    file: File
}

impl RustEditorFile {
    fn new(file: File) -> RustEditorFile {
        RustEditorFile { file }
    }
}

impl EditorFileImpl for RustEditorFile {
    fn parse(text: &str) -> Self {
        RustEditorFile::new(lang_rust().parse(text))
    }

    fn edit(&self, edit: &TextEdit) -> Self {
        RustEditorFile::new(self.file.edit(edit))
    }

    fn file(&self) -> &File {
        &self.file
    }

    fn syntax_tree(&self) -> String {
        gen_syntax_tree(&self.file)
    }

    fn highlight(&self) -> Highlights {
        process_subtree_bottom_up(
            self.file.root(),
            hl::visitor(
                &[]
            ),
        )
    }

    fn structure(&self) -> Vec<FileStructureNode> {
        fn process_name_owner<'f, D: NameOwner<'f>>(def: D, nodes: &mut Vec<FileStructureNode>) {
            if let Some(name_ident) = def.name_ident() {
                nodes.push(FileStructureNode {
                    name: name_ident.text().to_string(),
                    range: def.node().range(),
                    children: Vec::new(),
                })
            }
        }
        process_subtree_bottom_up(
            self.file().root(),
            visitor(Vec::new())
                .visit::<FnDef, _>(|nodes, def| process_name_owner(def, nodes))
                .visit::<StructDef, _>(|nodes, def| process_name_owner(def, nodes))
                .visit::<EnumDef, _>(|nodes, def| process_name_owner(def, nodes))
                .visit::<TraitDef, _>(|nodes, def| process_name_owner(def, nodes)),
        )
    }

    fn context_actions(&self, range: TextRange) -> Vec<&'static str> {
        if add_use_braces(self.file(), range.start(), false).is_some() {
            return vec!["Add braces"];
        }
        Vec::new()
    }

    fn apply_context_action(&self, range: TextRange, id: &str) -> Option<TextEdit> {
        if id == "Add braces" {
            let edit = add_use_braces(self.file(), range.start(), true)?.into_edit();
            return Some(edit);
        }
        None
    }
}

fn add_use_braces(file: &File, offset: TextUnit, apply: bool) -> Option<ActionResult> {
    let use_decl: UseDecl = ast::node_at_offset(file.root(), offset)?;
    let path = use_decl.path()?;
    let last_segment = path.segment()?.node();
    if use_decl.spec().is_some() {
        return None;
    }
    if !apply {
        return Some(ActionResult::Available);
    }
    let mut edit = FileEdit::new(&file);
    edit.replace_with_text(last_segment, format!("{{{}}}", last_segment.text()));
    Some(ActionResult::Applied(edit.into_text_edit()))
}

enum ActionResult {
    Available,
    Applied(TextEdit),
}

impl ActionResult {
    fn into_edit(self) -> TextEdit {
        match self {
            ActionResult::Available =>
                panic!("Context action should provide edit when apply is set to true"),
            ActionResult::Applied(edit) => edit,
        }
    }
}

#[test]
fn test_extract_sub_seq() {
    use fall_editor::check_context_action;

    check_context_action::<RustEditorFile>("Add braces", r"
use foo::^^bar;
", r"
use foo::{bar};
");
}<|endoftext|>


<commit_before>//! The client's "main" thread.

use client::LOD_THRESHOLDS;
use client_update::{ViewToClient, apply_view_to_client, apply_server_to_client};
use common::block_position::BlockPosition;
use common::communicate::{ClientToServer, ServerToClient};
use common::lod::LODIndex;
use common::process_events::process_channel;
use common::surroundings_loader::LODChange;
use std::num;
use std::old_io::timer;
use std::sync::mpsc::{Sender, Receiver};
use std::time::duration::Duration;
use view_update::ClientToView;
use view_update::ClientToView::*;

#[allow(missing_docs)]
pub fn client_thread(
  my_url: String,
  ups_from_server: Receiver<ServerToClient>,
  ups_to_server: Sender<ClientToServer>,
  ups_from_view: Receiver<ViewToClient>,
  ups_to_view: Sender<ClientToView>,
) {
  let ups_from_server = &ups_from_server;
  let ups_to_server = &ups_to_server;
  let ups_from_view = &ups_from_view;
  let ups_to_view = &ups_to_view;

  ups_to_server.send(ClientToServer::Init(my_url)).unwrap();

  let mut client = None;

  loop {
    let quit =
      !process_channel(
        ups_from_view,
        |update| {
          apply_view_to_client(update, ups_to_server);
          true
        },
      );
    if quit {
      break;
    }

    process_channel(
      ups_from_server,
      |update| {
        apply_server_to_client(update, &mut client, &ups_to_view);
        true
      },
    );

    client.as_mut().map(|client| {
      let block_position = BlockPosition::from_world_position(&client.player_position);

      let loaded_blocks = &mut client.loaded_blocks;
      client.surroundings_loader.update(
        block_position,
        |lod_change| {
          match lod_change {
            LODChange::Load(block_position, distance, _) => {
              let lod = lod_index(distance);
              ups_to_server.send(ClientToServer::RequestBlock(block_position, lod)).unwrap();
            },
            LODChange::Unload(block_position, _) => {
              loaded_blocks.remove(&block_position)
                // If it wasn't loaded, don't unload anything.
                .map(|(block, prev_lod)| {
                  for id in block.ids.iter() {
                    ups_to_view.send(RemoveTerrain(*id)).unwrap();
                  }

                  ups_to_view.send(RemoveBlockData(block_position, prev_lod)).unwrap();
                });
            },
          };
        },
      );
    });

    timer::sleep(Duration::milliseconds(0));
  }

  debug!("client exiting.");
}

fn lod_index(distance: i32) -> LODIndex {
  assert!(distance >= 0);
  let mut lod = 0;
  while
    lod < LOD_THRESHOLDS.len()
    && LOD_THRESHOLDS[lod] < distance
  {
    lod += 1;
  }
  LODIndex(num::cast(lod).unwrap())
}
<commit_msg>Client processes Quit signals properly.<commit_after>//! The client's "main" thread.

use client::LOD_THRESHOLDS;
use client_update::{ViewToClient, apply_view_to_client, apply_server_to_client};
use common::block_position::BlockPosition;
use common::communicate::{ClientToServer, ServerToClient};
use common::lod::LODIndex;
use common::process_events::process_channel;
use common::surroundings_loader::LODChange;
use std::num;
use std::old_io::timer;
use std::sync::mpsc::{Sender, Receiver};
use std::time::duration::Duration;
use view_update::ClientToView;
use view_update::ClientToView::*;

#[allow(missing_docs)]
pub fn client_thread(
  my_url: String,
  ups_from_server: Receiver<ServerToClient>,
  ups_to_server: Sender<ClientToServer>,
  ups_from_view: Receiver<ViewToClient>,
  ups_to_view: Sender<ClientToView>,
) {
  let ups_from_server = &ups_from_server;
  let ups_to_server = &ups_to_server;
  let ups_from_view = &ups_from_view;
  let ups_to_view = &ups_to_view;

  ups_to_server.send(ClientToServer::Init(my_url)).unwrap();

  let mut client = None;

  loop {
    let quit =
      !process_channel(
        ups_from_view,
        |update| {
          apply_view_to_client(update, ups_to_server)
        },
      );
    if quit {
      break;
    }

    process_channel(
      ups_from_server,
      |update| {
        apply_server_to_client(update, &mut client, &ups_to_view);
        true
      },
    );

    client.as_mut().map(|client| {
      let block_position = BlockPosition::from_world_position(&client.player_position);

      let loaded_blocks = &mut client.loaded_blocks;
      client.surroundings_loader.update(
        block_position,
        |lod_change| {
          match lod_change {
            LODChange::Load(block_position, distance, _) => {
              let lod = lod_index(distance);
              ups_to_server.send(ClientToServer::RequestBlock(block_position, lod)).unwrap();
            },
            LODChange::Unload(block_position, _) => {
              loaded_blocks.remove(&block_position)
                // If it wasn't loaded, don't unload anything.
                .map(|(block, prev_lod)| {
                  for id in block.ids.iter() {
                    ups_to_view.send(RemoveTerrain(*id)).unwrap();
                  }

                  ups_to_view.send(RemoveBlockData(block_position, prev_lod)).unwrap();
                });
            },
          };
        },
      );
    });

    timer::sleep(Duration::milliseconds(0));
  }

  debug!("client exiting.");
}

fn lod_index(distance: i32) -> LODIndex {
  assert!(distance >= 0);
  let mut lod = 0;
  while
    lod < LOD_THRESHOLDS.len()
    && LOD_THRESHOLDS[lod] < distance
  {
    lod += 1;
  }
  LODIndex(num::cast(lod).unwrap())
}
<|endoftext|>


<commit_before>use base::world::{Chunk, ChunkProvider, World};
use super::GameContext;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use std::mem::replace;
use std::thread;
use std::cell::{Ref, RefCell};
use std::sync::mpsc::{Receiver, Sender, TryRecvError, channel};
use base::world::{CHUNK_SIZE, ChunkIndex};
use base::math::*;
use world::WorldView;

#[derive(Clone)]
pub struct WorldManager {
    shared: Rc<RefCell<Shared>>,
    chunk_requests: Sender<ChunkIndex>,
    context: Rc<GameContext>,
}

struct Shared {
    world: World,
    world_view: WorldView,
    provided_chunks: Receiver<(ChunkIndex, Chunk)>,
    sent_requests: HashSet<ChunkIndex>,
    load_distance: f32,
    player_chunk: ChunkIndex,
}

impl WorldManager {
    pub fn new(provider: Box<ChunkProvider>, game_context: Rc<GameContext>) -> Self {
        // Create two channels to send chunk positions and receive chunks.
        let (chunk_request_sender, chunk_request_recv) = channel();
        let (chunk_sender, chunk_recv) = channel();

        // Spawn worker thread, which will detach from the main thread. But
        // that is no problem: once the last sender is destroyed, the worker
        // thread will quit.
        thread::spawn(move || {
            worker_thread(provider, chunk_request_recv, chunk_sender);
        });

        let this = WorldManager {
            shared: Rc::new(RefCell::new(Shared {
                world: World::empty(),
                world_view: WorldView::from_world(&World::empty(), game_context.get_facade()),
                sent_requests: HashSet::new(),
                provided_chunks: chunk_recv,
                // TODO: load this from the config!
                load_distance: 7.0,
                player_chunk: ChunkIndex(AxialPoint::new(0, 0)),
            })),
            chunk_requests: chunk_request_sender,
            context: game_context,
        };

        this.update_player_chunk();
        this
    }

    /// Called when the player moves to a different chunk.
    ///
    /// This unloads all currently loaded chunks that are too far away from the
    /// player, and loads all chunks close enough to the player (if they aren't
    /// already requested).
    fn update_player_chunk(&self) {
        let mut shared = self.shared.borrow_mut();
        let player_chunk = shared.player_chunk.0;
        let radius = shared.load_distance as i32;

        // Load new range
        for qd in -radius..radius {
            for rd in -radius..radius {
                let chunk_pos = AxialPoint::new(player_chunk.q + qd, player_chunk.r + rd);
                if (chunk_pos - player_chunk).to_real().distance(Vector2::zero()) <
                   shared.load_distance {
                    let chunk_index = ChunkIndex(chunk_pos);

                    if !shared.world.chunks.contains_key(&chunk_index) {
                        self.request_chunk(chunk_index, &mut shared.sent_requests);
                    }
                }
            }
        }

        // Drop unneeded chunks from world
        let chunks = replace(&mut shared.world.chunks, HashMap::new());
        let mut new_chunks = HashMap::new();
        for (index, chunk) in chunks {
            let chunk_pos = index.0;
            if (chunk_pos - player_chunk).to_real().distance(Vector2::zero()) <
               shared.load_distance {
                // Still in range
                new_chunks.insert(index, chunk);
            } else {
                // Remove
                shared.world_view.remove_chunk(index);
            }
        }
        shared.world.chunks = new_chunks;
    }

    /// Sends a chunk request if that was not already done for this chunk.
    fn request_chunk(&self, index: ChunkIndex, sent_requests: &mut HashSet<ChunkIndex>) {
        if !sent_requests.contains(&index) {
            self.chunk_requests.send(index).unwrap();
            sent_requests.insert(index);
        }
    }

    /// Returns an immutable reference to the world.
    ///
    /// *Note*: since the world manager uses a `RefCell` to save the world, a
    /// `Ref` is returned. But thanks to deref coercions you can use it like a
    /// standard reference.
    pub fn get_world(&self) -> Ref<World> {
        Ref::map(self.shared.borrow(), |shared| &shared.world)
    }

    /// Returns an immutable reference to the world view.
    pub fn get_view(&self) -> Ref<WorldView> {
        Ref::map(self.shared.borrow(), |shared| &shared.world_view)
    }

    /// Starts to generate all chunks within `load_distance` (config parameter)
    /// around `pos`.
    fn load_world_around(&self, pos: Point2f) {
        let axial_pos = AxialPoint::from_real(pos);
        let chunk_pos = AxialPoint::new(axial_pos.q / CHUNK_SIZE as i32,
                                        axial_pos.r / CHUNK_SIZE as i32);

        let mut shared = self.shared.borrow_mut();
        if shared.player_chunk.0 != chunk_pos {
            shared.player_chunk = ChunkIndex(chunk_pos);
            debug!("player moved to chunk {:?}", chunk_pos);
            drop(shared);

            self.update_player_chunk();
        }
    }

    /// Applies all queued updated to the actual world. Notably, all generated
    /// chunks are added.
    pub fn update_world(&self, player_pos: Point3f) {
        self.load_world_around(Point2f::new(player_pos.x, player_pos.y));

        let mut shared = self.shared.borrow_mut();

        loop {
            let (pos, chunk) = match shared.provided_chunks.try_recv() {
                Err(TryRecvError::Empty) => {
                    // No new chunks for us, we will check again next time ;-)
                    break;
                }
                Err(TryRecvError::Disconnected) => {
                    // The worker thread has shut down: this should never happen
                    // thus we can just panic, too.
                    error!("chunk providing worker thread shut down");
                    panic!("chunk providing worker thread shut down");
                }
                Ok(val) => val,
            };

            shared.world_view.refresh_chunk(pos, &chunk, self.context.get_facade());

            shared.sent_requests.remove(&pos);
            let res = shared.world.add_chunk(pos, chunk);
            if res.is_err() {
                warn!("chunk at {:?} already exists!", pos);
            }
        }
    }
}

fn worker_thread(provider: Box<ChunkProvider>,
                 commands: Receiver<ChunkIndex>,
                 chunks: Sender<(ChunkIndex, Chunk)>) {
    loop {
        let requested_chunk = match commands.recv() {
            Err(_) => {
                // The other side has hung up, so we can stop working, too.
                break;
            }
            Ok(index) => index,
        };

        debug!("chunk provider thread: received request to generate chunk {:?}",
               requested_chunk.0);

        match provider.load_chunk(requested_chunk) {
            Some(chunk) => {
                debug!("chunk provider thread: chunk at {:?} successfully loaded",
                       requested_chunk);
                chunks.send((requested_chunk, chunk)).expect("main thread has hung up");
            }
            None => {
                warn!("chunk provider thread: failed to load chunk at {:?}",
                      requested_chunk)
            }
        }
    }

    info!("chunk provider thread: now stopping ...")
}
<commit_msg>inline request_chunk<commit_after>use base::world::{Chunk, ChunkProvider, World};
use super::GameContext;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;
use std::mem::replace;
use std::thread;
use std::cell::{Ref, RefCell};
use std::sync::mpsc::{Receiver, Sender, TryRecvError, channel};
use base::world::{CHUNK_SIZE, ChunkIndex};
use base::math::*;
use world::WorldView;

#[derive(Clone)]
pub struct WorldManager {
    shared: Rc<RefCell<Shared>>,
    chunk_requests: Sender<ChunkIndex>,
    context: Rc<GameContext>,
}

struct Shared {
    world: World,
    world_view: WorldView,
    provided_chunks: Receiver<(ChunkIndex, Chunk)>,
    sent_requests: HashSet<ChunkIndex>,
    load_distance: f32,
    player_chunk: ChunkIndex,
}

impl WorldManager {
    pub fn new(provider: Box<ChunkProvider>, game_context: Rc<GameContext>) -> Self {
        // Create two channels to send chunk positions and receive chunks.
        let (chunk_request_sender, chunk_request_recv) = channel();
        let (chunk_sender, chunk_recv) = channel();

        // Spawn worker thread, which will detach from the main thread. But
        // that is no problem: once the last sender is destroyed, the worker
        // thread will quit.
        thread::spawn(move || {
            worker_thread(provider, chunk_request_recv, chunk_sender);
        });

        let this = WorldManager {
            shared: Rc::new(RefCell::new(Shared {
                world: World::empty(),
                world_view: WorldView::from_world(&World::empty(), game_context.get_facade()),
                sent_requests: HashSet::new(),
                provided_chunks: chunk_recv,
                // TODO: load this from the config!
                load_distance: 7.0,
                player_chunk: ChunkIndex(AxialPoint::new(0, 0)),
            })),
            chunk_requests: chunk_request_sender,
            context: game_context,
        };

        this.update_player_chunk();
        this
    }

    /// Called when the player moves to a different chunk.
    ///
    /// This unloads all currently loaded chunks that are too far away from the
    /// player, and loads all chunks close enough to the player (if they aren't
    /// already requested).
    fn update_player_chunk(&self) {
        let mut shared = self.shared.borrow_mut();
        let player_chunk = shared.player_chunk.0;
        let radius = shared.load_distance as i32;

        // Load new range
        for qd in -radius..radius {
            for rd in -radius..radius {
                let chunk_pos = AxialPoint::new(player_chunk.q + qd, player_chunk.r + rd);
                if (chunk_pos - player_chunk).to_real().distance(Vector2::zero()) <
                   shared.load_distance {
                    let chunk_index = ChunkIndex(chunk_pos);

                    if !shared.world.chunks.contains_key(&chunk_index) {
                        if !shared.sent_requests.contains(&chunk_index) {
                            self.chunk_requests.send(chunk_index).unwrap();
                            shared.sent_requests.insert(chunk_index);
                        }
                    }
                }
            }
        }

        // Drop unneeded chunks from world
        let chunks = replace(&mut shared.world.chunks, HashMap::new());
        let mut new_chunks = HashMap::new();
        for (index, chunk) in chunks {
            let chunk_pos = index.0;
            if (chunk_pos - player_chunk).to_real().distance(Vector2::zero()) <
               shared.load_distance {
                // Still in range
                new_chunks.insert(index, chunk);
            } else {
                // Remove
                shared.world_view.remove_chunk(index);
            }
        }
        shared.world.chunks = new_chunks;
    }

    /// Returns an immutable reference to the world.
    ///
    /// *Note*: since the world manager uses a `RefCell` to save the world, a
    /// `Ref` is returned. But thanks to deref coercions you can use it like a
    /// standard reference.
    pub fn get_world(&self) -> Ref<World> {
        Ref::map(self.shared.borrow(), |shared| &shared.world)
    }

    /// Returns an immutable reference to the world view.
    pub fn get_view(&self) -> Ref<WorldView> {
        Ref::map(self.shared.borrow(), |shared| &shared.world_view)
    }

    /// Starts to generate all chunks within `load_distance` (config parameter)
    /// around `pos`.
    fn load_world_around(&self, pos: Point2f) {
        let axial_pos = AxialPoint::from_real(pos);
        let chunk_pos = AxialPoint::new(axial_pos.q / CHUNK_SIZE as i32,
                                        axial_pos.r / CHUNK_SIZE as i32);

        let mut shared = self.shared.borrow_mut();
        if shared.player_chunk.0 != chunk_pos {
            shared.player_chunk = ChunkIndex(chunk_pos);
            debug!("player moved to chunk {:?}", chunk_pos);
            drop(shared);

            self.update_player_chunk();
        }
    }

    /// Applies all queued updated to the actual world. Notably, all generated
    /// chunks are added.
    pub fn update_world(&self, player_pos: Point3f) {
        self.load_world_around(Point2f::new(player_pos.x, player_pos.y));

        let mut shared = self.shared.borrow_mut();

        loop {
            let (pos, chunk) = match shared.provided_chunks.try_recv() {
                Err(TryRecvError::Empty) => {
                    // No new chunks for us, we will check again next time ;-)
                    break;
                }
                Err(TryRecvError::Disconnected) => {
                    // The worker thread has shut down: this should never happen
                    // thus we can just panic, too.
                    error!("chunk providing worker thread shut down");
                    panic!("chunk providing worker thread shut down");
                }
                Ok(val) => val,
            };

            shared.world_view.refresh_chunk(pos, &chunk, self.context.get_facade());

            shared.sent_requests.remove(&pos);
            let res = shared.world.add_chunk(pos, chunk);
            if res.is_err() {
                warn!("chunk at {:?} already exists!", pos);
            }
        }
    }
}

fn worker_thread(provider: Box<ChunkProvider>,
                 commands: Receiver<ChunkIndex>,
                 chunks: Sender<(ChunkIndex, Chunk)>) {
    loop {
        let requested_chunk = match commands.recv() {
            Err(_) => {
                // The other side has hung up, so we can stop working, too.
                break;
            }
            Ok(index) => index,
        };

        debug!("chunk provider thread: received request to generate chunk {:?}",
               requested_chunk.0);

        match provider.load_chunk(requested_chunk) {
            Some(chunk) => {
                debug!("chunk provider thread: chunk at {:?} successfully loaded",
                       requested_chunk);
                chunks.send((requested_chunk, chunk)).expect("main thread has hung up");
            }
            None => {
                warn!("chunk provider thread: failed to load chunk at {:?}",
                      requested_chunk)
            }
        }
    }

    info!("chunk provider thread: now stopping ...")
}
<|endoftext|>