<commit_before>// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use colored::*;
use connection::Connection;
use control_file;
use evcxr;
use evcxr::CommandContext;
use failure::Error;
use json;
use json::JsonValue;
use jupyter_message::JupyterMessage;
use std;
use std::collections::HashMap;
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
use std::time;
use zmq;

// Note, to avoid potential deadlocks, each thread should lock at most one mutex at a time.
#[derive(Clone)]
pub(crate) struct Server {
    iopub: Arc<Mutex<Connection>>,
    _stdin: Arc<Mutex<Connection>>,
    latest_execution_request: Arc<Mutex<Option<JupyterMessage>>>,
    shutdown_requested_receiver: Arc<Mutex<mpsc::Receiver<()>>>,
    shutdown_requested_sender: Arc<Mutex<mpsc::Sender<()>>>,
}

impl Server {
    pub(crate) fn start(config: &control_file::Control) -> Result<Server, Error> {
        use zmq::SocketType;

        let zmq_context = zmq::Context::new();
        let heartbeat = bind_socket(config, config.hb_port, zmq_context.socket(SocketType::REP)?)?;
        let shell_socket = bind_socket(
            config,
            config.shell_port,
            zmq_context.socket(SocketType::ROUTER)?,
        )?;
        let control_socket = bind_socket(
            config,
            config.control_port,
            zmq_context.socket(SocketType::ROUTER)?,
        )?;
        let stdin_socket = bind_socket(
            config,
            config.stdin_port,
            zmq_context.socket(SocketType::ROUTER)?,
        )?;
        let iopub = Arc::new(Mutex::new(bind_socket(
            config,
            config.iopub_port,
            zmq_context.socket(SocketType::PUB)?,
        )?));

        let (shutdown_requested_sender, shutdown_requested_receiver) = mpsc::channel();

        let server = Server {
            iopub,
            latest_execution_request: Arc::new(Mutex::new(None)),
            _stdin: Arc::new(Mutex::new(stdin_socket)),
            shutdown_requested_receiver: Arc::new(Mutex::new(shutdown_requested_receiver)),
            shutdown_requested_sender: Arc::new(Mutex::new(shutdown_requested_sender)),
        };

        let (execution_sender, execution_receiver) = mpsc::channel();
        let (execution_response_sender, execution_response_receiver) = mpsc::channel();

        thread::spawn(move || Self::handle_hb(&heartbeat));
        server.start_thread(move |server: Server| server.handle_control(control_socket));
        server.start_thread(move |server: Server| {
            server.handle_shell(
                shell_socket,
                &execution_sender,
                &execution_response_receiver,
            )
        });
        let (context, outputs) = CommandContext::new()?;
        server.start_thread(move |server: Server| {
            server.handle_execution_requests(
                context,
                &execution_receiver,
                &execution_response_sender,
            )
        });
        server
            .clone()
            .start_output_pass_through_thread("stdout", outputs.stdout);
        server
            .clone()
            .start_output_pass_through_thread("stderr", outputs.stderr);
        Ok(server)
    }

    pub(crate) fn wait_for_shutdown(&self) {
        self.shutdown_requested_receiver
            .lock()
            .unwrap()
            .recv()
            .unwrap();
    }

    fn signal_shutdown(&self) {
        self.shutdown_requested_sender
            .lock()
            .unwrap()
            .send(())
            .unwrap();
    }

    fn start_thread<F>(&self, body: F)
    where
        F: FnOnce(Server) -> Result<(), Error> + std::marker::Send + 'static,
    {
        let server_clone = self.clone();
        thread::spawn(|| {
            if let Err(error) = body(server_clone) {
                eprintln!("{:?}", error);
            }
        });
    }

    fn handle_hb(connection: &Connection) -> Result<(), Error> {
        let mut message = zmq::Message::new()?;
        loop {
            connection.socket.recv(&mut message, 0)?;
            connection.socket.send(b"ping", 0)?;
        }
    }

    fn handle_execution_requests(
        self,
        mut context: CommandContext,
        receiver: &mpsc::Receiver<JupyterMessage>,
        execution_reply_sender: &mpsc::Sender<JupyterMessage>,
    ) -> Result<(), Error> {
        let mut execution_count = 1;
        loop {
            let message = receiver.recv()?;

            // If we want this clone to be cheaper, we probably only need the header, not the
            // whole message.
            *self.latest_execution_request.lock().unwrap() = Some(message.clone());
            let code = message.code();
            execution_count += 1;
            message
                .new_message("execute_input")
                .with_content(object!{
                    "execution_count" => execution_count,
                    "code" => code
                }).send(&mut *self.iopub.lock().unwrap())?;
            let reply = match context.execute(code) {
                Ok(output) => {
                    if !output.is_empty() {
                        // Increase the odds that stdout will have been finished being sent. A
                        // less hacky alternative would be to add a print statement, then block
                        // waiting for it.
                        thread::sleep(time::Duration::from_millis(1));
                        let mut data = HashMap::new();
                        // At the time of writing the json crate appears to have a generic From
                        // implementation for a Vec<T> where T implements Into<JsonValue>. It also
                        // has conversion from HashMap<String, JsonValue>, but it doesn't have
                        // conversion from HashMap<String, T>. Perhaps send a PR? For now, we
                        // convert the values manually.
                        for (k, v) in output.content_by_mime_type {
                            data.insert(k, json::from(v));
                        }
                        message
                            .new_message("execute_result")
                            .with_content(object!{
                                "execution_count" => execution_count,
                                "data" => data,
                            }).send(&mut *self.iopub.lock().unwrap())?;
                    }
                    message.new_reply().with_content(object!{
                        "status" => "ok",
                        "execution_count" => execution_count
                    })
                }
                Err(errors) => {
                    self.emit_errors(&errors, &message)?;
                    message.new_reply().with_content(object!{
                        "status" => "error",
                        "execution_count" => execution_count,
                    })
                }
            };
            execution_reply_sender.send(reply)?;
        }
    }

    fn handle_shell(
        self,
        mut connection: Connection,
        execution_channel: &mpsc::Sender<JupyterMessage>,
        execution_reply_receiver: &mpsc::Receiver<JupyterMessage>,
    ) -> Result<(), Error> {
        loop {
            let message = JupyterMessage::read(&mut connection)?;
            // Processing of every message should be enclosed between "busy" and "idle"
            // see https://jupyter-client.readthedocs.io/en/latest/messaging.html#messages-on-the-shell-router-dealer-channel
            // Jupiter Lab doesn't use the kernel until it received "idle" for kernel_info_request
            message
                .new_message("status")
                .with_content(object!{"execution_state" => "busy"})
                .send(&mut *self.iopub.lock().unwrap())?;
            let idle = message
                .new_message("status")
                .with_content(object!{"execution_state" => "idle"});
            if message.message_type() == "kernel_info_request" {
                message
                    .new_reply()
                    .with_content(kernel_info())
                    .send(&mut connection)?;
            } else if message.message_type() == "is_complete_request" {
                message
                    .new_reply()
                    .with_content(object!{"status" => "complete"})
                    .send(&mut connection)?;
            } else if message.message_type() == "execute_request" {
                execution_channel.send(message)?;
                execution_reply_receiver.recv()?.send(&mut connection)?;
            } else if message.message_type() == "comm_open" {
                message
                    .new_message("comm_close")
                    .with_content(message.get_content().clone())
                    .send(&mut connection)?;
            } else {
                eprintln!(
                    "Got unrecognized message type on shell channel: {}",
                    message.message_type()
                );
            }
            idle.send(&mut *self.iopub.lock().unwrap())?;
        }
    }

    fn handle_control(self, mut connection: Connection) -> Result<(), Error> {
        loop {
            let message = JupyterMessage::read(&mut connection)?;
            match message.message_type() {
                "shutdown_request" => self.signal_shutdown(),
                "interrupt_request" => {
                    message.new_reply().send(&mut connection)?;
                    eprintln!(
                        "Rust doesn't support interrupting execution. Perhaps restart kernel?"
                    );
                }
                _ => {
                    eprintln!(
                        "Got unrecognized message type on control channel: {}",
                        message.message_type()
                    );
                }
            }
        }
    }

    fn start_output_pass_through_thread(
        self,
        output_name: &'static str,
        channel: mpsc::Receiver<String>,
    ) {
        thread::spawn(move || {
            while let Ok(line) = channel.recv() {
                let mut message = None;
                if let Some(exec_request) = &*self.latest_execution_request.lock().unwrap() {
                    message = Some(exec_request.new_message("stream"));
                }
                if let Some(message) = message {
                    if let Err(error) = message
                        .with_content(object!{
                            "name" => output_name,
                            "text" => format!("{}\n", line),
                        }).send(&mut *self.iopub.lock().unwrap())
                    {
                        eprintln!("{}", error);
                    }
                }
            }
        });
    }

    fn emit_errors(
        &self,
        errors: &evcxr::Error,
        parent_message: &JupyterMessage,
    ) -> Result<(), Error> {
        match errors {
            evcxr::Error::CompilationErrors(errors) => {
                for error in errors {
                    let message = format!("{}", error.message().bright_red());
                    if error.is_from_user_code() {
                        let mut traceback = Vec::new();
                        for spanned_message in error.spanned_messages() {
                            for line in &spanned_message.lines {
                                traceback.push(line.clone());
                            }
                            if let Some(span) = &spanned_message.span {
                                let mut carrots = String::new();
                                for _ in 1..span.start_column {
                                    carrots.push(' ');
                                }
                                for _ in span.start_column..span.end_column {
                                    carrots.push('^');
                                }
                                traceback.push(format!(
                                    "{} {}",
                                    carrots.bright_red(),
                                    spanned_message.label.bright_blue()
                                ));
                            } else {
                                traceback.push(spanned_message.label.clone());
                            }
                        }
                        traceback.push(error.message());
                        parent_message
                            .new_message("error")
                            .with_content(object!{
                                "ename" => "Error",
                                "evalue" => error.message(),
                                "traceback" => traceback,
                            }).send(&mut *self.iopub.lock().unwrap())?;
                    } else {
                        parent_message
                            .new_message("error")
                            .with_content(object!{
                                "ename" => "Error",
                                "evalue" => error.message(),
                                "traceback" => array![
                                    message
                                ],
                            }).send(&mut *self.iopub.lock().unwrap())?;
                    }
                }
            }
            error => {
                let displayed_error = format!("{}", error);
                parent_message
                    .new_message("error")
                    .with_content(object!{
                        "ename" => "Error",
                        "evalue" => displayed_error.clone(),
                        "traceback" => array![displayed_error],
                    }).send(&mut *self.iopub.lock().unwrap())?;
            }
        }
        Ok(())
    }
}

