<commit_before>//! cargo_check provides the functionality needed to run `cargo check` or
//! another compatible command (f.x. clippy) in a background thread and provide
//! LSP diagnostics based on the output of the command.

use std::{
    fmt,
    io::{self, BufReader},
    ops,
    path::PathBuf,
    process::{self, Command, Stdio},
    time::Duration,
};

use crossbeam_channel::{never, select, unbounded, Receiver, Sender};

pub use cargo_metadata::diagnostic::{
    Applicability, Diagnostic, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion,
};

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FlycheckConfig {
    CargoCommand {
        command: String,
        all_targets: bool,
        all_features: bool,
        features: Vec<String>,
        extra_args: Vec<String>,
    },
    CustomCommand {
        command: String,
        args: Vec<String>,
    },
}

impl fmt::Display for FlycheckConfig {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FlycheckConfig::CargoCommand { command, .. } => write!(f, "cargo {}", command),
            FlycheckConfig::CustomCommand { command, args } => {
                write!(f, "{} {}", command, args.join(" "))
            }
        }
    }
}

/// Flycheck wraps the shared state and communication machinery used for
/// running `cargo check` (or other compatible command) and providing
/// diagnostics based on the output.
/// The spawned thread is shut down when this struct is dropped.
#[derive(Debug)]
pub struct FlycheckHandle {
    // XXX: drop order is significant
    sender: Sender<Restart>,
    thread: jod_thread::JoinHandle,
}

impl FlycheckHandle {
    pub fn spawn(
        sender: Box<dyn Fn(Message) + Send>,
        config: FlycheckConfig,
        workspace_root: PathBuf,
    ) -> FlycheckHandle {
        let actor = FlycheckActor::new(sender, config, workspace_root);
        let (sender, receiver) = unbounded::<Restart>();
        let thread = jod_thread::spawn(move || actor.run(receiver));
        FlycheckHandle { sender, thread }
    }

    /// Schedule a re-start of the cargo check worker.
    pub fn update(&self) {
        self.sender.send(Restart).unwrap();
    }
}

#[derive(Debug)]
pub enum Message {
    /// Request adding a diagnostic with fixes included to a file
    AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic },

    /// Request check progress notification to client
    Progress(Progress),
}

#[derive(Debug)]
pub enum Progress {
    DidStart,
    DidCheckCrate(String),
    DidFinish(io::Result<()>),
    DidCancel,
}

struct Restart;

struct FlycheckActor {
    sender: Box<dyn Fn(Message) + Send>,
    config: FlycheckConfig,
    workspace_root: PathBuf,
    /// WatchThread exists to wrap around the communication needed to be able to
    /// run `cargo check` without blocking. Currently the Rust standard library
    /// doesn't provide a way to read sub-process output without blocking, so we
    /// have to wrap sub-processes output handling in a thread and pass messages
    /// back over a channel.
    cargo_handle: Option<CargoHandle>,
}

enum Event {
    Restart(Restart),
    CheckEvent(Option<cargo_metadata::Message>),
}

impl FlycheckActor {
    fn new(
        sender: Box<dyn Fn(Message) + Send>,
        config: FlycheckConfig,
        workspace_root: PathBuf,
    ) -> FlycheckActor {
        FlycheckActor { sender, config, workspace_root, cargo_handle: None }
    }
    fn next_event(&self, inbox: &Receiver<Restart>) -> Option<Event> {
        let check_chan = self.cargo_handle.as_ref().map(|cargo| &cargo.receiver);
        select! {
            recv(inbox) -> msg => msg.ok().map(Event::Restart),
            recv(check_chan.unwrap_or(&never())) -> msg => Some(Event::CheckEvent(msg.ok())),
        }
    }
    fn run(mut self, inbox: Receiver<Restart>) {
        while let Some(event) = self.next_event(&inbox) {
            match event {
                Event::Restart(Restart) => {
                    while let Ok(Restart) = inbox.recv_timeout(Duration::from_millis(50)) {}

                    self.cancel_check_process();

                    let mut command = self.check_command();
                    command.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null());
                    if let Ok(child) = command.spawn().map(JodChild) {
                        self.cargo_handle = Some(CargoHandle::spawn(child));
                        self.send(Message::Progress(Progress::DidStart));
                    }
                }
                Event::CheckEvent(None) => {
                    // Watcher finished, replace it with a never channel to
                    // avoid busy-waiting.
                    let cargo_handle = self.cargo_handle.take().unwrap();
                    let res = cargo_handle.join();
                    self.send(Message::Progress(Progress::DidFinish(res)));
                }
                Event::CheckEvent(Some(message)) => match message {
                    cargo_metadata::Message::CompilerArtifact(msg) => {
                        self.send(Message::Progress(Progress::DidCheckCrate(msg.target.name)));
                    }

                    cargo_metadata::Message::CompilerMessage(msg) => {
                        self.send(Message::AddDiagnostic {
                            workspace_root: self.workspace_root.clone(),
                            diagnostic: msg.message,
                        });
                    }

                    cargo_metadata::Message::BuildScriptExecuted(_)
                    | cargo_metadata::Message::BuildFinished(_)
                    | cargo_metadata::Message::TextLine(_)
                    | cargo_metadata::Message::Unknown => {}
                },
            }
        }
        // If we rerun the thread, we need to discard the previous check results first
        self.cancel_check_process();
    }
    fn cancel_check_process(&mut self) {
        if self.cargo_handle.take().is_some() {
            self.send(Message::Progress(Progress::DidCancel));
        }
    }
    fn check_command(&self) -> Command {
        let mut cmd = match &self.config {
            FlycheckConfig::CargoCommand {
                command,
                all_targets,
                all_features,
                extra_args,
                features,
            } => {
                let mut cmd = Command::new(ra_toolchain::cargo());
                cmd.arg(command);
                cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
                    .arg(self.workspace_root.join("Cargo.toml"));
                if *all_targets {
                    cmd.arg("--all-targets");
                }
                if *all_features {
                    cmd.arg("--all-features");
                } else if !features.is_empty() {
                    cmd.arg("--features");
                    cmd.arg(features.join(" "));
                }
                cmd.args(extra_args);
                cmd
            }
            FlycheckConfig::CustomCommand { command, args } => {
                let mut cmd = Command::new(command);
                cmd.args(args);
                cmd
            }
        };
        cmd.current_dir(&self.workspace_root);
        cmd
    }

    fn send(&self, check_task: Message) {
        (self.sender)(check_task)
    }
}

struct CargoHandle {
    child: JodChild,
    #[allow(unused)]
    thread: jod_thread::JoinHandle<io::Result<bool>>,
    receiver: Receiver<cargo_metadata::Message>,
}

impl CargoHandle {
    fn spawn(mut child: JodChild) -> CargoHandle {
        let child_stdout = child.stdout.take().unwrap();
        let (sender, receiver) = unbounded();
        let actor = CargoActor::new(child_stdout, sender);
        let thread = jod_thread::spawn(move || actor.run());
        CargoHandle { child, thread, receiver }
    }
    fn join(mut self) -> io::Result<()> {
        // It is okay to ignore the result, as it only errors if the process is already dead
        let _ = self.child.kill();
        let exit_status = self.child.wait()?;
        let read_at_least_one_message = self.thread.join()?;
        if !exit_status.success() && !read_at_least_one_message {
            // FIXME: Read the stderr to display the reason, see `read2()` reference in PR comment:
            // https://github.com/rust-analyzer/rust-analyzer/pull/3632#discussion_r395605298
            return Err(io::Error::new(
                io::ErrorKind::Other,
                format!(
                    "Cargo watcher failed,the command produced no valid metadata (exit code: {:?})",
                    exit_status
                ),
            ));
        }
        Ok(())
    }
}

struct CargoActor {
    child_stdout: process::ChildStdout,
    sender: Sender<cargo_metadata::Message>,
}

impl CargoActor {
    fn new(
        child_stdout: process::ChildStdout,
        sender: Sender<cargo_metadata::Message>,
    ) -> CargoActor {
        CargoActor { child_stdout, sender }
    }
    fn run(self) -> io::Result<bool> {
        // We manually read a line at a time, instead of using serde's
        // stream deserializers, because the deserializer cannot recover
        // from an error, resulting in it getting stuck, because we try to
        // be resilient against failures.
        //
        // Because cargo only outputs one JSON object per line, we can
        // simply skip a line if it doesn't parse, which just ignores any
        // erroneus output.
        let stdout = BufReader::new(self.child_stdout);
        let mut read_at_least_one_message = false;
        for message in cargo_metadata::Message::parse_stream(stdout) {
            let message = match message {
                Ok(message) => message,
                Err(err) => {
                    log::error!("Invalid json from cargo check, ignoring ({})", err);
                    continue;
                }
            };

            read_at_least_one_message = true;

            // Skip certain kinds of messages to only spend time on what's useful
            match &message {
                cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => (),
                cargo_metadata::Message::BuildScriptExecuted(_)
                | cargo_metadata::Message::Unknown => (),
                _ => self.sender.send(message).unwrap(),
            }
        }
        Ok(read_at_least_one_message)
    }
}

struct JodChild(process::Child);

impl ops::Deref for JodChild {
    type Target = process::Child;
    fn deref(&self) -> &process::Child {
        &self.0
    }
}

impl ops::DerefMut for JodChild {
    fn deref_mut(&mut self) -> &mut process::Child {
        &mut self.0
    }
}

impl Drop for JodChild {
    fn drop(&mut self) {
        let _ = self.0.kill();
    }
}
<commit_msg>Log flycheck command<commit_after>//! cargo_check provides the functionality needed to run `cargo check` or
//! another compatible command (f.x. clippy) in a background thread and provide
//! LSP diagnostics based on the output of the command.

use std::{
    fmt,
    io::{self, BufReader},
    ops,
    path::PathBuf,
    process::{self, Command, Stdio},
    time::Duration,
};