fn bind_socket(
    config: &control_file::Control,
    port: u16,
    socket: zmq::Socket,
) -> Result<Connection, Error> {
    let endpoint = format!("{}://{}:{}", config.transport, config.ip, port);
    socket.bind(&endpoint)?;
    Ok(Connection::new(socket, &config.key)?)
}

/// See [Kernel info documentation](https://jupyter-client.readthedocs.io/en/stable/messaging.html#kernel-info)
fn kernel_info() -> JsonValue {
    object!{
        "protocol_version" => "5.3",
        "implementation" => env!("CARGO_PKG_NAME"),
        "implementation_version" => env!("CARGO_PKG_VERSION"),
        "language_info" => object!{
            "name" => "Rust",
            "version" => "",
            "mimetype" => "text/rust",
            "file_extension" => ".rs",
            // Pygments lexer, for highlighting Only needed if it differs from the 'name' field.
            // see http://pygments.org/docs/lexers/#lexers-for-the-rust-language
            "pygment_lexer" => "rust",
            // Codemirror mode, for for highlighting in the notebook. Only needed if it differs from the 'name' field.
            // codemirror use text/x-rustsrc as mimetypes
            // see https://codemirror.net/mode/rust/
            "codemirror_mode" => "rust",
        },
        "banner" => format!("EvCxR {} - Evaluation Context for Rust", env!("CARGO_PKG_VERSION")),
        "help_links" => array![
            object!{"text" => "Rust std docs",
                    "url" => "https://doc.rust-lang.org/stable/std/"}
        ],
        "status" => "ok"
    }
}
<commit_msg>jupyter: protocol v5 add “metadata” into execution_response (else Jupyter lab ignore it) and export json content as json into data<commit_after>// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use colored::*;
use connection::Connection;
use control_file;
use evcxr;
use evcxr::CommandContext;
use failure::Error;
use json;
use json::JsonValue;
use jupyter_message::JupyterMessage;
use std;
use std::collections::HashMap;
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
use std::time;
use zmq;

// Note, to avoid potential deadlocks, each thread should lock at most one mutex at a time.
#[derive(Clone)]
pub(crate) struct Server {
    iopub: Arc<Mutex<Connection>>,
    _stdin: Arc<Mutex<Connection>>,
    latest_execution_request: Arc<Mutex<Option<JupyterMessage>>>,
    shutdown_requested_receiver: Arc<Mutex<mpsc::Receiver<()>>>,
    shutdown_requested_sender: Arc<Mutex<mpsc::Sender<()>>>,
}

impl Server {
    pub(crate) fn start(config: &control_file::Control) -> Result<Server, Error> {
        use zmq::SocketType;

        let zmq_context = zmq::Context::new();
        let heartbeat = bind_socket(config, config.hb_port, zmq_context.socket(SocketType::REP)?)?;
        let shell_socket = bind_socket(
            config,
            config.shell_port,
            zmq_context.socket(SocketType::ROUTER)?,
        )?;
        let control_socket = bind_socket(
            config,
            config.control_port,
            zmq_context.socket(SocketType::ROUTER)?,
        )?;
        let stdin_socket = bind_socket(
            config,
            config.stdin_port,
            zmq_context.socket(SocketType::ROUTER)?,
        )?;
        let iopub = Arc::new(Mutex::new(bind_socket(
            config,
            config.iopub_port,
            zmq_context.socket(SocketType::PUB)?,
        )?));

        let (shutdown_requested_sender, shutdown_requested_receiver) = mpsc::channel();

        let server = Server {
            iopub,
            latest_execution_request: Arc::new(Mutex::new(None)),
            _stdin: Arc::new(Mutex::new(stdin_socket)),
            shutdown_requested_receiver: Arc::new(Mutex::new(shutdown_requested_receiver)),
            shutdown_requested_sender: Arc::new(Mutex::new(shutdown_requested_sender)),
        };

        let (execution_sender, execution_receiver) = mpsc::channel();
        let (execution_response_sender, execution_response_receiver) = mpsc::channel();

        thread::spawn(move || Self::handle_hb(&heartbeat));
        server.start_thread(move |server: Server| server.handle_control(control_socket));
        server.start_thread(move |server: Server| {
            server.handle_shell(
                shell_socket,
                &execution_sender,
                &execution_response_receiver,
            )
        });
        let (context, outputs) = CommandContext::new()?;
        server.start_thread(move |server: Server| {
            server.handle_execution_requests(
                context,
                &execution_receiver,
                &execution_response_sender,
            )
        });
        server
            .clone()
            .start_output_pass_through_thread("stdout", outputs.stdout);
        server
            .clone()
            .start_output_pass_through_thread("stderr", outputs.stderr);
        Ok(server)
    }

    pub(crate) fn wait_for_shutdown(&self) {
        self.shutdown_requested_receiver
            .lock()
            .unwrap()
            .recv()
            .unwrap();
    }

    fn signal_shutdown(&self) {
        self.shutdown_requested_sender
            .lock()
            .unwrap()
            .send(())
            .unwrap();
    }

    fn start_thread<F>(&self, body: F)
    where
        F: FnOnce(Server) -> Result<(), Error> + std::marker::Send + 'static,
    {
        let server_clone = self.clone();
        thread::spawn(|| {
            if let Err(error) = body(server_clone) {
                eprintln!("{:?}", error);
            }
        });
    }

    fn handle_hb(connection: &Connection) -> Result<(), Error> {
        let mut message = zmq::Message::new()?;
        loop {
            connection.socket.recv(&mut message, 0)?;
            connection.socket.send(b"ping", 0)?;
        }
    }

    fn handle_execution_requests(
        self,
        mut context: CommandContext,
        receiver: &mpsc::Receiver<JupyterMessage>,
        execution_reply_sender: &mpsc::Sender<JupyterMessage>,
    ) -> Result<(), Error> {
        let mut execution_count = 1;
        loop {
            let message = receiver.recv()?;

            // If we want this clone to be cheaper, we probably only need the header, not the
            // whole message.
            *self.latest_execution_request.lock().unwrap() = Some(message.clone());
            let code = message.code();
            execution_count += 1;
            message
                .new_message("execute_input")
                .with_content(object!{
                    "execution_count" => execution_count,
                    "code" => code
                }).send(&mut *self.iopub.lock().unwrap())?;
            let reply = match context.execute(code) {
                Ok(output) => {
                    if !output.is_empty() {
                        // Increase the odds that stdout will have been finished being sent. A
                        // less hacky alternative would be to add a print statement, then block
                        // waiting for it.
                        thread::sleep(time::Duration::from_millis(1));
                        let mut data = HashMap::new();
                        // At the time of writing the json crate appears to have a generic From
                        // implementation for a Vec<T> where T implements Into<JsonValue>. It also
                        // has conversion from HashMap<String, JsonValue>, but it doesn't have
                        // conversion from HashMap<String, T>. Perhaps send a PR? For now, we
                        // convert the values manually.
                        for (k, v) in output.content_by_mime_type {
                            if k.contains("json") {
                                data.insert(k, json::parse(&v).unwrap_or(json::from(v)));
                            } else {
                                data.insert(k, json::from(v));
                            }
                        }
                        message
                            .new_message("execute_result")
                            .with_content(object!{
                                "execution_count" => execution_count,
                                "data" => data,
                                "metadata" => HashMap::new(),
                            }).send(&mut *self.iopub.lock().unwrap())?;
                    }
                    message.new_reply().with_content(object!{
                        "status" => "ok",
                        "execution_count" => execution_count
                    })
                }
                Err(errors) => {
                    self.emit_errors(&errors, &message)?;
                    message.new_reply().with_content(object!{
                        "status" => "error",
                        "execution_count" => execution_count,
                    })
                }
            };
            execution_reply_sender.send(reply)?;
        }
    }

    fn handle_shell(
        self,
        mut connection: Connection,
        execution_channel: &mpsc::Sender<JupyterMessage>,
        execution_reply_receiver: &mpsc::Receiver<JupyterMessage>,
    ) -> Result<(), Error> {
        loop {
            let message = JupyterMessage::read(&mut connection)?;
            // Processing of every message should be enclosed between "busy" and "idle"
            // see https://jupyter-client.readthedocs.io/en/latest/messaging.html#messages-on-the-shell-router-dealer-channel
            // Jupiter Lab doesn't use the kernel until it received "idle" for kernel_info_request
            message
                .new_message("status")
                .with_content(object!{"execution_state" => "busy"})
                .send(&mut *self.iopub.lock().unwrap())?;
            let idle = message
                .new_message("status")
                .with_content(object!{"execution_state" => "idle"});
            if message.message_type() == "kernel_info_request" {
                message
                    .new_reply()
                    .with_content(kernel_info())
                    .send(&mut connection)?;
            } else if message.message_type() == "is_complete_request" {
                message
                    .new_reply()
                    .with_content(object!{"status" => "complete"})
                    .send(&mut connection)?;
            } else if message.message_type() == "execute_request" {
                execution_channel.send(message)?;
                execution_reply_receiver.recv()?.send(&mut connection)?;
            } else if message.message_type() == "comm_open" {
                message
                    .new_message("comm_close")
                    .with_content(message.get_content().clone())
                    .send(&mut connection)?;
            } else {
                eprintln!(
                    "Got unrecognized message type on shell channel: {}",
                    message.message_type()
                );
            }
            idle.send(&mut *self.iopub.lock().unwrap())?;
        }
    }

    fn handle_control(self, mut connection: Connection) -> Result<(), Error> {
        loop {
            let message = JupyterMessage::read(&mut connection)?;
            match message.message_type() {
                "shutdown_request" => self.signal_shutdown(),
                "interrupt_request" => {
                    message.new_reply().send(&mut connection)?;
                    eprintln!(
                        "Rust doesn't support interrupting execution. Perhaps restart kernel?"
                    );
                }
                _ => {
                    eprintln!(
                        "Got unrecognized message type on control channel: {}",
                        message.message_type()
                    );
                }
            }
        }
    }

    fn start_output_pass_through_thread(
        self,
        output_name: &'static str,
        channel: mpsc::Receiver<String>,
    ) {
        thread::spawn(move || {
            while let Ok(line) = channel.recv() {
                let mut message = None;
                if let Some(exec_request) = &*self.latest_execution_request.lock().unwrap() {
                    message = Some(exec_request.new_message("stream"));
                }
                if let Some(message) = message {
                    if let Err(error) = message
                        .with_content(object!{
                            "name" => output_name,
                            "text" => format!("{}\n", line),
                        }).send(&mut *self.iopub.lock().unwrap())
                    {
                        eprintln!("{}", error);
                    }
                }
            }
        });
    }