use crossbeam_channel::{never, select, unbounded, Receiver, Sender};

pub use cargo_metadata::diagnostic::{
    Applicability, Diagnostic, DiagnosticLevel, DiagnosticSpan, DiagnosticSpanMacroExpansion,
};

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FlycheckConfig {
    CargoCommand {
        command: String,
        all_targets: bool,
        all_features: bool,
        features: Vec<String>,
        extra_args: Vec<String>,
    },
    CustomCommand {
        command: String,
        args: Vec<String>,
    },
}

impl fmt::Display for FlycheckConfig {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            FlycheckConfig::CargoCommand { command, .. } => write!(f, "cargo {}", command),
            FlycheckConfig::CustomCommand { command, args } => {
                write!(f, "{} {}", command, args.join(" "))
            }
        }
    }
}

/// Flycheck wraps the shared state and communication machinery used for
/// running `cargo check` (or other compatible command) and providing
/// diagnostics based on the output.
/// The spawned thread is shut down when this struct is dropped.
#[derive(Debug)]
pub struct FlycheckHandle {
    // XXX: drop order is significant
    sender: Sender<Restart>,
    thread: jod_thread::JoinHandle,
}

impl FlycheckHandle {
    pub fn spawn(
        sender: Box<dyn Fn(Message) + Send>,
        config: FlycheckConfig,
        workspace_root: PathBuf,
    ) -> FlycheckHandle {
        let actor = FlycheckActor::new(sender, config, workspace_root);
        let (sender, receiver) = unbounded::<Restart>();
        let thread = jod_thread::spawn(move || actor.run(receiver));
        FlycheckHandle { sender, thread }
    }

    /// Schedule a re-start of the cargo check worker.
    pub fn update(&self) {
        self.sender.send(Restart).unwrap();
    }
}

#[derive(Debug)]
pub enum Message {
    /// Request adding a diagnostic with fixes included to a file
    AddDiagnostic { workspace_root: PathBuf, diagnostic: Diagnostic },

    /// Request check progress notification to client
    Progress(Progress),
}

#[derive(Debug)]
pub enum Progress {
    DidStart,
    DidCheckCrate(String),
    DidFinish(io::Result<()>),
    DidCancel,
}

struct Restart;

struct FlycheckActor {
    sender: Box<dyn Fn(Message) + Send>,
    config: FlycheckConfig,
    workspace_root: PathBuf,
    /// WatchThread exists to wrap around the communication needed to be able to
    /// run `cargo check` without blocking. Currently the Rust standard library
    /// doesn't provide a way to read sub-process output without blocking, so we
    /// have to wrap sub-processes output handling in a thread and pass messages
    /// back over a channel.
    cargo_handle: Option<CargoHandle>,
}

enum Event {
    Restart(Restart),
    CheckEvent(Option<cargo_metadata::Message>),
}

impl FlycheckActor {
    fn new(
        sender: Box<dyn Fn(Message) + Send>,
        config: FlycheckConfig,
        workspace_root: PathBuf,
    ) -> FlycheckActor {
        FlycheckActor { sender, config, workspace_root, cargo_handle: None }
    }
    fn next_event(&self, inbox: &Receiver<Restart>) -> Option<Event> {
        let check_chan = self.cargo_handle.as_ref().map(|cargo| &cargo.receiver);
        select! {
            recv(inbox) -> msg => msg.ok().map(Event::Restart),
            recv(check_chan.unwrap_or(&never())) -> msg => Some(Event::CheckEvent(msg.ok())),
        }
    }
    fn run(mut self, inbox: Receiver<Restart>) {
        while let Some(event) = self.next_event(&inbox) {
            match event {
                Event::Restart(Restart) => {
                    while let Ok(Restart) = inbox.recv_timeout(Duration::from_millis(50)) {}

                    self.cancel_check_process();

                    let mut command = self.check_command();
                    log::info!("restart flycheck {:?}", command);
                    command.stdout(Stdio::piped()).stderr(Stdio::null()).stdin(Stdio::null());
                    if let Ok(child) = command.spawn().map(JodChild) {
                        self.cargo_handle = Some(CargoHandle::spawn(child));
                        self.send(Message::Progress(Progress::DidStart));
                    }
                }
                Event::CheckEvent(None) => {
                    // Watcher finished, replace it with a never channel to
                    // avoid busy-waiting.
                    let cargo_handle = self.cargo_handle.take().unwrap();
                    let res = cargo_handle.join();
                    self.send(Message::Progress(Progress::DidFinish(res)));
                }
                Event::CheckEvent(Some(message)) => match message {
                    cargo_metadata::Message::CompilerArtifact(msg) => {
                        self.send(Message::Progress(Progress::DidCheckCrate(msg.target.name)));
                    }

                    cargo_metadata::Message::CompilerMessage(msg) => {
                        self.send(Message::AddDiagnostic {
                            workspace_root: self.workspace_root.clone(),
                            diagnostic: msg.message,
                        });
                    }

                    cargo_metadata::Message::BuildScriptExecuted(_)
                    | cargo_metadata::Message::BuildFinished(_)
                    | cargo_metadata::Message::TextLine(_)
                    | cargo_metadata::Message::Unknown => {}
                },
            }
        }
        // If we rerun the thread, we need to discard the previous check results first
        self.cancel_check_process();
    }
    fn cancel_check_process(&mut self) {
        if self.cargo_handle.take().is_some() {
            self.send(Message::Progress(Progress::DidCancel));
        }
    }
    fn check_command(&self) -> Command {
        let mut cmd = match &self.config {
            FlycheckConfig::CargoCommand {
                command,
                all_targets,
                all_features,
                extra_args,
                features,
            } => {
                let mut cmd = Command::new(ra_toolchain::cargo());
                cmd.arg(command);
                cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
                    .arg(self.workspace_root.join("Cargo.toml"));
                if *all_targets {
                    cmd.arg("--all-targets");
                }
                if *all_features {
                    cmd.arg("--all-features");
                } else if !features.is_empty() {
                    cmd.arg("--features");
                    cmd.arg(features.join(" "));
                }
                cmd.args(extra_args);
                cmd
            }
            FlycheckConfig::CustomCommand { command, args } => {
                let mut cmd = Command::new(command);
                cmd.args(args);
                cmd
            }
        };
        cmd.current_dir(&self.workspace_root);
        cmd
    }

    fn send(&self, check_task: Message) {
        (self.sender)(check_task)
    }
}

struct CargoHandle {
    child: JodChild,
    #[allow(unused)]
    thread: jod_thread::JoinHandle<io::Result<bool>>,
    receiver: Receiver<cargo_metadata::Message>,
}

impl CargoHandle {
    fn spawn(mut child: JodChild) -> CargoHandle {
        let child_stdout = child.stdout.take().unwrap();
        let (sender, receiver) = unbounded();
        let actor = CargoActor::new(child_stdout, sender);
        let thread = jod_thread::spawn(move || actor.run());
        CargoHandle { child, thread, receiver }
    }
    fn join(mut self) -> io::Result<()> {
        // It is okay to ignore the result, as it only errors if the process is already dead
        let _ = self.child.kill();
        let exit_status = self.child.wait()?;
        let read_at_least_one_message = self.thread.join()?;
        if !exit_status.success() && !read_at_least_one_message {
            // FIXME: Read the stderr to display the reason, see `read2()` reference in PR comment:
            // https://github.com/rust-analyzer/rust-analyzer/pull/3632#discussion_r395605298
            return Err(io::Error::new(
                io::ErrorKind::Other,
                format!(
                    "Cargo watcher failed,the command produced no valid metadata (exit code: {:?})",
                    exit_status
                ),
            ));
        }
        Ok(())
    }
}

struct CargoActor {
    child_stdout: process::ChildStdout,
    sender: Sender<cargo_metadata::Message>,
}

impl CargoActor {
    fn new(
        child_stdout: process::ChildStdout,
        sender: Sender<cargo_metadata::Message>,
    ) -> CargoActor {
        CargoActor { child_stdout, sender }
    }
    fn run(self) -> io::Result<bool> {
        // We manually read a line at a time, instead of using serde's
        // stream deserializers, because the deserializer cannot recover
        // from an error, resulting in it getting stuck, because we try to
        // be resilient against failures.
        //
        // Because cargo only outputs one JSON object per line, we can
        // simply skip a line if it doesn't parse, which just ignores any
        // erroneus output.
        let stdout = BufReader::new(self.child_stdout);
        let mut read_at_least_one_message = false;
        for message in cargo_metadata::Message::parse_stream(stdout) {
            let message = match message {
                Ok(message) => message,
                Err(err) => {
                    log::error!("Invalid json from cargo check, ignoring ({})", err);
                    continue;
                }
            };

            read_at_least_one_message = true;

            // Skip certain kinds of messages to only spend time on what's useful
            match &message {
                cargo_metadata::Message::CompilerArtifact(artifact) if artifact.fresh => (),
                cargo_metadata::Message::BuildScriptExecuted(_)
                | cargo_metadata::Message::Unknown => (),
                _ => self.sender.send(message).unwrap(),
            }
        }
        Ok(read_at_least_one_message)
    }
}

struct JodChild(process::Child);

impl ops::Deref for JodChild {
    type Target = process::Child;
    fn deref(&self) -> &process::Child {
        &self.0
    }
}

impl ops::DerefMut for JodChild {
    fn deref_mut(&mut self) -> &mut process::Child {
        &mut self.0
    }
}

impl Drop for JodChild {
    fn drop(&mut self) {
        let _ = self.0.kill();
    }
}
<|endoftext|>


<commit_before>//! printf debugging infrastructure for rust-analyzer.
//!
//! When you print a hir type, like a module, using `eprintln!("{:?}", module)`,
//! you usually get back a numeric ID, which doesn't tell you much:
//! `Module(92)`.
//!
//! This module adds convenience `debug` methods to various types, which resolve
//! the id to a human-readable location info:
//!
//! ```not_rust
//! eprintln!("{:?}", module.debug(db));
//! =>
//! Module { name: collections, path: "liballoc/collections/mod.rs" }
//! ```
//!
//! Note that to get this info, we might need to execute queries! So
//!
//! * don't use the `debug` methods for logging
//! * when debugging, be aware that interference is possible.