    fn emit_errors(
        &self,
        errors: &evcxr::Error,
        parent_message: &JupyterMessage,
    ) -> Result<(), Error> {
        match errors {
            evcxr::Error::CompilationErrors(errors) => {
                for error in errors {
                    let message = format!("{}", error.message().bright_red());
                    if error.is_from_user_code() {
                        let mut traceback = Vec::new();
                        for spanned_message in error.spanned_messages() {
                            for line in &spanned_message.lines {
                                traceback.push(line.clone());
                            }
                            if let Some(span) = &spanned_message.span {
                                let mut carrots = String::new();
                                for _ in 1..span.start_column {
                                    carrots.push(' ');
                                }
                                for _ in span.start_column..span.end_column {
                                    carrots.push('^');
                                }
                                traceback.push(format!(
                                    "{} {}",
                                    carrots.bright_red(),
                                    spanned_message.label.bright_blue()
                                ));
                            } else {
                                traceback.push(spanned_message.label.clone());
                            }
                        }
                        traceback.push(error.message());
                        parent_message
                            .new_message("error")
                            .with_content(object!{
                                "ename" => "Error",
                                "evalue" => error.message(),
                                "traceback" => traceback,
                            }).send(&mut *self.iopub.lock().unwrap())?;
                    } else {
                        parent_message
                            .new_message("error")
                            .with_content(object!{
                                "ename" => "Error",
                                "evalue" => error.message(),
                                "traceback" => array![
                                    message
                                ],
                            }).send(&mut *self.iopub.lock().unwrap())?;
                    }
                }
            }
            error => {
                let displayed_error = format!("{}", error);
                parent_message
                    .new_message("error")
                    .with_content(object!{
                        "ename" => "Error",
                        "evalue" => displayed_error.clone(),
                        "traceback" => array![displayed_error],
                    }).send(&mut *self.iopub.lock().unwrap())?;
            }
        }
        Ok(())
    }
}

fn bind_socket(
    config: &control_file::Control,
    port: u16,
    socket: zmq::Socket,
) -> Result<Connection, Error> {
    let endpoint = format!("{}://{}:{}", config.transport, config.ip, port);
    socket.bind(&endpoint)?;
    Ok(Connection::new(socket, &config.key)?)
}

/// See [Kernel info documentation](https://jupyter-client.readthedocs.io/en/stable/messaging.html#kernel-info)
fn kernel_info() -> JsonValue {
    object!{
        "protocol_version" => "5.3",
        "implementation" => env!("CARGO_PKG_NAME"),
        "implementation_version" => env!("CARGO_PKG_VERSION"),
        "language_info" => object!{
            "name" => "Rust",
            "version" => "",
            "mimetype" => "text/rust",
            "file_extension" => ".rs",
            // Pygments lexer, for highlighting Only needed if it differs from the 'name' field.
            // see http://pygments.org/docs/lexers/#lexers-for-the-rust-language
            "pygment_lexer" => "rust",
            // Codemirror mode, for for highlighting in the notebook. Only needed if it differs from the 'name' field.
            // codemirror use text/x-rustsrc as mimetypes
            // see https://codemirror.net/mode/rust/
            "codemirror_mode" => "rust",
        },
        "banner" => format!("EvCxR {} - Evaluation Context for Rust", env!("CARGO_PKG_VERSION")),
        "help_links" => array![
            object!{"text" => "Rust std docs",
                    "url" => "https://doc.rust-lang.org/stable/std/"}
        ],
        "status" => "ok"
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate evcxr;
#[macro_use]
extern crate json;
#[macro_use]
extern crate failure;
extern crate colored;
extern crate hex;
extern crate hmac;
extern crate dirs;
extern crate sha2;
extern crate uuid;
extern crate zmq;

mod connection;
mod control_file;
mod core;
mod install;
mod jupyter_message;

use failure::Error;

fn run(control_file_name: &str) -> Result<(), Error> {
    let config = control_file::Control::parse_file(&control_file_name)?;
    let server = core::Server::start(&config)?;
    server.wait_for_shutdown();
    Ok(())
}

fn main() -> Result<(), Error> {
    evcxr::runtime_hook();
    let mut args = std::env::args();
    let bin = args.next().unwrap();
    if let Some(arg) = args.next() {
        match arg.as_str() {
            "--control_file" => {
                return run(&args
                    .next()
                    .ok_or_else(|| format_err!("Missing control file"))?);
            }
            "--install" => return install::install(),
            "--uninstall" => return install::uninstall(),
            "--help" => {}
            x => bail!("Unrecognised option {}", x),
        }
    }
    println!("To install, run:\n  {} --install", bin);
    println!("To uninstall, run:\n  {} --uninstall", bin);
    Ok(())
}
<commit_msg>Cargo fmt<commit_after>// Copyright 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

extern crate evcxr;
#[macro_use]
extern crate json;
#[macro_use]
extern crate failure;
extern crate colored;
extern crate dirs;
extern crate hex;
extern crate hmac;
extern crate sha2;
extern crate uuid;
extern crate zmq;

mod connection;
mod control_file;
mod core;
mod install;
mod jupyter_message;

use failure::Error;

fn run(control_file_name: &str) -> Result<(), Error> {
    let config = control_file::Control::parse_file(&control_file_name)?;
    let server = core::Server::start(&config)?;
    server.wait_for_shutdown();
    Ok(())
}

fn main() -> Result<(), Error> {
    evcxr::runtime_hook();
    let mut args = std::env::args();
    let bin = args.next().unwrap();
    if let Some(arg) = args.next() {
        match arg.as_str() {
            "--control_file" => {
                return run(&args
                    .next()
                    .ok_or_else(|| format_err!("Missing control file"))?);
            }
            "--install" => return install::install(),
            "--uninstall" => return install::uninstall(),
            "--help" => {}
            x => bail!("Unrecognised option {}", x),
        }
    }
    println!("To install, run:\n  {} --install", bin);
    println!("To uninstall, run:\n  {} --uninstall", bin);
    Ok(())
}
<|endoftext|>


<commit_before>use actix_web::{self, AsyncResponder, FromRequest, HttpMessage, HttpRequest, HttpResponse, Query};
use futures::{Future, IntoFuture};
use serde::de::DeserializeOwned;
use serde::Serialize;

use error;
use service::{ServiceApiBackend, ServiceApiContext, ServiceApiContextMut};
use NamedFn;

pub type RawHandler = Fn(HttpRequest<ServiceApiContextMut>)
    -> Box<Future<Item = HttpResponse, Error = actix_web::Error>>;

pub struct RequestHandler {
    pub name: &'static str,
    pub method: actix_web::http::Method,
    pub inner: Box<RawHandler>,
}

impl<Q, I, F> From<NamedFn<ServiceApiContext, Q, I, Result<I, error::Error>, F>> for RequestHandler
where
    F: for<'r> Fn(&'r ServiceApiContext, Q) -> Result<I, error::Error> + 'static,
    Q: DeserializeOwned + 'static,
    I: Serialize + 'static,
{
        fn from(f: NamedFn<ServiceApiContext, Q, I, Result<I, error::Error>, F>) -> Self {
            let handler = f.inner.f;
            let index = move |request: HttpRequest<ServiceApiContextMut>| -> Box<Future<Item=HttpResponse, Error=actix_web::Error>> {
                    let to_response = |request: HttpRequest<ServiceApiContextMut>| -> Result<HttpResponse, actix_web::Error> {
                        let context = request.state();
                        let query: Query<Q> = Query::from_request(&request, &())?;
                        let value = handler(context, query.into_inner())?;
                        Ok(HttpResponse::Ok().json(value))
                    };

                    Box::new(to_response(request).into_future())
                };

            RequestHandler {
                name: f.name,
                method: actix_web::http::Method::GET,
                inner: Box::new(index) as Box<RawHandler>,
            }
        }
}

impl<Q, I, F> From<NamedFn<ServiceApiContextMut, Q, I, Result<I, error::Error>, F>>
    for RequestHandler
where
    F: for<'r> Fn(&'r ServiceApiContextMut, Q) -> Result<I, error::Error> + 'static + Clone,
    Q: DeserializeOwned + 'static,
    I: Serialize + 'static,
{
    fn from(f: NamedFn<ServiceApiContextMut, Q, I, Result<I, error::Error>, F>) -> Self {
        let handler = f.inner.f;
        let index = move |request: HttpRequest<ServiceApiContextMut>| -> Box<Future<Item=HttpResponse, Error=actix_web::Error>> {
            let handler = handler.clone();
            let context = request.state().clone();
            request.json().from_err().and_then(move |query: Q| {
                let value = handler(&context, query)?;
                Ok(HttpResponse::Ok().json(value))
            }).responder()
        };

        RequestHandler {
            name: f.name,
            method: actix_web::http::Method::POST,
            inner: Box::new(index) as Box<RawHandler>,
        }
    }
}

#[derive(Default)]
pub struct BackendBuilder {
    handlers: Vec<RequestHandler>,
}

impl ServiceApiBackend for BackendBuilder {
    type Handler = RequestHandler;

    fn raw_handler(&mut self, handler: Self::Handler) -> &mut Self {
        self.handlers.push(handler);
        self
    }
}

impl BackendBuilder {
    pub fn new() -> BackendBuilder {
        BackendBuilder::default()
    }

    pub fn finish(self) -> Vec<RequestHandler> {
        self.handlers
    }
}
<commit_msg>Format code<commit_after>use actix_web::{self, AsyncResponder, FromRequest, HttpMessage, HttpRequest, HttpResponse, Query};
use futures::{Future, IntoFuture};
use serde::de::DeserializeOwned;
use serde::Serialize;

use error;
use service::{ServiceApiBackend, ServiceApiContext, ServiceApiContextMut};
use NamedFn;

pub type RawHandler = Fn(HttpRequest<ServiceApiContextMut>)
    -> Box<Future<Item = HttpResponse, Error = actix_web::Error>>;

pub struct RequestHandler {
    pub name: &'static str,
    pub method: actix_web::http::Method,
    pub inner: Box<RawHandler>,
}

impl<Q, I, F> From<NamedFn<ServiceApiContext, Q, I, Result<I, error::Error>, F>> for RequestHandler
where
    F: for<'r> Fn(&'r ServiceApiContext, Q) -> Result<I, error::Error> + 'static,
    Q: DeserializeOwned + 'static,
    I: Serialize + 'static,
{
    fn from(f: NamedFn<ServiceApiContext, Q, I, Result<I, error::Error>, F>) -> Self {
        let handler = f.inner.f;
        let index = move |request: HttpRequest<ServiceApiContextMut>|
         -> Box<Future<Item=HttpResponse, Error=actix_web::Error>> {
            let to_response = |request: HttpRequest<ServiceApiContextMut>|
             -> Result<HttpResponse, actix_web::Error> {
                let context = request.state();
                let query: Query<Q> = Query::from_request(&request, &())?;
                let value = handler(context, query.into_inner())?;
                Ok(HttpResponse::Ok().json(value))
            };

            Box::new(to_response(request).into_future())
        };

        RequestHandler {
            name: f.name,
            method: actix_web::http::Method::GET,
            inner: Box::new(index) as Box<RawHandler>,
        }
    }
}

impl<Q, I, F> From<NamedFn<ServiceApiContextMut, Q, I, Result<I, error::Error>, F>>
    for RequestHandler
where
    F: for<'r> Fn(&'r ServiceApiContextMut, Q) -> Result<I, error::Error> + 'static + Clone,
    Q: DeserializeOwned + 'static,
    I: Serialize + 'static,
{
    fn from(f: NamedFn<ServiceApiContextMut, Q, I, Result<I, error::Error>, F>) -> Self {
        let handler = f.inner.f;
        let index = move |request: HttpRequest<ServiceApiContextMut>|
         -> Box<Future<Item=HttpResponse, Error=actix_web::Error>> {
            let handler = handler.clone();
            let context = request.state().clone();
            request.json().from_err().and_then(move |query: Q| {
                let value = handler(&context, query)?;
                Ok(HttpResponse::Ok().json(value))
            }).responder()
        };

        RequestHandler {
            name: f.name,
            method: actix_web::http::Method::POST,
            inner: Box::new(index) as Box<RawHandler>,
        }
    }
}

#[derive(Default)]
pub struct BackendBuilder {
    handlers: Vec<RequestHandler>,
}

impl ServiceApiBackend for BackendBuilder {
    type Handler = RequestHandler;

    fn raw_handler(&mut self, handler: Self::Handler) -> &mut Self {
        self.handlers.push(handler);
        self
    }
}

impl BackendBuilder {
    pub fn new() -> BackendBuilder {
        BackendBuilder::default()
    }

    pub fn finish(self) -> Vec<RequestHandler> {
        self.handlers
    }
}
<|endoftext|>


<commit_before>//! Various APRS data types
//!
//! Data is broken down into objects depending on its purpose. See each struct definition for its
//! description.

use constants;
use functions;

pub struct Frame {
    pub source: Callsign,
    pub destination: Callsign,
    pub path: Vec<Callsign>,
    pub info: InformationField,
}

impl Frame {
    pub fn new() -> Frame {
        Frame {
            source: Callsign::new(),
            destination: Callsign::new(),
            path: Vec::new(),
            info: InformationField::new()
        }
    }
}

impl Frame {
    pub fn set_source(&mut self, source: &[u8]) {
        self.source = functions::parse_callsign(source);
    }
    pub fn set_destination(&mut self, dest: &[u8]) {
        self.destination = functions::parse_callsign(dest);
    }
    pub fn set_path(&mut self, path: Vec<Vec<u8>>) {
        for pth in path {
            let byts: &[u8] = pth.as_slice();
            self.path.push(functions::parse_callsign(byts));
        }
    }
    pub fn set_info(&mut self, info: &[u8]) {
        self.info = functions::parse_info_field(info);
    }
    pub fn encode_ax25(&self) -> Vec<u8> {
        // TODO: find a way to return raw bytes
        let mut encoded_frame: Vec<u8> = Vec::new();
        encoded_frame.push(constants::AX25_FLAG);
        encoded_frame.extend(self.destination.encode_ax25());
        encoded_frame.extend(self.source.encode_ax25());
        for path_call in self.path.iter() {
            encoded_frame.extend(path_call.encode_ax25());
        }
        encoded_frame.extend(self.info.data.as_slice());
        encoded_frame
    }
}

pub struct PositionFrame;

pub struct Callsign {
    pub callsign: String,
    pub ssid: u8,
    pub digi: bool,
}

impl Callsign {
    pub fn new() -> Callsign {
        Callsign {
            callsign: String::new(),
            ssid: 0,
            digi: false,
        }
    }
}

impl Callsign {
    pub fn set_callsign(&mut self, callsign: String) {
        self.callsign = callsign;
        // self.callsign = String::from_utf8(callsign.to_vec()).unwrap();
    }
    pub fn set_ssid(&mut self, ssid: u8) {
        self.ssid = ssid;
    }
    pub fn set_digi(&mut self, digi: bool) {
        self.digi = digi;
    }
    pub fn encode_ax25(&self) -> Vec<u8> {
        // TODO: find a way to return raw bytes
        let mut encoded_callsign: Vec<u8> = Vec::new();
        let mut encoded_ssid = (self.ssid << 1) | 0x60;
        let mut _callsign: String = String::new();

        if self.digi {
            encoded_ssid = encoded_ssid | 0x80;
        }
        for chr in self.callsign.chars() {
            _callsign.push(chr);
        }
        while _callsign.len() < 6 {
            _callsign.push(' ');
        }
        for byt in _callsign.bytes() {
            encoded_callsign.push(byt << 1);
        }
        encoded_callsign.push(encoded_ssid);

        encoded_callsign
    }
}

pub struct InformationField {
    pub data: Vec<u8>,
    pub data_type: String,
    pub safe: bool,
}

impl InformationField {
    pub fn new() -> InformationField {
        InformationField {
            data: Vec::new(),
            data_type: String::new(),
            safe: false
        }
    }
}

impl InformationField {
    pub fn set_data(&mut self, raw_data: &[u8]) {
        self.data = raw_data.to_vec();
    }
    pub fn set_data_type(&mut self, data_type: &str) {
        self.data_type = data_type.to_string();
    }
    pub fn set_safe(&mut self, safe: bool) {
        self.safe = safe;
    }
}

pub struct APRS;

pub struct TCP;

pub struct UDP;

pub struct HTTP;
<commit_msg>PositionFrame<commit_after>//! Various APRS data types
//!
//! Data is broken down into objects depending on its purpose. See each struct definition for its
//! description.

use constants;
use functions;
use geo_util;

pub struct Frame {
    pub source: Callsign,
    pub destination: Callsign,
    pub path: Vec<Callsign>,
    pub info: InformationField,
}

impl Frame {
    pub fn new() -> Frame {
        Frame {
            source: Callsign::new(),
            destination: Callsign::new(),
            path: Vec::new(),
            info: InformationField::new()
        }
    }
}

impl Frame {
    pub fn set_source(&mut self, source: &[u8]) {
        self.source = functions::parse_callsign(source);
    }
    pub fn set_destination(&mut self, dest: &[u8]) {
        self.destination = functions::parse_callsign(dest);
    }
    pub fn set_path(&mut self, path: Vec<Vec<u8>>) {
        for pth in path {
            let byts: &[u8] = pth.as_slice();
            self.path.push(functions::parse_callsign(byts));
        }
    }
    pub fn set_info(&mut self, info: &[u8]) {
        self.info = functions::parse_info_field(info);
    }
    pub fn encode_ax25(&self) -> Vec<u8> {
        // TODO: find a way to return raw bytes
        let mut encoded_frame: Vec<u8> = Vec::new();
        encoded_frame.push(constants::AX25_FLAG);
        encoded_frame.extend(self.destination.encode_ax25());
        encoded_frame.extend(self.source.encode_ax25());
        for path_call in self.path.iter() {
            encoded_frame.extend(path_call.encode_ax25());
        }
        encoded_frame.extend(self.info.data.as_slice());
        encoded_frame
    }
}

pub struct PositionFrame {
    pub source: Callsign,
    pub destination: Callsign,
    pub path: Vec<Callsign>,
    pub info: InformationField,
    pub comment: Vec<u8>,
    pub table: Vec<u8>,
    pub symbol: u8,
    pub lat: f32,
    pub lng: f32,
    pub ambiguity: usize
}

impl PositionFrame {
    pub fn new() -> PositionFrame {
        PositionFrame {
            source: Callsign::new(),
            destination: Callsign::new(),
            path: Vec::new(),
            info: InformationField::new(),
            comment: Vec::new(),
            table: Vec::new(),
            symbol: 0,
            lat: 0.0,
            lng: 0.0,
            ambiguity: 0
        }
    }
}

impl PositionFrame {
    pub fn set_source(&mut self, source: &[u8]) {
        self.source = functions::parse_callsign(source);
    }
    pub fn set_destination(&mut self, dest: &[u8]) {
        self.destination = functions::parse_callsign(dest);
    }
    pub fn set_path(&mut self, path: Vec<Vec<u8>>) {
        for pth in path {
            let byts: &[u8] = pth.as_slice();
            self.path.push(functions::parse_callsign(byts));
        }
    }
    pub fn create_info_field(&self) -> Vec<u8> {
        let lat = geo_util::dec2dm_lat(self.lat);
        let lat_enc = geo_util::ambiguate(&lat, self.ambiguity);
        let lng = geo_util::dec2dm_lng(self.lng);
        let lng_enc = geo_util::ambiguate(&lng, self.ambiguity);

        let mut frame: Vec<u8> = Vec::new();
        frame.push(b'=');
        frame.extend(lat_enc.as_bytes());
        frame.extend(&self.table);
        frame.extend(lng_enc.as_bytes());
        frame.push(self.symbol);
        frame.extend(&self.comment);

        frame
    }
}

pub struct Callsign {
    pub callsign: String,
    pub ssid: u8,
    pub digi: bool,
}

impl Callsign {
    pub fn new() -> Callsign {
        Callsign {
            callsign: String::new(),
            ssid: 0,
            digi: false,
        }
    }
}

impl Callsign {
    pub fn set_callsign(&mut self, callsign: String) {
        self.callsign = callsign;
        // self.callsign = String::from_utf8(callsign.to_vec()).unwrap();
    }
    pub fn set_ssid(&mut self, ssid: u8) {
        self.ssid = ssid;
    }
    pub fn set_digi(&mut self, digi: bool) {
        self.digi = digi;
    }
    pub fn encode_ax25(&self) -> Vec<u8> {
        // TODO: find a way to return raw bytes
        let mut encoded_callsign: Vec<u8> = Vec::new();
        let mut encoded_ssid = (self.ssid << 1) | 0x60;
        let mut _callsign: String = String::new();

        if self.digi {
            encoded_ssid = encoded_ssid | 0x80;
        }
        for chr in self.callsign.chars() {
            _callsign.push(chr);
        }
        while _callsign.len() < 6 {
            _callsign.push(' ');
        }
        for byt in _callsign.bytes() {
            encoded_callsign.push(byt << 1);
        }
        encoded_callsign.push(encoded_ssid);

        encoded_callsign
    }
}

pub struct InformationField {
    pub data: Vec<u8>,
    pub data_type: String,
    pub safe: bool,
}

impl InformationField {
    pub fn new() -> InformationField {
        InformationField {
            data: Vec::new(),
            data_type: String::new(),
            safe: false
        }
    }
}

impl InformationField {
    pub fn set_data(&mut self, raw_data: &[u8]) {
        self.data = raw_data.to_vec();
    }
    pub fn set_data_type(&mut self, data_type: &str) {
        self.data_type = data_type.to_string();
    }
    pub fn set_safe(&mut self, safe: bool) {
        self.safe = safe;
    }
}