use std::fmt;

use ra_db::{CrateId, FileId};

use crate::{db::HirDatabase, Crate, HirFileId, Module, Name};

impl Crate {
    pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
        debug_fn(move |fmt| db.debug_crate(self, fmt))
    }
}

impl Module {
    pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
        debug_fn(move |fmt| db.debug_module(self, fmt))
    }
}

pub trait HirDebugHelper: HirDatabase {
    fn crate_name(&self, _krate: CrateId) -> Option<String> {
        None
    }
    fn file_path(&self, _file_id: FileId) -> Option<String> {
        None
    }
}

pub trait HirDebugDatabase {
    fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
    fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
    fn debug_hir_file_id(&self, file_id: HirFileId, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
}

impl<DB: HirDebugHelper> HirDebugDatabase for DB {
    fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut builder = fmt.debug_tuple("Crate");
        match self.crate_name(krate.crate_id) {
            Some(name) => builder.field(&name),
            None => builder.field(&krate.crate_id),
        }
        .finish()
    }

    fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let file_id = module.definition_source(self).file_id.original_file(self);
        let path = self.file_path(file_id).unwrap_or_else(|| "N/A".to_string());
        fmt.debug_struct("Module")
            .field("name", &module.name(self).unwrap_or_else(Name::missing))
            .field("path", &path)
            .finish()
    }

    fn debug_hir_file_id(&self, file_id: HirFileId, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let original = file_id.original_file(self);
        let path = self.file_path(original).unwrap_or_else(|| "N/A".to_string());
        let is_macro = file_id != original.into();
        fmt.debug_struct("HirFileId").field("path", &path).field("macro", &is_macro).finish()
    }
}

fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug {
    struct DebugFn<F>(F);

    impl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for DebugFn<F> {
        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
            (&self.0)(fmt)
        }
    }

    DebugFn(f)
}
<commit_msg>Note that debugging infra is broken<commit_after>//! XXX: This does not work at the moment.
//!
//! printf debugging infrastructure for rust-analyzer.
//!
//! When you print a hir type, like a module, using `eprintln!("{:?}", module)`,
//! you usually get back a numeric ID, which doesn't tell you much:
//! `Module(92)`.
//!
//! This module adds convenience `debug` methods to various types, which resolve
//! the id to a human-readable location info:
//!
//! ```not_rust
//! eprintln!("{:?}", module.debug(db));
//! =>
//! Module { name: collections, path: "liballoc/collections/mod.rs" }
//! ```
//!
//! Note that to get this info, we might need to execute queries! So
//!
//! * don't use the `debug` methods for logging
//! * when debugging, be aware that interference is possible.

use std::fmt;

use ra_db::{CrateId, FileId};

use crate::{db::HirDatabase, Crate, HirFileId, Module, Name};

impl Crate {
    pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
        debug_fn(move |fmt| db.debug_crate(self, fmt))
    }
}

impl Module {
    pub fn debug(self, db: &impl HirDebugDatabase) -> impl fmt::Debug + '_ {
        debug_fn(move |fmt| db.debug_module(self, fmt))
    }
}

pub trait HirDebugHelper: HirDatabase {
    fn crate_name(&self, _krate: CrateId) -> Option<String> {
        None
    }
    fn file_path(&self, _file_id: FileId) -> Option<String> {
        None
    }
}

pub trait HirDebugDatabase {
    fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
    fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
    fn debug_hir_file_id(&self, file_id: HirFileId, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
}

impl<DB: HirDebugHelper> HirDebugDatabase for DB {
    fn debug_crate(&self, krate: Crate, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut builder = fmt.debug_tuple("Crate");
        match self.crate_name(krate.crate_id) {
            Some(name) => builder.field(&name),
            None => builder.field(&krate.crate_id),
        }
        .finish()
    }

    fn debug_module(&self, module: Module, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let file_id = module.definition_source(self).file_id.original_file(self);
        let path = self.file_path(file_id).unwrap_or_else(|| "N/A".to_string());
        fmt.debug_struct("Module")
            .field("name", &module.name(self).unwrap_or_else(Name::missing))
            .field("path", &path)
            .finish()
    }

    fn debug_hir_file_id(&self, file_id: HirFileId, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        let original = file_id.original_file(self);
        let path = self.file_path(original).unwrap_or_else(|| "N/A".to_string());
        let is_macro = file_id != original.into();
        fmt.debug_struct("HirFileId").field("path", &path).field("macro", &is_macro).finish()
    }
}

fn debug_fn(f: impl Fn(&mut fmt::Formatter<'_>) -> fmt::Result) -> impl fmt::Debug {
    struct DebugFn<F>(F);

    impl<F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result> fmt::Debug for DebugFn<F> {
        fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
            (&self.0)(fmt)
        }
    }

    DebugFn(f)
}
<|endoftext|>


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

//! A graph module for use in dataflow, region resolution, and elsewhere.
//!
//! # Interface details
//!
//! You customize the graph by specifying a "node data" type `N` and an
//! "edge data" type `E`. You can then later gain access (mutable or
//! immutable) to these "user-data" bits. Currently, you can only add
//! nodes or edges to the graph. You cannot remove or modify them once
//! added. This could be changed if we have a need.
//!
//! # Implementation details
//!
//! The main tricky thing about this code is the way that edges are
//! stored. The edges are stored in a central array, but they are also
//! threaded onto two linked lists for each node, one for incoming edges
//! and one for outgoing edges. Note that every edge is a member of some
//! incoming list and some outgoing list.  Basically you can load the
//! first index of the linked list from the node data structures (the
//! field `first_edge`) and then, for each edge, load the next index from
//! the field `next_edge`). Each of those fields is an array that should
//! be indexed by the direction (see the type `Direction`).

use bitvec::BitVector;
use std::fmt::{Formatter, Error, Debug};
use std::usize;
use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};

#[cfg(test)]
mod tests;

pub struct Graph<N, E> {
    nodes: SnapshotVec<Node<N>>,
    edges: SnapshotVec<Edge<E>>,
}

pub struct Node<N> {
    first_edge: [EdgeIndex; 2], // see module comment
    pub data: N,
}

pub struct Edge<E> {
    next_edge: [EdgeIndex; 2], // see module comment
    source: NodeIndex,
    target: NodeIndex,
    pub data: E,
}

impl<N> SnapshotVecDelegate for Node<N> {
    type Value = Node<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Node<N>>, _: ()) {}
}

impl<N> SnapshotVecDelegate for Edge<N> {
    type Value = Edge<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Edge<N>>, _: ()) {}
}

impl<E: Debug> Debug for Edge<E> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f,
               "Edge {{ next_edge: [{:?}, {:?}], source: {:?}, target: {:?}, data: {:?} }}",
               self.next_edge[0],
               self.next_edge[1],
               self.source,
               self.target,
               self.data)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct NodeIndex(pub usize);

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct EdgeIndex(pub usize);

pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX);

// Use a private field here to guarantee no more instances are created:
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Direction {
    repr: usize,
}

pub const OUTGOING: Direction = Direction { repr: 0 };

pub const INCOMING: Direction = Direction { repr: 1 };

impl NodeIndex {
    /// Returns unique id (unique with respect to the graph holding associated node).
    pub fn node_id(&self) -> usize {
        self.0
    }
}

impl EdgeIndex {
    /// Returns unique id (unique with respect to the graph holding associated edge).
    pub fn edge_id(&self) -> usize {
        self.0
    }
}

impl<N: Debug, E: Debug> Graph<N, E> {
    pub fn new() -> Graph<N, E> {
        Graph {
            nodes: SnapshotVec::new(),
            edges: SnapshotVec::new(),
        }
    }

    // # Simple accessors

    #[inline]
    pub fn all_nodes(&self) -> &[Node<N>] {
        &self.nodes
    }

    #[inline]
    pub fn len_nodes(&self) -> usize {
        self.nodes.len()
    }

    #[inline]
    pub fn all_edges(&self) -> &[Edge<E>] {
        &self.edges
    }

    #[inline]
    pub fn len_edges(&self) -> usize {
        self.edges.len()
    }

    // # Node construction

    pub fn next_node_index(&self) -> NodeIndex {
        NodeIndex(self.nodes.len())
    }