pub struct APRS;

pub struct TCP;

pub struct UDP;

pub struct HTTP;
<|endoftext|>


<commit_before>//! Various APRS data types
//!
//! Data is broken down into objects depending on its purpose. See each struct definition for its
//! description.

use constants;
use functions;
use geo_util;

pub struct Frame {
    pub source: Callsign,
    pub destination: Callsign,
    pub path: Vec<Callsign>,
    pub info: InformationField,
}

impl Frame {
    pub fn new() -> Frame {
        Frame {
            source: Callsign::new(),
            destination: Callsign::new(),
            path: Vec::new(),
            info: InformationField::new()
        }
    }
}

impl Frame {
    pub fn set_source(&mut self, source: &[u8]) {
        self.source = functions::parse_callsign(source);
    }
    pub fn set_destination(&mut self, dest: &[u8]) {
        self.destination = functions::parse_callsign(dest);
    }
    pub fn set_path(&mut self, path: Vec<Vec<u8>>) {
        for pth in path {
            let byts: &[u8] = pth.as_slice();
            self.path.push(functions::parse_callsign(byts));
        }
    }
    pub fn set_info(&mut self, info: &[u8]) {
        self.info = functions::parse_info_field(info);
    }
    pub fn encode_ax25(&self) -> Vec<u8> {
        // TODO: find a way to return raw bytes
        let mut encoded_frame: Vec<u8> = Vec::new();
        encoded_frame.push(constants::AX25_FLAG);
        encoded_frame.extend(self.destination.encode_ax25());
        encoded_frame.extend(self.source.encode_ax25());
        for path_call in self.path.iter() {
            encoded_frame.extend(path_call.encode_ax25());
        }
        encoded_frame.extend(self.info.data.as_slice());
        encoded_frame
    }
}

pub struct PositionFrame {
    pub source: Callsign,
    pub destination: Callsign,
    pub path: Vec<Callsign>,
    pub info: InformationField,
    pub comment: Vec<u8>,
    pub table: Vec<u8>,
    pub symbol: u8,
    pub lat: f32,
    pub lng: f32,
    pub ambiguity: usize
}

impl PositionFrame {
    pub fn new() -> PositionFrame {
        PositionFrame {
            source: Callsign::new(),
            destination: Callsign::new(),
            path: Vec::new(),
            info: InformationField::new(),
            comment: Vec::new(),
            table: Vec::new(),
            symbol: 0,
            lat: 0.0,
            lng: 0.0,
            ambiguity: 0
        }
    }
}

impl PositionFrame {
    pub fn set_source(&mut self, source: &[u8]) {
        self.source = functions::parse_callsign(source);
    }
    pub fn set_destination(&mut self, dest: &[u8]) {
        self.destination = functions::parse_callsign(dest);
    }
    pub fn set_path(&mut self, path: Vec<Vec<u8>>) {
        for pth in path {
            let byts: &[u8] = pth.as_slice();
            self.path.push(functions::parse_callsign(byts));
        }
    }
    pub fn update_info(&mut self) {
        self.info = functions::parse_info_field(&self.create_info_field());
    }
    pub fn create_info_field(&self) -> Vec<u8> {
        let lat = geo_util::dec2dm_lat(self.lat);
        let lat_enc = geo_util::ambiguate(&lat, self.ambiguity);
        let lng = geo_util::dec2dm_lng(self.lng);
        let lng_enc = geo_util::ambiguate(&lng, self.ambiguity);

        let mut frame: Vec<u8> = Vec::new();
        frame.push(b'=');
        frame.extend(lat_enc.as_bytes());
        frame.extend(&self.table);
        frame.extend(lng_enc.as_bytes());
        frame.push(self.symbol);
        frame.extend(&self.comment);

        frame
    }
}

pub struct Callsign {
    pub callsign: String,
    pub ssid: u8,
    pub digi: bool,
}

impl Callsign {
    pub fn new() -> Callsign {
        Callsign {
            callsign: String::new(),
            ssid: 0,
            digi: false,
        }
    }
}

impl Callsign {
    pub fn set_callsign(&mut self, callsign: String) {
        self.callsign = callsign;
        // self.callsign = String::from_utf8(callsign.to_vec()).unwrap();
    }
    pub fn set_ssid(&mut self, ssid: u8) {
        self.ssid = ssid;
    }
    pub fn set_digi(&mut self, digi: bool) {
        self.digi = digi;
    }
    pub fn encode_ax25(&self) -> Vec<u8> {
        // TODO: find a way to return raw bytes
        let mut encoded_callsign: Vec<u8> = Vec::new();
        let mut encoded_ssid = (self.ssid << 1) | 0x60;
        let mut _callsign: String = String::new();

        if self.digi {
            encoded_ssid = encoded_ssid | 0x80;
        }
        for chr in self.callsign.chars() {
            _callsign.push(chr);
        }
        while _callsign.len() < 6 {
            _callsign.push(' ');
        }
        for byt in _callsign.bytes() {
            encoded_callsign.push(byt << 1);
        }
        encoded_callsign.push(encoded_ssid);

        encoded_callsign
    }
}

pub struct InformationField {
    pub data: Vec<u8>,
    pub data_type: String,
    pub safe: bool,
}

impl InformationField {
    pub fn new() -> InformationField {
        InformationField {
            data: Vec::new(),
            data_type: String::new(),
            safe: false
        }
    }
}

impl InformationField {
    pub fn set_data(&mut self, raw_data: &[u8]) {
        self.data = raw_data.to_vec();
    }
    pub fn set_data_type(&mut self, data_type: &str) {
        self.data_type = data_type.to_string();
    }
    pub fn set_safe(&mut self, safe: bool) {
        self.safe = safe;
    }
}

pub struct APRS;

pub struct TCP;

pub struct UDP;

pub struct HTTP;
<commit_msg>format for readability<commit_after>//! Various APRS data types
//!
//! Data is broken down into objects depending on its purpose. See each struct definition for its
//! description.

use constants;
use functions;
use geo_util;

pub struct Frame {
    pub source: Callsign,
    pub destination: Callsign,
    pub path: Vec<Callsign>,
    pub info: InformationField,
}

impl Frame {
    pub fn new() -> Frame {
        Frame {
            source: Callsign::new(),
            destination: Callsign::new(),
            path: Vec::new(),
            info: InformationField::new()
        }
    }
}

impl Frame {
    pub fn set_source(&mut self, source: &[u8]) {
        self.source = functions::parse_callsign(source);
    }
    pub fn set_destination(&mut self, dest: &[u8]) {
        self.destination = functions::parse_callsign(dest);
    }
    pub fn set_path(&mut self, path: Vec<Vec<u8>>) {
        for pth in path {
            let byts: &[u8] = pth.as_slice();
            self.path.push(functions::parse_callsign(byts));
        }
    }
    pub fn set_info(&mut self, info: &[u8]) {
        self.info = functions::parse_info_field(info);
    }
    pub fn encode_ax25(&self) -> Vec<u8> {
        // TODO: find a way to return raw bytes
        let mut encoded_frame: Vec<u8> = Vec::new();
        encoded_frame.push(constants::AX25_FLAG);
        encoded_frame.extend(self.destination.encode_ax25());
        encoded_frame.extend(self.source.encode_ax25());
        for path_call in self.path.iter() {
            encoded_frame.extend(path_call.encode_ax25());
        }
        encoded_frame.extend(self.info.data.as_slice());
        encoded_frame
    }
}

pub struct PositionFrame {
    pub source: Callsign,
    pub destination: Callsign,
    pub path: Vec<Callsign>,
    pub info: InformationField,
    pub comment: Vec<u8>,
    pub table: Vec<u8>,
    pub symbol: u8,
    pub lat: f32,
    pub lng: f32,
    pub ambiguity: usize
}

impl PositionFrame {
    pub fn new() -> PositionFrame {
        PositionFrame {
            source: Callsign::new(),
            destination: Callsign::new(),
            path: Vec::new(),
            info: InformationField::new(),
            comment: Vec::new(),
            table: Vec::new(),
            symbol: 0,
            lat: 0.0,
            lng: 0.0,
            ambiguity: 0
        }
    }
}

impl PositionFrame {
    pub fn set_source(&mut self, source: &[u8]) {
        self.source = functions::parse_callsign(source);
    }
    pub fn set_destination(&mut self, dest: &[u8]) {
        self.destination = functions::parse_callsign(dest);
    }
    pub fn set_path(&mut self, path: Vec<Vec<u8>>) {
        for pth in path {
            let byts: &[u8] = pth.as_slice();
            self.path.push(functions::parse_callsign(byts));
        }
    }
    pub fn update_info(&mut self) {
        self.info = functions::parse_info_field(&self.create_info_field());
    }
    pub fn create_info_field(&self) -> Vec<u8> {
        let lat     = geo_util::dec2dm_lat(self.lat);
        let lat_enc = geo_util::ambiguate(&lat, self.ambiguity);
        let lng     = geo_util::dec2dm_lng(self.lng);
        let lng_enc = geo_util::ambiguate(&lng, self.ambiguity);

        let mut frame: Vec<u8> = Vec::new();
        frame.push(b'=');
        frame.extend(lat_enc.as_bytes());
        frame.extend(&self.table);
        frame.extend(lng_enc.as_bytes());
        frame.push(self.symbol);
        frame.extend(&self.comment);

        frame
    }
}

pub struct Callsign {
    pub callsign: String,
    pub ssid: u8,
    pub digi: bool,
}

impl Callsign {
    pub fn new() -> Callsign {
        Callsign {
            callsign: String::new(),
            ssid: 0,
            digi: false,
        }
    }
}

impl Callsign {
    pub fn set_callsign(&mut self, callsign: String) {
        self.callsign = callsign;
        // self.callsign = String::from_utf8(callsign.to_vec()).unwrap();
    }
    pub fn set_ssid(&mut self, ssid: u8) {
        self.ssid = ssid;
    }
    pub fn set_digi(&mut self, digi: bool) {
        self.digi = digi;
    }
    pub fn encode_ax25(&self) -> Vec<u8> {
        // TODO: find a way to return raw bytes
        let mut encoded_callsign: Vec<u8> = Vec::new();
        let mut encoded_ssid = (self.ssid << 1) | 0x60;
        let mut _callsign: String = String::new();

        if self.digi {
            encoded_ssid = encoded_ssid | 0x80;
        }
        for chr in self.callsign.chars() {
            _callsign.push(chr);
        }
        while _callsign.len() < 6 {
            _callsign.push(' ');
        }
        for byt in _callsign.bytes() {
            encoded_callsign.push(byt << 1);
        }
        encoded_callsign.push(encoded_ssid);

        encoded_callsign
    }
}

pub struct InformationField {
    pub data: Vec<u8>,
    pub data_type: String,
    pub safe: bool,
}

impl InformationField {
    pub fn new() -> InformationField {
        InformationField {
            data: Vec::new(),
            data_type: String::new(),
            safe: false
        }
    }
}

impl InformationField {
    pub fn set_data(&mut self, raw_data: &[u8]) {
        self.data = raw_data.to_vec();
    }
    pub fn set_data_type(&mut self, data_type: &str) {
        self.data_type = data_type.to_string();
    }
    pub fn set_safe(&mut self, safe: bool) {
        self.safe = safe;
    }
}

pub struct APRS;

pub struct TCP;

pub struct UDP;

pub struct HTTP;
<|endoftext|>


<commit_before>// Copyright (c) 2016-2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::thread;
use std::ops::{Deref, DerefMut, Range};
use std::time::Duration;

use time::SteadyTime;

use common;
use habitat_butterfly::server::Server;
use habitat_butterfly::member::{Member, Health};
use habitat_butterfly::server::timing::Timing;
use habitat_butterfly::rumor::service::Service;
use habitat_butterfly::rumor::service_config::ServiceConfig;
use habitat_butterfly::rumor::service_file::ServiceFile;
use habitat_butterfly::message::swim::Election_Status;
use habitat_core::service::ServiceGroup;
use habitat_core::crypto::keys::sym_key::SymKey;

#[derive(Debug)]
pub struct SwimNet {
    pub members: Vec<Server>,
}

impl Deref for SwimNet {
    type Target = Vec<Server>;

    fn deref(&self) -> &Vec<Server> {
        &self.members
    }
}

impl DerefMut for SwimNet {
    fn deref_mut(&mut self) -> &mut Vec<Server> {
        &mut self.members
    }
}

impl SwimNet {
    pub fn new(count: usize) -> SwimNet {
        let mut members = Vec::with_capacity(count);
        for x in 0..count {
            members.push(common::start_server(&format!("{}", x), None));
        }
        SwimNet { members: members }
    }

    pub fn new_ring_encryption(count: usize, ring_key: Option<SymKey>) -> SwimNet {
        let mut members = Vec::with_capacity(count);
        for x in 0..count {
            let rk = ring_key.clone();
            members.push(common::start_server(&format!("{}", x), rk));
        }
        SwimNet { members: members }
    }

    pub fn connect(&mut self, from_entry: usize, to_entry: usize) {
        let to = common::member_from_server(&self.members[to_entry]);
        trace_it!(TEST: &self.members[from_entry], format!("Connected {} {}", self.members[to_entry].name(), self.members[to_entry].member_id()));
        self.members[from_entry].insert_member(to, Health::Alive);
    }

    // Fully mesh the network
    pub fn mesh(&mut self) {
        trace_it!(TEST_NET: self, "Mesh");
        for pos in 0..self.members.len() {
            let mut to_mesh: Vec<Member> = Vec::new();
            for x_pos in 0..self.members.len() {
                if pos == x_pos {
                    continue;
                }
                let server_b = self.members.get(x_pos).unwrap();
                to_mesh.push(common::member_from_server(server_b))
            }
            let server_a = self.members.get(pos).unwrap();
            for server_b in to_mesh.into_iter() {
                server_a.insert_member(server_b, Health::Alive);
            }
        }
    }

    pub fn blacklist(&self, from_entry: usize, to_entry: usize) {
        let from = self.members.get(from_entry).expect(
            "Asked for a network member who is out of bounds",
        );
        let to = self.members.get(to_entry).expect(
            "Asked for a network member who is out of bounds",
        );
        trace_it!(TEST: &self.members[from_entry], format!("Blacklisted {} {}", self.members[to_entry].name(), self.members[to_entry].member_id()));
        from.add_to_blacklist(String::from(
            to.member.read().expect("Member lock is poisoned").get_id(),
        ));
    }

    pub fn unblacklist(&self, from_entry: usize, to_entry: usize) {
        let from = self.members.get(from_entry).expect(
            "Asked for a network member who is out of bounds",
        );
        let to = self.members.get(to_entry).expect(
            "Asked for a network member who is out of bounds",
        );
        trace_it!(TEST: &self.members[from_entry], format!("Un-Blacklisted {} {}", self.members[to_entry].name(), self.members[to_entry].member_id()));
        from.remove_from_blacklist(to.member_id());
    }

    pub fn health_of(&self, from_entry: usize, to_entry: usize) -> Option<Health> {
        let from = self.members.get(from_entry).expect(
            "Asked for a network member who is out of bounds",
        );

        let to = self.members.get(to_entry).expect(
            "Asked for a network member who is out of bounds",
        );
        let to_member = to.member.read().expect("Member lock is poisoned");
        from.member_list.health_of(&to_member)
    }

    pub fn network_health_of(&self, to_check: usize) -> Vec<Option<Health>> {
        let mut health_summary = Vec::with_capacity(self.members.len() - 1);
        let length = self.members.len();
        for x in 0..length {
            if x == to_check {
                continue;
            }
            health_summary.push(self.health_of(x, to_check));
        }
        health_summary
    }

    pub fn max_rounds(&self) -> isize {
        7
    }

    pub fn max_gossip_rounds(&self) -> isize {
        5
    }

    pub fn rounds(&self) -> Vec<isize> {
        self.members.iter().map(|m| m.swim_rounds()).collect()
    }

    pub fn rounds_in(&self, count: isize) -> Vec<isize> {
        self.rounds().iter().map(|r| r + count).collect()
    }

    pub fn gossip_rounds(&self) -> Vec<isize> {
        self.members.iter().map(|m| m.gossip_rounds()).collect()
    }

    pub fn gossip_rounds_in(&self, count: isize) -> Vec<isize> {
        self.gossip_rounds().iter().map(|r| r + count).collect()
    }

    pub fn check_rounds(&self, rounds_in: &Vec<isize>) -> bool {
        let mut finished = Vec::with_capacity(rounds_in.len());
        for (i, round) in rounds_in.into_iter().enumerate() {
            if self.members[i].paused() {
                finished.push(true);
            } else {
                if self.members[i].swim_rounds() > *round {
                    finished.push(true);
                } else {
                    finished.push(false);
                }
            }
        }
        if finished.iter().all(|m| m == &true) {
            return true;
        } else {
            return false;
        }
    }

    pub fn wait_for_rounds(&self, rounds: isize) {
        let rounds_in = self.rounds_in(rounds);
        loop {
            if self.check_rounds(&rounds_in) {
                return;
            }
            thread::sleep(Duration::from_millis(500));
        }
    }

    pub fn check_gossip_rounds(&self, rounds_in: &Vec<isize>) -> bool {
        let mut finished = Vec::with_capacity(rounds_in.len());
        for (i, round) in rounds_in.into_iter().enumerate() {
            if self.members[i].paused() {
                finished.push(true);
            } else {
                if self.members[i].gossip_rounds() > *round {
                    finished.push(true);
                } else {
                    finished.push(false);
                }
            }
        }
        if finished.iter().all(|m| m == &true) {
            return true;
        } else {
            return false;
        }
    }

    #[allow(dead_code)]
    pub fn wait_for_gossip_rounds(&self, rounds: isize) {
        let rounds_in = self.gossip_rounds_in(rounds);
        loop {
            if self.check_gossip_rounds(&rounds_in) {
                return;
            }
            thread::sleep(Duration::from_millis(500));
        }
    }

    pub fn wait_for_election_status(
        &self,
        e_num: usize,
        key: &str,
        status: Election_Status,
    ) -> bool {
        let rounds_in = self.gossip_rounds_in(self.max_gossip_rounds());
        loop {
            let mut result = false;
            let server = self.members.get(e_num).expect(
                "Asked for a network member who is out of bounds",
            );
            server.election_store.with_rumor(
                key,
                "election",
                |e| if e.is_some() &&
                    e.unwrap().get_status() == status
                {
                    result = true;
                },
            );
            if result {
                return true;
            }
            if self.check_gossip_rounds(&rounds_in) {
                println!(
                    "Failed election check for status {:?}: {:#?}",
                    status,
                    self.members[e_num].election_store
                );
                return false;
            }
        }
    }

    pub fn wait_for_equal_election(&self, left: usize, right: usize, key: &str) -> bool {
        let rounds_in = self.gossip_rounds_in(self.max_gossip_rounds());
        loop {
            let mut result = false;

            let left_server = self.members.get(left).expect(
                "Asked for a network member who is out of bounds",
            );
            let right_server = self.members.get(right).expect(
                "Asked for a network member who is out of bounds",
            );

            left_server.election_store.with_rumor(key, "election", |l| {
                right_server.election_store.with_rumor(
                    key,
                    "election",
                    |r| {
                        result = l.is_some() && r.is_some() && l.unwrap() == r.unwrap();
                    },
                );
            });
            if result {
                return true;
            }
            if self.check_gossip_rounds(&rounds_in) {
                println!("Failed election check for equality:\nL: {:#?}\n\nR: {:#?}",
                         self.members[left].election_store,
                         self.members[right].election_store,
                         );
                return false;
            }
        }
    }

    pub fn partition(&self, left_range: Range<usize>, right_range: Range<usize>) {
        let left: Vec<usize> = left_range.collect();
        let right: Vec<usize> = right_range.collect();
        for l in left.iter() {
            for r in right.iter() {
                println!("Partitioning {} from {}", *l, *r);
                if l == r {
                    continue;
                }
                self.blacklist(*l, *r);
                self.blacklist(*r, *l);
            }
        }
    }

    pub fn unpartition(&self, left_range: Range<usize>, right_range: Range<usize>) {
        let left: Vec<usize> = left_range.collect();
        let right: Vec<usize> = right_range.collect();
        for l in left.iter() {
            for r in right.iter() {
                println!("UnPartitioning {} from {}", *l, *r);
                self.unblacklist(*l, *r);
                self.unblacklist(*r, *l);
            }
        }
    }

    pub fn wait_for_health_of(&self, from_entry: usize, to_check: usize, health: Health) -> bool {
        let rounds_in = self.rounds_in(self.max_rounds());
        loop {
            if let Some(real_health) = self.health_of(from_entry, to_check) {
                if real_health == health {
                    trace_it!(TEST: &self.members[from_entry], format!("Health {} {} as {}", self.members[to_check].name(), self.members[to_check].member_id(), health));
                    return true;
                }
            }
            if self.check_rounds(&rounds_in) {
                trace_it!(TEST: &self.members[from_entry], format!("Health failed {} {} as {}", self.members[to_check].name(), self.members[to_check].member_id(), health));
                println!("MEMBERS: {:#?}", self.members);
                println!(
                    "Failed health check for\n***FROM***{:#?}\n***TO***\n{:#?}",
                    self.members[from_entry],
                    self.members[to_check]
                );
                return false;
            }
        }
    }