    pub fn add_node(&mut self, data: N) -> NodeIndex {
        let idx = self.next_node_index();
        self.nodes.push(Node {
            first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX],
            data: data,
        });
        idx
    }

    pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
        &mut self.nodes[idx.0].data
    }

    pub fn node_data(&self, idx: NodeIndex) -> &N {
        &self.nodes[idx.0].data
    }

    pub fn node(&self, idx: NodeIndex) -> &Node<N> {
        &self.nodes[idx.0]
    }

    // # Edge construction and queries

    pub fn next_edge_index(&self) -> EdgeIndex {
        EdgeIndex(self.edges.len())
    }

    pub fn add_edge(&mut self, source: NodeIndex, target: NodeIndex, data: E) -> EdgeIndex {
        debug!("graph: add_edge({:?}, {:?}, {:?})", source, target, data);

        let idx = self.next_edge_index();

        // read current first of the list of edges from each node
        let source_first = self.nodes[source.0].first_edge[OUTGOING.repr];
        let target_first = self.nodes[target.0].first_edge[INCOMING.repr];

        // create the new edge, with the previous firsts from each node
        // as the next pointers
        self.edges.push(Edge {
            next_edge: [source_first, target_first],
            source: source,
            target: target,
            data: data,
        });

        // adjust the firsts for each node target be the next object.
        self.nodes[source.0].first_edge[OUTGOING.repr] = idx;
        self.nodes[target.0].first_edge[INCOMING.repr] = idx;

        return idx;
    }

    pub fn mut_edge_data(&mut self, idx: EdgeIndex) -> &mut E {
        &mut self.edges[idx.0].data
    }

    pub fn edge_data(&self, idx: EdgeIndex) -> &E {
        &self.edges[idx.0].data
    }

    pub fn edge(&self, idx: EdgeIndex) -> &Edge<E> {
        &self.edges[idx.0]
    }

    pub fn first_adjacent(&self, node: NodeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the index of the first edge adjacent to `node`.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.nodes[node.0].first_edge[dir.repr]
    }

    pub fn next_adjacent(&self, edge: EdgeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the next edge in a given direction.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.edges[edge.0].next_edge[dir.repr]
    }

    // # Iterating over nodes, edges

    pub fn all_nodes_enumerated(&self) -> Nodes<N> {
        Nodes {
            iter: self.nodes.iter().enumerate()
        }
    }

    pub fn all_edges_enumerated(&self) -> Edges<E> {
        Edges {
            iter: self.edges.iter().enumerate()
        }
    }

    pub fn each_node<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(NodeIndex, &'a Node<N>) -> bool
    {
        //! Iterates over all edges defined in the graph.
        self.all_nodes_enumerated().all(|(node_idx, node)| f(node_idx, node))
    }

    pub fn each_edge<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(EdgeIndex, &'a Edge<E>) -> bool
    {
        //! Iterates over all edges defined in the graph
        self.all_edges_enumerated().all(|(edge_idx, edge)| f(edge_idx, edge))
    }

    pub fn outgoing_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, OUTGOING)
    }

    pub fn incoming_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, INCOMING)
    }

    pub fn adjacent_edges(&self, source: NodeIndex, direction: Direction) -> AdjacentEdges<N, E> {
        let first_edge = self.node(source).first_edge[direction.repr];
        AdjacentEdges {
            graph: self,
            direction: direction,
            next: first_edge,
        }
    }

    pub fn successor_nodes(&self, source: NodeIndex) -> AdjacentTargets<N, E> {
        self.outgoing_edges(source).targets()
    }

    pub fn predecessor_nodes(&self, target: NodeIndex) -> AdjacentSources<N, E> {
        self.incoming_edges(target).sources()
    }

    // # Fixed-point iteration
    //
    // A common use for graphs in our compiler is to perform
    // fixed-point iteration. In this case, each edge represents a
    // constraint, and the nodes themselves are associated with
    // variables or other bitsets. This method facilitates such a
    // computation.

    pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F)
        where F: FnMut(usize, EdgeIndex, &'a Edge<E>) -> bool
    {
        let mut iteration = 0;
        let mut changed = true;
        while changed {
            changed = false;
            iteration += 1;
            for (edge_index, edge) in self.all_edges_enumerated() {
                changed |= op(iteration, edge_index, edge);
            }
        }
    }

    pub fn depth_traverse<'a>(&'a self,
                              start: NodeIndex,
                              direction: Direction)
                              -> DepthFirstTraversal<'a, N, E> {
        DepthFirstTraversal::with_start_node(self, start, direction)
    }
}

// # Iterators

pub struct Nodes<'g, N>
    where N: 'g,
{
    iter: ::std::iter::Enumerate<::std::slice::Iter<'g, Node<N>>>
}

impl<'g, N: Debug> Iterator for Nodes<'g, N> {
    type Item = (NodeIndex, &'g Node<N>);

    fn next(&mut self) -> Option<(NodeIndex, &'g Node<N>)> {
        self.iter.next().map(|(idx, n)| (NodeIndex(idx), n))
    }
}

pub struct Edges<'g, E>
    where E: 'g,
{
    iter: ::std::iter::Enumerate<::std::slice::Iter<'g, Edge<E>>>
}

impl<'g, E: Debug> Iterator for Edges<'g, E> {
    type Item = (EdgeIndex, &'g Edge<E>);

    fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> {
        self.iter.next().map(|(idx, e)| (EdgeIndex(idx), e))
    }
}

pub struct AdjacentEdges<'g, N, E>
    where N: 'g,
          E: 'g
{
    graph: &'g Graph<N, E>,
    direction: Direction,
    next: EdgeIndex,
}

impl<'g, N, E> AdjacentEdges<'g, N, E> {
    fn targets(self) -> AdjacentTargets<'g, N, E> {
        AdjacentTargets { edges: self }
    }

    fn sources(self) -> AdjacentSources<'g, N, E> {
        AdjacentSources { edges: self }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
    type Item = (EdgeIndex, &'g Edge<E>);

    fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> {
        let edge_index = self.next;
        if edge_index == INVALID_EDGE_INDEX {
            return None;
        }

        let edge = self.graph.edge(edge_index);
        self.next = edge.next_edge[self.direction.repr];
        Some((edge_index, edge))
    }
}

pub struct AdjacentTargets<'g, N, E>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentTargets<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.target)
    }
}

pub struct AdjacentSources<'g, N, E>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentSources<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.source)
    }
}

pub struct DepthFirstTraversal<'g, N, E>
    where N: 'g,
          E: 'g
{
    graph: &'g Graph<N, E>,
    stack: Vec<NodeIndex>,
    visited: BitVector,
    direction: Direction,
}

impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
    pub fn new(graph: &'g Graph<N, E>, direction: Direction) -> Self {
        let visited = BitVector::new(graph.len_nodes());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![],
            visited: visited,
            direction: direction,
        }
    }

    pub fn with_start_node(graph: &'g Graph<N, E>,
                           start_node: NodeIndex,
                           direction: Direction)
                           -> Self {
        let mut visited = BitVector::new(graph.len_nodes());
        visited.insert(start_node.node_id());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![start_node],
            visited: visited,
            direction: direction,
        }
    }

    pub fn reset(&mut self, start_node: NodeIndex) {
        self.stack.truncate(0);
        self.stack.push(start_node);
        self.visited.clear();
        self.visited.insert(start_node.node_id());
    }

    fn visit(&mut self, node: NodeIndex) {
        if self.visited.insert(node.node_id()) {
            self.stack.push(node);
        }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        let next = self.stack.pop();
        if let Some(idx) = next {
            for (_, edge) in self.graph.adjacent_edges(idx, self.direction) {
                let target = edge.source_or_target(self.direction);
                self.visit(target);
            }
        }
        next
    }
}

pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F)
    where F: FnMut(EdgeIndex) -> bool
{
    let mut i = 0;
    let n = max_edge_index.0;
    while i < n {
        if !f(EdgeIndex(i)) {
            return;
        }
        i += 1;
    }
}

impl<E> Edge<E> {
    pub fn source(&self) -> NodeIndex {
        self.source
    }

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

    pub fn source_or_target(&self, direction: Direction) -> NodeIndex {
        if direction == OUTGOING {
            self.target
        } else {
            self.source
        }
    }
}
<commit_msg>Change Make comment into doc comment  on Graph::iterate_until_fixed_point<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A graph module for use in dataflow, region resolution, and elsewhere.
//!
//! # Interface details
//!
//! You customize the graph by specifying a "node data" type `N` and an
//! "edge data" type `E`. You can then later gain access (mutable or
//! immutable) to these "user-data" bits. Currently, you can only add
//! nodes or edges to the graph. You cannot remove or modify them once
//! added. This could be changed if we have a need.
//!
//! # Implementation details
//!
//! The main tricky thing about this code is the way that edges are
//! stored. The edges are stored in a central array, but they are also
//! threaded onto two linked lists for each node, one for incoming edges
//! and one for outgoing edges. Note that every edge is a member of some
//! incoming list and some outgoing list.  Basically you can load the
//! first index of the linked list from the node data structures (the
//! field `first_edge`) and then, for each edge, load the next index from
//! the field `next_edge`). Each of those fields is an array that should
//! be indexed by the direction (see the type `Direction`).

use bitvec::BitVector;
use std::fmt::{Formatter, Error, Debug};
use std::usize;
use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};

#[cfg(test)]
mod tests;

pub struct Graph<N, E> {
    nodes: SnapshotVec<Node<N>>,
    edges: SnapshotVec<Edge<E>>,
}

pub struct Node<N> {
    first_edge: [EdgeIndex; 2], // see module comment
    pub data: N,
}

pub struct Edge<E> {
    next_edge: [EdgeIndex; 2], // see module comment
    source: NodeIndex,
    target: NodeIndex,
    pub data: E,
}

impl<N> SnapshotVecDelegate for Node<N> {
    type Value = Node<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Node<N>>, _: ()) {}
}

impl<N> SnapshotVecDelegate for Edge<N> {
    type Value = Edge<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Edge<N>>, _: ()) {}
}

impl<E: Debug> Debug for Edge<E> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f,
               "Edge {{ next_edge: [{:?}, {:?}], source: {:?}, target: {:?}, data: {:?} }}",
               self.next_edge[0],
               self.next_edge[1],
               self.source,
               self.target,
               self.data)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct NodeIndex(pub usize);

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct EdgeIndex(pub usize);

pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX);

// Use a private field here to guarantee no more instances are created:
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Direction {
    repr: usize,
}

pub const OUTGOING: Direction = Direction { repr: 0 };

pub const INCOMING: Direction = Direction { repr: 1 };

impl NodeIndex {
    /// Returns unique id (unique with respect to the graph holding associated node).
    pub fn node_id(&self) -> usize {
        self.0
    }
}

impl EdgeIndex {
    /// Returns unique id (unique with respect to the graph holding associated edge).
    pub fn edge_id(&self) -> usize {
        self.0
    }
}

impl<N: Debug, E: Debug> Graph<N, E> {
    pub fn new() -> Graph<N, E> {
        Graph {
            nodes: SnapshotVec::new(),
            edges: SnapshotVec::new(),
        }
    }

    // # Simple accessors

    #[inline]
    pub fn all_nodes(&self) -> &[Node<N>] {
        &self.nodes
    }