    pub fn wait_for_network_health_of(&self, to_check: usize, health: Health) -> bool {
        let rounds_in = self.rounds_in(self.max_rounds());
        loop {
            let network_health = self.network_health_of(to_check);
            if network_health.iter().all(|x| if let &Some(ref h) = x {
                *h == health
            } else {
                false
            })
            {
                trace_it!(
                    TEST_NET: self,
                    format!(
                        "Health {} {} as {}",
                        self.members[to_check].name(),
                        self.members[to_check].member_id(),
                        health
                    )
                );
                return true;
            } else if self.check_rounds(&rounds_in) {
                for (i, some_health) in network_health.iter().enumerate() {
                    match some_health {
                        &Some(ref health) => {
                            println!("{}: {:?}", i, health);
                            trace_it!(TEST: &self.members[i], format!("Health failed {} {} as {}", self.members[to_check].name(), self.members[to_check].member_id(), health));
                        }
                        &None => {}
                    }
                }
                // println!("Failed network health check dump: {:#?}", self);
                return false;
            }
        }
    }

    #[allow(dead_code)]
    pub fn wait_protocol_period(&self) {
        let timing = Timing::default();
        let next_period = timing.next_protocol_period();
        loop {
            if SteadyTime::now() <= next_period {
                thread::sleep(Duration::from_millis(100));
            } else {
                return;
            }
        }
    }

    pub fn add_service(&mut self, member: usize, service: &str) {
        let s = Service::new(
            self[member].member_id(),
            ServiceGroup::new(service, "prod", None),
            "localhost",
            "127.0.0.1",
            vec![4040, 4041, 4042],
        );
        self[member].insert_service(s);
    }

    pub fn add_service_config(&mut self, member: usize, service: &str, config: &str) {
        let config_bytes: Vec<u8> = Vec::from(config);
        let s = ServiceConfig::new(
            self[member].member_id(),
            ServiceGroup::new(service, "prod", None),
            config_bytes,
        );
        self[member].insert_service_config(s);
    }

    pub fn add_service_file(&mut self, member: usize, service: &str, filename: &str, body: &str) {
        let body_bytes: Vec<u8> = Vec::from(body);
        let s = ServiceFile::new(
            self[member].member_id(),
            ServiceGroup::new(service, "prod", None),
            filename,
            body_bytes,
        );
        self[member].insert_service_file(s);
    }

    pub fn add_election(&mut self, member: usize, service: &str) {
        self[member].start_election(ServiceGroup::new(service, "prod", None), suitability, 0);
    }
}

macro_rules! assert_health_of {
    ($network:expr, $to:expr, $health:expr) => {
        assert!($network.network_health_of($to).into_iter().all(|x| x == $health), "Member {} does not always have health {}", $to, $health)
    };
    ($network:expr, $from: expr, $to:expr, $health:expr) => {
        assert!($network.health_of($from, $to) == $health, "Member {} does not see {} as {}", $from, $to, $health)
    }
}

macro_rules! assert_wait_for_health_of {
    ($network:expr, [$from: expr, $to:expr], $health:expr) => {
        let left: Vec<usize> = $from.collect();
        let right: Vec<usize> = $to.collect();
        for l in left.iter() {
            for r in right.iter() {
                if l == r {
                    continue;
                }
                assert!($network.wait_for_health_of(*l, *r, $health), "Member {} does not see {} as {}", l, r, $health);
                assert!($network.wait_for_health_of(*r, *l, $health), "Member {} does not see {} as {}", r, l, $health);
            }
        }
    };
    ($network:expr, $to:expr, $health:expr) => {
        assert!($network.wait_for_network_health_of($to, $health), "Member {} does not always have health {}", $to, $health);
    };
    ($network:expr, $from: expr, $to:expr, $health:expr) => {
        assert!($network.wait_for_health_of($from, $to, $health), "Member {} does not see {} as {}", $from, $to, $health);
    };
}

macro_rules! assert_wait_for_election_status {
    ($network:expr, [$range:expr], $key:expr, $status: expr) => {
        for x in $range {
            assert!($network.wait_for_election_status(x, $key, $status));
        }
    };
    ($network:expr, $to:expr, $key:expr, $status: expr) => {
        assert!($network.wait_for_election_status($to, $key, $status));
    };
}

macro_rules! assert_wait_for_equal_election {
    ($network:expr, $left:expr, $right:expr, $key:expr) => {
        assert!($network.wait_for_equal_election($left, $right, $key));
    };
    ($network:expr, [$from: expr, $to:expr], $key:expr) => {
        let left: Vec<usize> = $from.collect();
        let right: Vec<usize> = $to.collect();
        for l in left.iter() {
            for r in right.iter() {
                if l == r {
                    continue;
                }
                assert!($network.wait_for_equal_election(*l, *r, $key), "Member {} is not equal to {}", l, r);
            }
        }
    };
}
<commit_msg>Drop a file with unused code<commit_after><|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A windowing implementation using GLUT.
///
/// GLUT is a very old and bare-bones toolkit. However, it has good cross-platform support, at
/// least on desktops. It is designed for testing Servo without the need of a UI.

use windowing::{ApplicationMethods, CompositeCallback, LoadUrlCallback, MouseCallback};
use windowing::{ResizeCallback, ScrollCallback, WindowMethods, WindowMouseEvent, WindowClickEvent};
use windowing::{WindowMouseDownEvent, WindowMouseUpEvent, ZoomCallback};

use alert::{Alert, AlertMethods};
use core::libc::c_int;
use geom::point::Point2D;
use geom::size::Size2D;
use glut::glut::{ACTIVE_CTRL, DOUBLE, HAVE_PRECISE_MOUSE_WHEEL, WindowHeight, WindowWidth};
use glut::glut;
use glut::machack;

/// A structure responsible for setting up and tearing down the entire windowing system.
pub struct Application;

impl ApplicationMethods for Application {
    pub fn new() -> Application {
        glut::init();
        glut::init_display_mode(DOUBLE);
        Application
    }
}

/// The type of a window.
pub struct Window {
    glut_window: glut::Window,

    composite_callback: Option<CompositeCallback>,
    resize_callback: Option<ResizeCallback>,
    load_url_callback: Option<LoadUrlCallback>,
    mouse_callback: Option<MouseCallback>,
    scroll_callback: Option<ScrollCallback>,
    zoom_callback: Option<ZoomCallback>,

    drag_origin: Point2D<c_int>,

    mouse_down_button: @mut c_int,
    mouse_down_point: @mut Point2D<c_int>,
}

impl WindowMethods<Application> for Window {
    /// Creates a new window.
    pub fn new(_: &Application) -> @mut Window {
        // Create the GLUT window.
        let glut_window = glut::create_window(~"Servo");
        glut::reshape_window(glut_window, 800, 600);

        // Create our window object.
        let window = @mut Window {
            glut_window: glut_window,

            composite_callback: None,
            resize_callback: None,
            load_url_callback: None,
            mouse_callback: None,
            scroll_callback: None,
            zoom_callback: None,

            drag_origin: Point2D(0, 0),

            mouse_down_button: @mut 0,
            mouse_down_point: @mut Point2D(0, 0),
        };

        // Register event handlers.
        do glut::reshape_func(window.glut_window) |width, height| {
            match window.resize_callback {
                None => {}
                Some(callback) => callback(width as uint, height as uint),
            }
        }
        do glut::display_func {
            // FIXME(pcwalton): This will not work with multiple windows.
            match window.composite_callback {
                None => {}
                Some(callback) => callback(),
            }
        }
        do glut::keyboard_func |key, _, _| {
            window.handle_key(key)
        }
        do glut::mouse_func |button, state, x, y| {
            if button < 3 {
                window.handle_mouse(button, state, x, y);
            }
        }
        do glut::mouse_wheel_func |wheel, direction, x, y| {
            let delta = if HAVE_PRECISE_MOUSE_WHEEL {
                (direction as f32) / 10000.0
            } else {
                (direction as f32) * 30.0
            };

            match wheel {
                1 => window.handle_scroll(Point2D(delta, 0.0)),
                2 => window.handle_zoom(delta),
                _ => window.handle_scroll(Point2D(0.0, delta)),
            }
        }

        machack::perform_scroll_wheel_hack();

        window
    }

    /// Returns the size of the window.
    pub fn size(&self) -> Size2D<f32> {
        Size2D(glut::get(WindowWidth) as f32, glut::get(WindowHeight) as f32)
    }

    /// Presents the window to the screen (perhaps by page flipping).
    pub fn present(&mut self) {
        glut::swap_buffers();
    }

    /// Registers a callback to run when a composite event occurs.
    pub fn set_composite_callback(&mut self, new_composite_callback: CompositeCallback) {
        self.composite_callback = Some(new_composite_callback)
    }

    /// Registers a callback to run when a resize event occurs.
    pub fn set_resize_callback(&mut self, new_resize_callback: ResizeCallback) {
        self.resize_callback = Some(new_resize_callback)
    }

    /// Registers a callback to be run when a new URL is to be loaded.
    pub fn set_load_url_callback(&mut self, new_load_url_callback: LoadUrlCallback) {
        self.load_url_callback = Some(new_load_url_callback)
    }

    /// Registers a callback to be run when a mouse event occurs.
    pub fn set_mouse_callback(&mut self, new_mouse_callback: MouseCallback) {
        self.mouse_callback = Some(new_mouse_callback)
    }

    /// Registers a callback to be run when the user scrolls.
    pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback) {
        self.scroll_callback = Some(new_scroll_callback)
    }

    /// Registers a zoom to be run when the user zooms.
    pub fn set_zoom_callback(&mut self, new_zoom_callback: ZoomCallback) {
        self.zoom_callback = Some(new_zoom_callback)
    }

    /// Spins the event loop.
    pub fn check_loop(@mut self) {
        glut::check_loop()
    }

    /// Schedules a redisplay.
    pub fn set_needs_display(@mut self) {
        glut::post_redisplay()
    }

    pub fn set_title(@mut self, title: &str) {
        glut::set_window_title(self.glut_window, title);
    }
}

impl Window {
    /// Helper function to handle keyboard events.
    fn handle_key(&self, key: u8) {
        debug!("got key: %d", key as int);
        match key {
            12 => self.load_url(),                                                      // Ctrl+L
            k if k == ('=' as u8) && (glut::get_modifiers() & ACTIVE_CTRL) != 0 => {    // Ctrl++
                for self.zoom_callback.each |&callback| {
                    callback(0.1);
                }
            }
            k if k == 31 && (glut::get_modifiers() & ACTIVE_CTRL) != 0 => {             // Ctrl+-
                for self.zoom_callback.each |&callback| {
                    callback(-0.1);
                }
            }
            _ => {}
        }
    }

    /// Helper function to handle a click
    fn handle_mouse(&self, button: c_int, state: c_int, x: c_int, y: c_int) {
        // FIXME(tkuehn): max pixel dist should be based on pixel density
        let max_pixel_dist = 10f;
        match self.mouse_callback {
            None => {}
            Some(callback) => {
                let event: WindowMouseEvent;
                match state {
                    glut::MOUSE_DOWN => {
                        event = WindowMouseDownEvent(button as uint, Point2D(x as f32, y as f32));
                        *self.mouse_down_point = Point2D(x, y);
                        *self.mouse_down_button = button;
                    }
                    glut::MOUSE_UP => {
                        event = WindowMouseUpEvent(button as uint, Point2D(x as f32, y as f32));
                        if *self.mouse_down_button == button {
                            let pixel_dist = *self.mouse_down_point - Point2D(x, y);
                            let pixel_dist = ((pixel_dist.x * pixel_dist.x +
                                              pixel_dist.y * pixel_dist.y) as float).sqrt();
                            if pixel_dist < max_pixel_dist {
                                let click_event = WindowClickEvent(button as uint,
                                                                   Point2D(x as f32, y as f32));
                                callback(click_event);
                            }
                        }
                    }
                    _ => fail!("I cannot recognize the type of mouse action that occured. :-(")
                };
                callback(event);
            }
        }
    }

    /// Helper function to handle a scroll.
    fn handle_scroll(&mut self, delta: Point2D<f32>) {
        match self.scroll_callback {
            None => {}
            Some(callback) => callback(delta),
        }
    }

    /// Helper function to handle a zoom.
    fn handle_zoom(&mut self, magnification: f32) {
        match self.zoom_callback {
            None => {}
            Some(callback) => callback(magnification),
        }
    }

    /// Helper function to pop up an alert box prompting the user to load a URL.
    fn load_url(&self) {
        match self.load_url_callback {
            None => error!("no URL callback registered, doing nothing"),
            Some(callback) => {
                let mut alert: Alert = AlertMethods::new("Navigate to:");
                alert.add_prompt();
                alert.run();
                let value = alert.prompt_value();
                if "" == value {    // To avoid crashing on Linux.
                    callback("http://purple.com/")
                } else {
                    callback(value)
                }
            }
        }
    }
}

<commit_msg>Spin the event loop every 50 ms to allow Rust channels to be processed.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! A windowing implementation using GLUT.
///
/// GLUT is a very old and bare-bones toolkit. However, it has good cross-platform support, at
/// least on desktops. It is designed for testing Servo without the need of a UI.

use windowing::{ApplicationMethods, CompositeCallback, LoadUrlCallback, MouseCallback};
use windowing::{ResizeCallback, ScrollCallback, WindowMethods, WindowMouseEvent, WindowClickEvent};
use windowing::{WindowMouseDownEvent, WindowMouseUpEvent, ZoomCallback};

use alert::{Alert, AlertMethods};
use core::cell::Cell;
use core::libc::c_int;
use geom::point::Point2D;
use geom::size::Size2D;
use glut::glut::{ACTIVE_CTRL, DOUBLE, HAVE_PRECISE_MOUSE_WHEEL, WindowHeight, WindowWidth};
use glut::glut;
use glut::machack;

/// A structure responsible for setting up and tearing down the entire windowing system.
pub struct Application;

impl ApplicationMethods for Application {
    pub fn new() -> Application {
        glut::init();
        glut::init_display_mode(DOUBLE);
        Application
    }
}

/// The type of a window.
pub struct Window {
    glut_window: glut::Window,

    composite_callback: Option<CompositeCallback>,
    resize_callback: Option<ResizeCallback>,
    load_url_callback: Option<LoadUrlCallback>,
    mouse_callback: Option<MouseCallback>,
    scroll_callback: Option<ScrollCallback>,
    zoom_callback: Option<ZoomCallback>,

    drag_origin: Point2D<c_int>,

    mouse_down_button: @mut c_int,
    mouse_down_point: @mut Point2D<c_int>,
}

impl WindowMethods<Application> for Window {
    /// Creates a new window.
    pub fn new(_: &Application) -> @mut Window {
        // Create the GLUT window.
        let glut_window = glut::create_window(~"Servo");
        glut::reshape_window(glut_window, 800, 600);

        // Create our window object.
        let window = @mut Window {
            glut_window: glut_window,

            composite_callback: None,
            resize_callback: None,
            load_url_callback: None,
            mouse_callback: None,
            scroll_callback: None,
            zoom_callback: None,

            drag_origin: Point2D(0, 0),

            mouse_down_button: @mut 0,
            mouse_down_point: @mut Point2D(0, 0),
        };

        // Spin the event loop every 50 ms to allow the Rust channels to be polled.
        //
        // This requirement is pretty much the nail in the coffin for GLUT's usefulness.
        //
        // FIXME(pcwalton): What a mess.
        let register_timer_callback: @mut @fn() = @mut ||{};
        *register_timer_callback = || {
            glut::timer_func(50, *register_timer_callback);
        };

        // Register event handlers.
        do glut::reshape_func(window.glut_window) |width, height| {
            match window.resize_callback {
                None => {}
                Some(callback) => callback(width as uint, height as uint),
            }
        }
        do glut::display_func {
            // FIXME(pcwalton): This will not work with multiple windows.
            match window.composite_callback {
                None => {}
                Some(callback) => callback(),
            }
        }
        do glut::keyboard_func |key, _, _| {
            window.handle_key(key)
        }
        do glut::mouse_func |button, state, x, y| {
            if button < 3 {
                window.handle_mouse(button, state, x, y);
            }
        }
        do glut::mouse_wheel_func |wheel, direction, x, y| {
            let delta = if HAVE_PRECISE_MOUSE_WHEEL {
                (direction as f32) / 10000.0
            } else {
                (direction as f32) * 30.0
            };

            match wheel {
                1 => window.handle_scroll(Point2D(delta, 0.0)),
                2 => window.handle_zoom(delta),
                _ => window.handle_scroll(Point2D(0.0, delta)),
            }
        }
        (*register_timer_callback)();

        machack::perform_scroll_wheel_hack();

        window
    }

    /// Returns the size of the window.
    pub fn size(&self) -> Size2D<f32> {
        Size2D(glut::get(WindowWidth) as f32, glut::get(WindowHeight) as f32)
    }

    /// Presents the window to the screen (perhaps by page flipping).
    pub fn present(&mut self) {
        glut::swap_buffers();
    }

    /// Registers a callback to run when a composite event occurs.
    pub fn set_composite_callback(&mut self, new_composite_callback: CompositeCallback) {
        self.composite_callback = Some(new_composite_callback)
    }

    /// Registers a callback to run when a resize event occurs.
    pub fn set_resize_callback(&mut self, new_resize_callback: ResizeCallback) {
        self.resize_callback = Some(new_resize_callback)
    }

    /// Registers a callback to be run when a new URL is to be loaded.
    pub fn set_load_url_callback(&mut self, new_load_url_callback: LoadUrlCallback) {
        self.load_url_callback = Some(new_load_url_callback)
    }

    /// Registers a callback to be run when a mouse event occurs.
    pub fn set_mouse_callback(&mut self, new_mouse_callback: MouseCallback) {
        self.mouse_callback = Some(new_mouse_callback)
    }

    /// Registers a callback to be run when the user scrolls.
    pub fn set_scroll_callback(&mut self, new_scroll_callback: ScrollCallback) {
        self.scroll_callback = Some(new_scroll_callback)
    }

    /// Registers a zoom to be run when the user zooms.
    pub fn set_zoom_callback(&mut self, new_zoom_callback: ZoomCallback) {
        self.zoom_callback = Some(new_zoom_callback)
    }

    /// Spins the event loop.
    pub fn check_loop(@mut self) {
        glut::check_loop()
    }

    /// Schedules a redisplay.
    pub fn set_needs_display(@mut self) {
        glut::post_redisplay()
    }

    pub fn set_title(@mut self, title: &str) {
        glut::set_window_title(self.glut_window, title);
    }
}

impl Window {
    /// Helper function to handle keyboard events.
    fn handle_key(&self, key: u8) {
        debug!("got key: %d", key as int);
        match key {
            12 => self.load_url(),                                                      // Ctrl+L
            k if k == ('=' as u8) && (glut::get_modifiers() & ACTIVE_CTRL) != 0 => {    // Ctrl++
                for self.zoom_callback.each |&callback| {
                    callback(0.1);
                }
            }
            k if k == 31 && (glut::get_modifiers() & ACTIVE_CTRL) != 0 => {             // Ctrl+-
                for self.zoom_callback.each |&callback| {
                    callback(-0.1);
                }
            }
            _ => {}
        }
    }

    /// Helper function to handle a click
    fn handle_mouse(&self, button: c_int, state: c_int, x: c_int, y: c_int) {
        // FIXME(tkuehn): max pixel dist should be based on pixel density
        let max_pixel_dist = 10f;
        match self.mouse_callback {
            None => {}
            Some(callback) => {
                let event: WindowMouseEvent;
                match state {
                    glut::MOUSE_DOWN => {
                        event = WindowMouseDownEvent(button as uint, Point2D(x as f32, y as f32));
                        *self.mouse_down_point = Point2D(x, y);
                        *self.mouse_down_button = button;
                    }
                    glut::MOUSE_UP => {
                        event = WindowMouseUpEvent(button as uint, Point2D(x as f32, y as f32));
                        if *self.mouse_down_button == button {
                            let pixel_dist = *self.mouse_down_point - Point2D(x, y);
                            let pixel_dist = ((pixel_dist.x * pixel_dist.x +
                                              pixel_dist.y * pixel_dist.y) as float).sqrt();
                            if pixel_dist < max_pixel_dist {
                                let click_event = WindowClickEvent(button as uint,
                                                                   Point2D(x as f32, y as f32));
                                callback(click_event);
                            }
                        }
                    }
                    _ => fail!("I cannot recognize the type of mouse action that occured. :-(")
                };
                callback(event);
            }
        }
    }

    /// Helper function to handle a scroll.
    fn handle_scroll(&mut self, delta: Point2D<f32>) {
        match self.scroll_callback {
            None => {}
            Some(callback) => callback(delta),
        }
    }

    /// Helper function to handle a zoom.
    fn handle_zoom(&mut self, magnification: f32) {
        match self.zoom_callback {
            None => {}
            Some(callback) => callback(magnification),
        }
    }

    /// Helper function to pop up an alert box prompting the user to load a URL.
    fn load_url(&self) {
        match self.load_url_callback {
            None => error!("no URL callback registered, doing nothing"),
            Some(callback) => {
                let mut alert: Alert = AlertMethods::new("Navigate to:");
                alert.add_prompt();
                alert.run();
                let value = alert.prompt_value();
                if "" == value {    // To avoid crashing on Linux.
                    callback("http://purple.com/")
                } else {
                    callback(value)
                }
            }
        }
    }
}

<|endoftext|>