    #[inline]
    pub fn len_nodes(&self) -> usize {
        self.nodes.len()
    }

    #[inline]
    pub fn all_edges(&self) -> &[Edge<E>] {
        &self.edges
    }

    #[inline]
    pub fn len_edges(&self) -> usize {
        self.edges.len()
    }

    // # Node construction

    pub fn next_node_index(&self) -> NodeIndex {
        NodeIndex(self.nodes.len())
    }

    pub fn add_node(&mut self, data: N) -> NodeIndex {
        let idx = self.next_node_index();
        self.nodes.push(Node {
            first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX],
            data: data,
        });
        idx
    }

    pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
        &mut self.nodes[idx.0].data
    }

    pub fn node_data(&self, idx: NodeIndex) -> &N {
        &self.nodes[idx.0].data
    }

    pub fn node(&self, idx: NodeIndex) -> &Node<N> {
        &self.nodes[idx.0]
    }

    // # Edge construction and queries

    pub fn next_edge_index(&self) -> EdgeIndex {
        EdgeIndex(self.edges.len())
    }

    pub fn add_edge(&mut self, source: NodeIndex, target: NodeIndex, data: E) -> EdgeIndex {
        debug!("graph: add_edge({:?}, {:?}, {:?})", source, target, data);

        let idx = self.next_edge_index();

        // read current first of the list of edges from each node
        let source_first = self.nodes[source.0].first_edge[OUTGOING.repr];
        let target_first = self.nodes[target.0].first_edge[INCOMING.repr];

        // create the new edge, with the previous firsts from each node
        // as the next pointers
        self.edges.push(Edge {
            next_edge: [source_first, target_first],
            source: source,
            target: target,
            data: data,
        });

        // adjust the firsts for each node target be the next object.
        self.nodes[source.0].first_edge[OUTGOING.repr] = idx;
        self.nodes[target.0].first_edge[INCOMING.repr] = idx;

        return idx;
    }

    pub fn mut_edge_data(&mut self, idx: EdgeIndex) -> &mut E {
        &mut self.edges[idx.0].data
    }

    pub fn edge_data(&self, idx: EdgeIndex) -> &E {
        &self.edges[idx.0].data
    }

    pub fn edge(&self, idx: EdgeIndex) -> &Edge<E> {
        &self.edges[idx.0]
    }

    pub fn first_adjacent(&self, node: NodeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the index of the first edge adjacent to `node`.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.nodes[node.0].first_edge[dir.repr]
    }

    pub fn next_adjacent(&self, edge: EdgeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the next edge in a given direction.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.edges[edge.0].next_edge[dir.repr]
    }

    // # Iterating over nodes, edges

    pub fn all_nodes_enumerated(&self) -> Nodes<N> {
        Nodes {
            iter: self.nodes.iter().enumerate()
        }
    }

    pub fn all_edges_enumerated(&self) -> Edges<E> {
        Edges {
            iter: self.edges.iter().enumerate()
        }
    }

    pub fn each_node<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(NodeIndex, &'a Node<N>) -> bool
    {
        //! Iterates over all edges defined in the graph.
        self.all_nodes_enumerated().all(|(node_idx, node)| f(node_idx, node))
    }

    pub fn each_edge<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(EdgeIndex, &'a Edge<E>) -> bool
    {
        //! Iterates over all edges defined in the graph
        self.all_edges_enumerated().all(|(edge_idx, edge)| f(edge_idx, edge))
    }

    pub fn outgoing_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, OUTGOING)
    }

    pub fn incoming_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, INCOMING)
    }

    pub fn adjacent_edges(&self, source: NodeIndex, direction: Direction) -> AdjacentEdges<N, E> {
        let first_edge = self.node(source).first_edge[direction.repr];
        AdjacentEdges {
            graph: self,
            direction: direction,
            next: first_edge,
        }
    }

    pub fn successor_nodes(&self, source: NodeIndex) -> AdjacentTargets<N, E> {
        self.outgoing_edges(source).targets()
    }

    pub fn predecessor_nodes(&self, target: NodeIndex) -> AdjacentSources<N, E> {
        self.incoming_edges(target).sources()
    }

    /// A common use for graphs in our compiler is to perform
    /// fixed-point iteration. In this case, each edge represents a
    /// constraint, and the nodes themselves are associated with
    /// variables or other bitsets. This method facilitates such a
    /// computation.
    pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F)
        where F: FnMut(usize, EdgeIndex, &'a Edge<E>) -> bool
    {
        let mut iteration = 0;
        let mut changed = true;
        while changed {
            changed = false;
            iteration += 1;
            for (edge_index, edge) in self.all_edges_enumerated() {
                changed |= op(iteration, edge_index, edge);
            }
        }
    }

    pub fn depth_traverse<'a>(&'a self,
                              start: NodeIndex,
                              direction: Direction)
                              -> DepthFirstTraversal<'a, N, E> {
        DepthFirstTraversal::with_start_node(self, start, direction)
    }
}

// # Iterators

pub struct Nodes<'g, N>
    where N: 'g,
{
    iter: ::std::iter::Enumerate<::std::slice::Iter<'g, Node<N>>>
}

impl<'g, N: Debug> Iterator for Nodes<'g, N> {
    type Item = (NodeIndex, &'g Node<N>);

    fn next(&mut self) -> Option<(NodeIndex, &'g Node<N>)> {
        self.iter.next().map(|(idx, n)| (NodeIndex(idx), n))
    }
}

pub struct Edges<'g, E>
    where E: 'g,
{
    iter: ::std::iter::Enumerate<::std::slice::Iter<'g, Edge<E>>>
}

impl<'g, E: Debug> Iterator for Edges<'g, E> {
    type Item = (EdgeIndex, &'g Edge<E>);

    fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> {
        self.iter.next().map(|(idx, e)| (EdgeIndex(idx), e))
    }
}

pub struct AdjacentEdges<'g, N, E>
    where N: 'g,
          E: 'g
{
    graph: &'g Graph<N, E>,
    direction: Direction,
    next: EdgeIndex,
}

impl<'g, N, E> AdjacentEdges<'g, N, E> {
    fn targets(self) -> AdjacentTargets<'g, N, E> {
        AdjacentTargets { edges: self }
    }

    fn sources(self) -> AdjacentSources<'g, N, E> {
        AdjacentSources { edges: self }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
    type Item = (EdgeIndex, &'g Edge<E>);

    fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> {
        let edge_index = self.next;
        if edge_index == INVALID_EDGE_INDEX {
            return None;
        }

        let edge = self.graph.edge(edge_index);
        self.next = edge.next_edge[self.direction.repr];
        Some((edge_index, edge))
    }
}

pub struct AdjacentTargets<'g, N, E>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentTargets<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.target)
    }
}

pub struct AdjacentSources<'g, N, E>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentSources<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.source)
    }
}

pub struct DepthFirstTraversal<'g, N, E>
    where N: 'g,
          E: 'g
{
    graph: &'g Graph<N, E>,
    stack: Vec<NodeIndex>,
    visited: BitVector,
    direction: Direction,
}

impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
    pub fn new(graph: &'g Graph<N, E>, direction: Direction) -> Self {
        let visited = BitVector::new(graph.len_nodes());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![],
            visited: visited,
            direction: direction,
        }
    }

    pub fn with_start_node(graph: &'g Graph<N, E>,
                           start_node: NodeIndex,
                           direction: Direction)
                           -> Self {
        let mut visited = BitVector::new(graph.len_nodes());
        visited.insert(start_node.node_id());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![start_node],
            visited: visited,
            direction: direction,
        }
    }

    pub fn reset(&mut self, start_node: NodeIndex) {
        self.stack.truncate(0);
        self.stack.push(start_node);
        self.visited.clear();
        self.visited.insert(start_node.node_id());
    }

    fn visit(&mut self, node: NodeIndex) {
        if self.visited.insert(node.node_id()) {
            self.stack.push(node);
        }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        let next = self.stack.pop();
        if let Some(idx) = next {
            for (_, edge) in self.graph.adjacent_edges(idx, self.direction) {
                let target = edge.source_or_target(self.direction);
                self.visit(target);
            }
        }
        next
    }
}

pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F)
    where F: FnMut(EdgeIndex) -> bool
{
    let mut i = 0;
    let n = max_edge_index.0;
    while i < n {
        if !f(EdgeIndex(i)) {
            return;
        }
        i += 1;
    }
}

impl<E> Edge<E> {
    pub fn source(&self) -> NodeIndex {
        self.source
    }

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

    pub fn source_or_target(&self, direction: Direction) -> NodeIndex {
        if direction == OUTGOING {
            self.target
        } else {
            self.source
        }
    }
}
<|endoftext|>


<commit_before>use time;
use std::mem;
use std::num::{Float};
use image::{GenericImage, SubImage, Pixel};
use image::{ImageBuffer, Rgba};
use image;
use glutin;
use glium::{self, DisplayBuild};
use util::{self, AtlasBuilder, Atlas, AtlasItem, V2, Rect, Rgb, Color};
use event::{Event, MouseButton};
use renderer::{Renderer, Vertex};
use scancode;

pub static FONT_W: u32 = 8;
pub static FONT_H: u32 = 8;

/// The first font image in the atlas image set.
static FONT_IDX: usize = 0;

/// Image index of the solid color texture block.
static SOLID_IDX: usize = 96;

pub struct CanvasBuilder {
    title: String,
    dim: V2<i32>,
    frame_interval: Option<f64>,
    builder: AtlasBuilder,
}

/// Toplevel graphics drawing and input reading context.
impl CanvasBuilder {
    pub fn new() -> CanvasBuilder {
        let mut ret = CanvasBuilder {
            title: "window".to_string(),
            dim: V2(640, 360),
            frame_interval: None,
            builder: AtlasBuilder::new(),
        };
        ret.init_font();
        ret.init_solid();
        ret
    }

    pub fn set_title(mut self, title: &str) -> CanvasBuilder {
        self.title = title.to_string();
        self
    }

    /// Set the frame rate.
    pub fn set_frame_interval(mut self, interval_s: f64) -> CanvasBuilder {
        assert!(interval_s > 0.00001);
        self.frame_interval = Some(interval_s);
        self
    }

    /// Set the resolution.
    pub fn set_dim(mut self, dim: V2<i32>) -> CanvasBuilder {
        self.dim = dim;
        self
    }

    pub fn add_image<P: Pixel<u8> + 'static, I: GenericImage<P>>(
        &mut self, offset: V2<i32>, image: I) -> Image {
        Image(self.builder.push(offset, image))
    }

    /// Start running the engine, return an event iteration.
    pub fn run(&mut self) -> Canvas {
        Canvas::new(
            self.dim,
            self.title.as_slice(),
            self.frame_interval,
            Atlas::new(&self.builder))
    }

    /// Load the default font into the texture atlas.
    fn init_font(&mut self) {
        let mut font_sheet = util::color_key(
            &image::load_from_memory(include_bytes!("../assets/font.png")).unwrap(),
            &Rgb::new(0x80u8, 0x80u8, 0x80u8));
        for i in 0..96 {
            let x = 8u32 * (i % 16u32);
            let y = 8u32 * (i / 16u32);
            let Image(idx) = self.add_image(V2(0, -8), SubImage::new(&mut font_sheet, x, y, 8, 8));
            assert!(idx - i as usize == FONT_IDX);
        }
    }

    /// Load a solid color element into the texture atlas.
    fn init_solid(&mut self) {
        let image: ImageBuffer<Vec<u8>, u8, Rgba<u8>> = ImageBuffer::from_fn(1, 1, Box::new(|&: _, _| Rgba([0xffu8, 0xffu8, 0xffu8, 0xffu8])));
        let Image(idx) = self.add_image(V2(0, 0), image);
        assert!(idx == SOLID_IDX);
    }
}

/// Interface to render to a live display.
pub struct Canvas {
    display: glium::Display,
    events: Vec<glutin::Event>,
    renderer: Renderer,

    atlas: Atlas,

    state: State,
    frame_interval: Option<f64>,
    last_render_time: f64,
    resolution: V2<i32>,
    window_resolution: V2<i32>,

    vertices: Vec<Vertex>,
    indices: Vec<u16>,

    /// Time in seconds it took to render the last frame.
    pub render_duration: f64,
}

#[derive(PartialEq)]
enum State {
    Normal,
    EndFrame,
}

impl Canvas {
    fn new(
        dim: V2<i32>,
        title: &str,
        frame_interval: Option<f64>,
        atlas: Atlas) -> Canvas {

        let display = glutin::WindowBuilder::new()
            .with_title(title.to_string())
            .with_dimensions(dim.0 as u32, dim.1 as u32)
            .build_glium().unwrap();

        let (w, h) = display.get_framebuffer_dimensions();

        let tex_image = image::imageops::flip_vertical(&atlas.image);
        let renderer = Renderer::new(&display, tex_image);

        Canvas {
            display: display,
            events: Vec::new(),
            renderer: renderer,

            atlas: atlas,

            state: State::Normal,
            frame_interval: frame_interval,
            last_render_time: time::precise_time_s(),
            resolution: dim,
            window_resolution: V2(w as i32, h as i32),

            vertices: Vec::new(),
            indices: Vec::new(),

            render_duration: 0.1f64,
        }
    }

    /// Clear the screen.
    pub fn clear(&mut self) {
        // TODO: use the color.
        self.vertices.clear();
        self.indices.clear();
    }

    /// Transform screen coordinates from the scaled-up window into
    /// pixel-perfect coordinates of the actual graphics.
    fn screen_to_pixel(&self, V2(sx, sy): V2<i32>) -> V2<i32> {
        let Rect(V2(rx, ry), V2(rw, rh)) = pixel_perfect(self.resolution, self.window_resolution);

        V2(((sx - rx) as f32 * self.resolution.0 as f32 / rw as f32) as i32,
           ((sy - ry) as f32 * self.resolution.1 as f32 / rh as f32) as i32)
    }

    fn window_to_device(&self, window_pos: V2<f32>, z: f32) -> [f32; 3] {
        let V2(w, h) = self.window_resolution;
        let Rect(V2(rx, ry), V2(rw, _)) = pixel_perfect(self.resolution, self.window_resolution);
        let zoom = (rw as f32) / (self.resolution.0 as f32);
        [-1.0 + (2.0 * (rx as f32 + window_pos.0 * zoom) / w as f32),
          1.0 - (2.0 * (ry as f32 + window_pos.1 * zoom) / h as f32),
         z]
    }

    /// Add a vertex to the geometry data of the current frame.
    pub fn push_vertex<C: Color, C2: Color>(&mut self, pos: V2<f32>, layer: f32, tex_coord: V2<f32>,
                                 color: &C, back_color: &C2) {
        let pos = self.window_to_device(pos, layer);

        self.vertices.push(Vertex {
            pos: pos,
            tex_coord: [tex_coord.0, tex_coord.1],
            color: color.to_rgba(),
            back_color: back_color.to_rgba(),
        });
    }

    /// Return the current vertex count, important for determining the indices
    /// for newly inserted vertices.
    pub fn num_vertices(&self) -> u16 { self.vertices.len() as u16 }

    /// Add a triangle defined by index values into the list of vertices
    /// inserted with push_vertex.
    pub fn push_triangle(&mut self, p0: u16, p1: u16, p2: u16) {
        self.indices.push(p0);
        self.indices.push(p1);
        self.indices.push(p2);
    }

    /// Return the image corresponding to a char in the built-in font.
    pub fn font_image(&self, c: char) -> Option<Image> {
        let idx = c as usize;
        // Hardcoded limiting of the font to printable ASCII.
        if idx >= 32 && idx < 128 {
            Some(Image((idx - 32) as usize + FONT_IDX))
        } else {
            None
        }
    }

    /// Return a texture coordinate to a #FFFFFFFF texel for solid color
    /// graphics.
    pub fn solid_tex_coord(&self) -> V2<f32> { self.atlas.items[SOLID_IDX].tex.0 }

    pub fn image_data<'a>(&'a self, Image(idx): Image) -> &'a AtlasItem {
        &self.atlas.items[idx]
    }
}

impl<'a> Iterator for Canvas {
    type Item=Event<'a>;

    fn next(&mut self) -> Option<Event<'a>> {
        // After a render event, control will return here on a new
        // iter call. Do post-render work here.
        if self.state == State::EndFrame {
            self.state = State::Normal;

            let mut target = self.display.draw();

            // Move out the accumulated geometry data.
            let vertices = mem::replace(&mut self.vertices, Vec::new());
            let indices = mem::replace(&mut self.indices, Vec::new());
            self.renderer.draw(&self.display, &mut target, vertices, indices);

            target.finish();
        }

        loop {
            self.events.push_all(self.display.poll_events().as_slice());

            if !self.events.is_empty() {
                match self.events.remove(0) {
                    glutin::Event::ReceivedCharacter(ch) => {
                        return Some(Event::Char(ch));
                    }
                    glutin::Event::KeyboardInput(action, scan, _vko) => {
                        if (scan as usize) < scancode::MAP.len() {
                            if let Some(key) = scancode::MAP[scan as usize] {
                                return Some(if action == glutin::ElementState::Pressed {
                                    Event::KeyPressed(key)
                                }
                                else {
                                    Event::KeyReleased(key)
                                });
                            }
                        }
                    }
                    glutin::Event::MouseMoved((x, y)) => {
                        let pixel_pos = self.screen_to_pixel(V2(x, y));
                        return Some(Event::MouseMoved((pixel_pos.0, pixel_pos.1)));
                    }
                    glutin::Event::MouseWheel(x) => {
                        return Some(Event::MouseWheel(x));
                    }
                    glutin::Event::MouseInput(state, button) => {
                        let button = match button {
                            glutin::MouseButton::LeftMouseButton => MouseButton::Left,
                            glutin::MouseButton::RightMouseButton => MouseButton::Right,
                            glutin::MouseButton::MiddleMouseButton => MouseButton::Middle,
                            glutin::MouseButton::OtherMouseButton(x) => MouseButton::Other(x),
                        };
                        match state {
                            glutin::ElementState::Pressed => {
                                return Some(Event::MousePressed(button));
                            }
                            glutin::ElementState::Released => {
                                return Some(Event::MouseReleased(button));
                            }
                        }
                    }
                    glutin::Event::Focused(b) => {
                        return Some(Event::FocusChanged(b));
                    }
                    glutin::Event::Closed => {
                        return None;
                    }
                    _ => ()
                }
            }

            let t = time::precise_time_s();
            if self.frame_interval.map_or(true,
                |x| t - self.last_render_time >= x) {
                let delta = t - self.last_render_time;
                let sensitivity = 0.25f64;
                self.render_duration = (1f64 - sensitivity) * self.render_duration + sensitivity * delta;

                self.last_render_time = t;

                // Time to render, must return a handle to self.
                // XXX: Need unsafe hackery to get around lifetimes check.
                self.state = State::EndFrame;

                let (w, h) = self.display.get_framebuffer_dimensions();
                self.window_resolution = V2(w as i32, h as i32);

                unsafe {
                    return Some(Event::Render(mem::transmute(self)))
                }
            }
        }
    }
}

/// Drawable images stored in the Canvas.
#[derive(Copy, Clone, PartialEq)]
pub struct Image(usize);

/// A pixel perfect centered and scaled rectangle of resolution dim in a
/// window of size area.
fn pixel_perfect(canvas: V2<i32>, window: V2<i32>) -> Rect<i32> {
    let mut scale = (window.0 as f32 / canvas.0 as f32)
        .min(window.1 as f32 / canvas.1 as f32);

    if scale > 1.0 {
        // Snap to pixel scale if more than 1 window pixel per canvas pixel.
        scale = scale.floor();
    }

    let dim = V2((scale * canvas.0 as f32) as i32, (scale * canvas.1 as f32) as i32);
    let offset = (window - dim) / 2;
    Rect(offset, dim)
}
<commit_msg>Inline transforms that get called all the time<commit_after>use time;
use std::mem;
use std::num::{Float};
use image::{GenericImage, SubImage, Pixel};
use image::{ImageBuffer, Rgba};
use image;
use glutin;
use glium::{self, DisplayBuild};
use util::{self, AtlasBuilder, Atlas, AtlasItem, V2, Rect, Rgb, Color};
use event::{Event, MouseButton};
use renderer::{Renderer, Vertex};
use scancode;

pub static FONT_W: u32 = 8;
pub static FONT_H: u32 = 8;

/// The first font image in the atlas image set.
static FONT_IDX: usize = 0;

/// Image index of the solid color texture block.
static SOLID_IDX: usize = 96;

pub struct CanvasBuilder {
    title: String,
    dim: V2<i32>,
    frame_interval: Option<f64>,
    builder: AtlasBuilder,
}

/// Toplevel graphics drawing and input reading context.
impl CanvasBuilder {
    pub fn new() -> CanvasBuilder {
        let mut ret = CanvasBuilder {
            title: "window".to_string(),
            dim: V2(640, 360),
            frame_interval: None,
            builder: AtlasBuilder::new(),
        };
        ret.init_font();
        ret.init_solid();
        ret
    }

    pub fn set_title(mut self, title: &str) -> CanvasBuilder {
        self.title = title.to_string();
        self
    }

    /// Set the frame rate.
    pub fn set_frame_interval(mut self, interval_s: f64) -> CanvasBuilder {
        assert!(interval_s > 0.00001);
        self.frame_interval = Some(interval_s);
        self
    }

    /// Set the resolution.
    pub fn set_dim(mut self, dim: V2<i32>) -> CanvasBuilder {
        self.dim = dim;
        self
    }

    pub fn add_image<P: Pixel<u8> + 'static, I: GenericImage<P>>(
        &mut self, offset: V2<i32>, image: I) -> Image {
        Image(self.builder.push(offset, image))
    }

    /// Start running the engine, return an event iteration.
    pub fn run(&mut self) -> Canvas {
        Canvas::new(
            self.dim,
            self.title.as_slice(),
            self.frame_interval,
            Atlas::new(&self.builder))
    }

    /// Load the default font into the texture atlas.
    fn init_font(&mut self) {
        let mut font_sheet = util::color_key(
            &image::load_from_memory(include_bytes!("../assets/font.png")).unwrap(),
            &Rgb::new(0x80u8, 0x80u8, 0x80u8));
        for i in 0..96 {
            let x = 8u32 * (i % 16u32);
            let y = 8u32 * (i / 16u32);
            let Image(idx) = self.add_image(V2(0, -8), SubImage::new(&mut font_sheet, x, y, 8, 8));
            assert!(idx - i as usize == FONT_IDX);
        }
    }

    /// Load a solid color element into the texture atlas.
    fn init_solid(&mut self) {
        let image: ImageBuffer<Vec<u8>, u8, Rgba<u8>> = ImageBuffer::from_fn(1, 1, Box::new(|&: _, _| Rgba([0xffu8, 0xffu8, 0xffu8, 0xffu8])));
        let Image(idx) = self.add_image(V2(0, 0), image);
        assert!(idx == SOLID_IDX);
    }
}

/// Interface to render to a live display.
pub struct Canvas {
    display: glium::Display,
    events: Vec<glutin::Event>,
    renderer: Renderer,

    atlas: Atlas,

    state: State,
    frame_interval: Option<f64>,
    last_render_time: f64,
    resolution: V2<i32>,
    window_resolution: V2<i32>,

    vertices: Vec<Vertex>,
    indices: Vec<u16>,

    /// Time in seconds it took to render the last frame.
    pub render_duration: f64,
}

#[derive(PartialEq)]
enum State {
    Normal,
    EndFrame,
}

impl Canvas {
    fn new(
        dim: V2<i32>,
        title: &str,
        frame_interval: Option<f64>,
        atlas: Atlas) -> Canvas {

        let display = glutin::WindowBuilder::new()
            .with_title(title.to_string())
            .with_dimensions(dim.0 as u32, dim.1 as u32)
            .build_glium().unwrap();

        let (w, h) = display.get_framebuffer_dimensions();

        let tex_image = image::imageops::flip_vertical(&atlas.image);
        let renderer = Renderer::new(&display, tex_image);

        Canvas {
            display: display,
            events: Vec::new(),
            renderer: renderer,

            atlas: atlas,

            state: State::Normal,
            frame_interval: frame_interval,
            last_render_time: time::precise_time_s(),
            resolution: dim,
            window_resolution: V2(w as i32, h as i32),

            vertices: Vec::new(),
            indices: Vec::new(),

            render_duration: 0.1f64,
        }
    }

    /// Clear the screen.
    pub fn clear(&mut self) {
        // TODO: use the color.
        self.vertices.clear();
        self.indices.clear();
    }

    /// Transform screen coordinates from the scaled-up window into
    /// pixel-perfect coordinates of the actual graphics.
    fn screen_to_pixel(&self, V2(sx, sy): V2<i32>) -> V2<i32> {
        let Rect(V2(rx, ry), V2(rw, rh)) = pixel_perfect(self.resolution, self.window_resolution);

        V2(((sx - rx) as f32 * self.resolution.0 as f32 / rw as f32) as i32,
           ((sy - ry) as f32 * self.resolution.1 as f32 / rh as f32) as i32)
    }

    #[inline(always)]
    fn window_to_device(&self, window_pos: V2<f32>, z: f32) -> [f32; 3] {
        let V2(w, h) = self.window_resolution;
        let Rect(V2(rx, ry), V2(rw, _)) = pixel_perfect(self.resolution, self.window_resolution);
        let zoom = (rw as f32) / (self.resolution.0 as f32);
        [-1.0 + (2.0 * (rx as f32 + window_pos.0 * zoom) / w as f32),
          1.0 - (2.0 * (ry as f32 + window_pos.1 * zoom) / h as f32),
         z]
    }

    /// Add a vertex to the geometry data of the current frame.
    pub fn push_vertex<C: Color, C2: Color>(&mut self, pos: V2<f32>, layer: f32, tex_coord: V2<f32>,
                                 color: &C, back_color: &C2) {
        let pos = self.window_to_device(pos, layer);

        self.vertices.push(Vertex {
            pos: pos,
            tex_coord: [tex_coord.0, tex_coord.1],
            color: color.to_rgba(),
            back_color: back_color.to_rgba(),
        });
    }

    /// Return the current vertex count, important for determining the indices
    /// for newly inserted vertices.
    pub fn num_vertices(&self) -> u16 { self.vertices.len() as u16 }

    /// Add a triangle defined by index values into the list of vertices
    /// inserted with push_vertex.
    pub fn push_triangle(&mut self, p0: u16, p1: u16, p2: u16) {
        self.indices.push(p0);
        self.indices.push(p1);
        self.indices.push(p2);
    }

    /// Return the image corresponding to a char in the built-in font.
    pub fn font_image(&self, c: char) -> Option<Image> {
        let idx = c as usize;
        // Hardcoded limiting of the font to printable ASCII.
        if idx >= 32 && idx < 128 {
            Some(Image((idx - 32) as usize + FONT_IDX))
        } else {
            None
        }
    }

    /// Return a texture coordinate to a #FFFFFFFF texel for solid color
    /// graphics.
    pub fn solid_tex_coord(&self) -> V2<f32> { self.atlas.items[SOLID_IDX].tex.0 }

    pub fn image_data<'a>(&'a self, Image(idx): Image) -> &'a AtlasItem {
        &self.atlas.items[idx]
    }
}

impl<'a> Iterator for Canvas {
    type Item=Event<'a>;

    fn next(&mut self) -> Option<Event<'a>> {
        // After a render event, control will return here on a new
        // iter call. Do post-render work here.
        if self.state == State::EndFrame {
            self.state = State::Normal;

            let mut target = self.display.draw();

            // Move out the accumulated geometry data.
            let vertices = mem::replace(&mut self.vertices, Vec::new());
            let indices = mem::replace(&mut self.indices, Vec::new());
            self.renderer.draw(&self.display, &mut target, vertices, indices);

            target.finish();
        }

        loop {
            self.events.push_all(self.display.poll_events().as_slice());

            if !self.events.is_empty() {
                match self.events.remove(0) {
                    glutin::Event::ReceivedCharacter(ch) => {
                        return Some(Event::Char(ch));
                    }
                    glutin::Event::KeyboardInput(action, scan, _vko) => {
                        if (scan as usize) < scancode::MAP.len() {
                            if let Some(key) = scancode::MAP[scan as usize] {
                                return Some(if action == glutin::ElementState::Pressed {
                                    Event::KeyPressed(key)
                                }
                                else {
                                    Event::KeyReleased(key)
                                });
                            }
                        }
                    }
                    glutin::Event::MouseMoved((x, y)) => {
                        let pixel_pos = self.screen_to_pixel(V2(x, y));
                        return Some(Event::MouseMoved((pixel_pos.0, pixel_pos.1)));
                    }
                    glutin::Event::MouseWheel(x) => {
                        return Some(Event::MouseWheel(x));
                    }
                    glutin::Event::MouseInput(state, button) => {
                        let button = match button {
                            glutin::MouseButton::LeftMouseButton => MouseButton::Left,
                            glutin::MouseButton::RightMouseButton => MouseButton::Right,
                            glutin::MouseButton::MiddleMouseButton => MouseButton::Middle,
                            glutin::MouseButton::OtherMouseButton(x) => MouseButton::Other(x),
                        };
                        match state {
                            glutin::ElementState::Pressed => {
                                return Some(Event::MousePressed(button));
                            }
                            glutin::ElementState::Released => {
                                return Some(Event::MouseReleased(button));
                            }
                        }
                    }
                    glutin::Event::Focused(b) => {
                        return Some(Event::FocusChanged(b));
                    }
                    glutin::Event::Closed => {
                        return None;
                    }
                    _ => ()
                }
            }

            let t = time::precise_time_s();
            if self.frame_interval.map_or(true,
                |x| t - self.last_render_time >= x) {
                let delta = t - self.last_render_time;
                let sensitivity = 0.25f64;
                self.render_duration = (1f64 - sensitivity) * self.render_duration + sensitivity * delta;

                self.last_render_time = t;

                // Time to render, must return a handle to self.
                // XXX: Need unsafe hackery to get around lifetimes check.
                self.state = State::EndFrame;

                let (w, h) = self.display.get_framebuffer_dimensions();
                self.window_resolution = V2(w as i32, h as i32);

                unsafe {
                    return Some(Event::Render(mem::transmute(self)))
                }
            }
        }
    }
}

/// Drawable images stored in the Canvas.
#[derive(Copy, Clone, PartialEq)]
pub struct Image(usize);

/// A pixel perfect centered and scaled rectangle of resolution dim in a
/// window of size area.
#[inline(always)]
fn pixel_perfect(canvas: V2<i32>, window: V2<i32>) -> Rect<i32> {
    let mut scale = (window.0 as f32 / canvas.0 as f32)
        .min(window.1 as f32 / canvas.1 as f32);

    if scale > 1.0 {
        // Snap to pixel scale if more than 1 window pixel per canvas pixel.
        scale = scale.floor();
    }

    let dim = V2((scale * canvas.0 as f32) as i32, (scale * canvas.1 as f32) as i32);
    let offset = (window - dim) / 2;
    Rect(offset, dim)
}
<|endoftext|>


<commit_before>
mod proof;

use proof::{ Proof, Lemma, Positioned };
pub use self::proof::{ ProofProto, LemmaProto };

use protobuf::Message;
use protobuf::error::ProtobufResult;
use protobuf::core::parse_from_bytes;

impl <D, T> Proof<D, T> {

    /// Constructs a `Proof` struct from its Protobuf representation.
    pub fn from_protobuf(digest: D, proto: ProofProto) -> Option<Self>
        where T: From<Vec<u8>>
    {
        proto.into_proof(digest)
    }

    /// Encode this `Proof` to its Protobuf representation.
    pub fn into_protobuf(self) -> ProofProto
        where T: Into<Vec<u8>>
    {
        ProofProto::from_proof(self)
    }

    /// Parse a `Proof` from its Protobuf binary representation.
    pub fn parse_from_bytes(bytes: &[u8], digest: D) -> ProtobufResult<Option<Proof<D, T>>>
        where T: From<Vec<u8>>
    {
        parse_from_bytes::<ProofProto>(bytes).map(|proto| proto.into_proof(digest))
    }

    /// Serialize this `Proof` with Protobuf.
    pub fn write_to_bytes(self) -> ProtobufResult<Vec<u8>> where T: Into<Vec<u8>>  {
        self.into_protobuf().write_to_bytes()
    }

}

impl ProofProto {

    pub fn from_proof<D, T>(proof: Proof<D, T>) -> Self
        where T: Into<Vec<u8>>
    {
        let mut proto = Self::new();

        match proof {
            Proof { root_hash, lemma, value, .. } => {
                proto.set_root_hash(root_hash);
                proto.set_lemma(LemmaProto::from_lemma(lemma));
                proto.set_value(value.into());
            }
        }

        proto
    }

    pub fn into_proof<D, T>(mut self, digest: D) -> Option<Proof<D, T>>
        where T: From<Vec<u8>>
    {
        if !self.has_root_hash() || !self.has_lemma() {
            return None;
        }

        self.take_lemma().into_lemma().map(|lemma| {
            Proof::new(
                digest,
                self.take_root_hash(),
                lemma,
                self.take_value().into()
            )
        })
    }

}

impl LemmaProto {

    pub fn from_lemma(lemma: Lemma) -> Self {
        let mut proto = Self::new();

        match lemma {
            Lemma { node_hash, sibling_hash, sub_lemma } => {
                proto.set_node_hash(node_hash);

                if let Some(sub_proto) = sub_lemma.map(|l| Self::from_lemma(*l)) {
                    proto.set_sub_lemma(sub_proto);
                }

                match sibling_hash {
                    Some(Positioned::Left(hash)) =>
                        proto.set_left_sibling_hash(hash),

                    Some(Positioned::Right(hash)) =>
                        proto.set_right_sibling_hash(hash),

                    None => {}
                }
            }
        }

        proto
    }

    pub fn into_lemma(mut self) -> Option<Lemma> {
        if !self.has_node_hash() {
            return None;
        }

        let node_hash = self.take_node_hash();

        let sibling_hash =
            if self.has_left_sibling_hash() {
                Some(Positioned::Left(self.take_left_sibling_hash()))
            }
            else if self.has_right_sibling_hash() {
                Some(Positioned::Left(self.take_right_sibling_hash()))
            }
            else {
                None
            };

        if self.has_sub_lemma() {
            // If a `sub_lemma` is present is the Protobuf,
            // then we expect it to unserialize to a valid `Lemma`,
            // otherwise we return `None`
            self.take_sub_lemma().into_lemma().map(|sub_lemma| {
                Lemma {
                    node_hash: node_hash,
                    sibling_hash: sibling_hash,
                    sub_lemma: Some(Box::new(sub_lemma))
                }
            })
        }
        else {
            // We might very well not have a sub_lemma,
            // in which case we just set it to `None`,
            // but still return a potentially valid `Lemma`.
            Some(Lemma {
                node_hash: node_hash,
                sibling_hash: sibling_hash,
                sub_lemma: None
            })
        }
    }

}

<commit_msg>Fix a bug where Lemma would be unserialized incorrectly.<commit_after>
mod proof;

use proof::{ Proof, Lemma, Positioned };
pub use self::proof::{ ProofProto, LemmaProto };

use protobuf::Message;
use protobuf::error::ProtobufResult;
use protobuf::core::parse_from_bytes;

impl <D, T> Proof<D, T> {

    /// Constructs a `Proof` struct from its Protobuf representation.
    pub fn from_protobuf(digest: D, proto: ProofProto) -> Option<Self>
        where T: From<Vec<u8>>
    {
        proto.into_proof(digest)
    }

    /// Encode this `Proof` to its Protobuf representation.
    pub fn into_protobuf(self) -> ProofProto
        where T: Into<Vec<u8>>
    {
        ProofProto::from_proof(self)
    }

    /// Parse a `Proof` from its Protobuf binary representation.
    pub fn parse_from_bytes(bytes: &[u8], digest: D) -> ProtobufResult<Option<Proof<D, T>>>
        where T: From<Vec<u8>>
    {
        parse_from_bytes::<ProofProto>(bytes).map(|proto| proto.into_proof(digest))
    }

    /// Serialize this `Proof` with Protobuf.
    pub fn write_to_bytes(self) -> ProtobufResult<Vec<u8>> where T: Into<Vec<u8>>  {
        self.into_protobuf().write_to_bytes()
    }

}

impl ProofProto {

    pub fn from_proof<D, T>(proof: Proof<D, T>) -> Self
        where T: Into<Vec<u8>>
    {
        let mut proto = Self::new();

        match proof {
            Proof { root_hash, lemma, value, .. } => {
                proto.set_root_hash(root_hash);
                proto.set_lemma(LemmaProto::from_lemma(lemma));
                proto.set_value(value.into());
            }
        }

        proto
    }

    pub fn into_proof<D, T>(mut self, digest: D) -> Option<Proof<D, T>>
        where T: From<Vec<u8>>
    {
        if !self.has_root_hash() || !self.has_lemma() {
            return None;
        }

        self.take_lemma().into_lemma().map(|lemma| {
            Proof::new(
                digest,
                self.take_root_hash(),
                lemma,
                self.take_value().into()
            )
        })
    }

}

impl LemmaProto {

    pub fn from_lemma(lemma: Lemma) -> Self {
        let mut proto = Self::new();

        match lemma {
            Lemma { node_hash, sibling_hash, sub_lemma } => {
                proto.set_node_hash(node_hash);

                if let Some(sub_proto) = sub_lemma.map(|l| Self::from_lemma(*l)) {
                    proto.set_sub_lemma(sub_proto);
                }

                match sibling_hash {
                    Some(Positioned::Left(hash)) =>
                        proto.set_left_sibling_hash(hash),

                    Some(Positioned::Right(hash)) =>
                        proto.set_right_sibling_hash(hash),

                    None => {}
                }
            }
        }

        proto
    }

    pub fn into_lemma(mut self) -> Option<Lemma> {
        if !self.has_node_hash() {
            return None;
        }

        let node_hash = self.take_node_hash();

        let sibling_hash =
            if self.has_left_sibling_hash() {
                Some(Positioned::Left(self.take_left_sibling_hash()))
            }
            else if self.has_right_sibling_hash() {
                Some(Positioned::Right(self.take_right_sibling_hash()))
            }
            else {
                None
            };

        if self.has_sub_lemma() {
            // If a `sub_lemma` is present is the Protobuf,
            // then we expect it to unserialize to a valid `Lemma`,
            // otherwise we return `None`
            self.take_sub_lemma().into_lemma().map(|sub_lemma| {
                Lemma {
                    node_hash: node_hash,
                    sibling_hash: sibling_hash,
                    sub_lemma: Some(Box::new(sub_lemma))
                }
            })
        }
        else {
            // We might very well not have a sub_lemma,
            // in which case we just set it to `None`,
            // but still return a potentially valid `Lemma`.
            Some(Lemma {
                node_hash: node_hash,
                sibling_hash: sibling_hash,
                sub_lemma: None
            })
        }
    }

}

<|endoftext|>