<commit_before>// Copyright 2016 Kyle Mayes
//
// 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.

//! Provides helper functionality.

use std::path::{Path, PathBuf};
use std::process::Command;
use std::{env, io};

use glob;

use libc::c_int;

use super::CXVersion;

//================================================
// Macros
//================================================

macro_rules! try_opt {
    ($option:expr) => {{
        match $option {
            Some(some) => some,
            None => return None,
        }
    }};
}

//================================================
// Structs
//================================================

/// A `clang` executable.
#[derive(Clone, Debug)]
pub struct Clang {
    /// The path to this `clang` executable.
    pub path: PathBuf,
    /// The version of this `clang` executable if it could be parsed.
    pub version: Option<CXVersion>,
    /// The directories searched by this `clang` executable for C headers if
    /// they could be parsed.
    pub c_search_paths: Option<Vec<PathBuf>>,
    /// The directories searched by this `clang` executable for C++ headers if
    /// they could be parsed.
    pub cpp_search_paths: Option<Vec<PathBuf>>,
}

impl Clang {
    fn new(path: impl AsRef<Path>, args: &[String]) -> Self {
        Self {
            path: path.as_ref().into(),
            version: parse_version(path.as_ref()),
            c_search_paths: parse_search_paths(path.as_ref(), "c", args),
            cpp_search_paths: parse_search_paths(path.as_ref(), "c++", args),
        }
    }

    /// Returns a `clang` executable if one can be found.
    ///
    /// If the `CLANG_PATH` environment variable is set, that is the instance of
    /// `clang` used. Otherwise, a series of directories are searched. First, if
    /// a path is supplied, that is the first directory searched. Then, the
    /// directory returned by `llvm-config --bindir` is searched. On macOS
    /// systems, `xcodebuild -find clang` will next be queried. Last, the
    /// directories in the system's `PATH` are searched.
    pub fn find(path: Option<&Path>, args: &[String]) -> Option<Clang> {
        if let Ok(path) = env::var("CLANG_PATH") {
            return Some(Clang::new(path, args));
        }

        let mut paths = vec![];
        if let Some(path) = path {
            paths.push(path.into());
        }
        if let Ok(path) = run_llvm_config(&["--bindir"]) {
            paths.push(path.into());
        }
        if cfg!(target_os = "macos") {
            if let Ok((path, _)) = run("xcodebuild", &["-find", "clang"]) {
                paths.push(path.into());
            }
        }
        paths.extend(env::split_paths(&env::var("PATH").unwrap()));

        let default = format!("clang{}", env::consts::EXE_SUFFIX);
        let versioned = format!("clang-[0-9]*{}", env::consts::EXE_SUFFIX);
        let patterns = &[&default[..], &versioned[..]];
        for path in paths {
            if let Some(path) = find(&path, patterns) {
                return Some(Clang::new(path, args));
            }
        }

        None
    }
}

//================================================
// Functions
//================================================

/// Returns the first match to the supplied glob patterns in the supplied
/// directory if there are any matches.
fn find(directory: &Path, patterns: &[&str]) -> Option<PathBuf> {
    for pattern in patterns {
        let pattern = directory.join(pattern).to_string_lossy().into_owned();
        if let Some(path) = try_opt!(glob::glob(&pattern).ok())
            .filter_map(|p| p.ok())
            .next()
        {
            if path.is_file() && is_executable(&path).unwrap_or(false) {
                return Some(path);
            }
        }
    }

    None
}

#[cfg(unix)]
fn is_executable(path: &Path) -> io::Result<bool> {
    use std::ffi::CString;
    use std::os::unix::ffi::OsStrExt;

    let path = CString::new(path.as_os_str().as_bytes())?;
    unsafe { Ok(libc::access(path.as_ptr(), libc::X_OK) == 0) }
}

#[cfg(not(unix))]
fn is_executable(_: &Path) -> io::Result<bool> {
    Ok(true)
}

/// Attempts to run an executable, returning the `stdout` and `stderr` output if
/// successful.
fn run(executable: &str, arguments: &[&str]) -> Result<(String, String), String> {
    Command::new(executable)
        .args(arguments)
        .output()
        .map(|o| {
            let stdout = String::from_utf8_lossy(&o.stdout).into_owned();
            let stderr = String::from_utf8_lossy(&o.stderr).into_owned();
            (stdout, stderr)
        })
        .map_err(|e| format!("could not run executable `{}`: {}", executable, e))
}

/// Runs `clang`, returning the `stdout` and `stderr` output.
fn run_clang(path: &Path, arguments: &[&str]) -> (String, String) {
    run(&path.to_string_lossy().into_owned(), arguments).unwrap()
}

/// Runs `llvm-config`, returning the `stdout` output if successful.
fn run_llvm_config(arguments: &[&str]) -> Result<String, String> {
    let config = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".to_string());
    run(&config, arguments).map(|(o, _)| o)
}

/// Parses a version number if possible, ignoring trailing non-digit characters.
fn parse_version_number(number: &str) -> Option<c_int> {
    number
        .chars()
        .take_while(|c| c.is_digit(10))
        .collect::<String>()
        .parse()
        .ok()
}

/// Parses the version from the output of a `clang` executable if possible.
fn parse_version(path: &Path) -> Option<CXVersion> {
    let output = run_clang(path, &["--version"]).0;
    let start = try_opt!(output.find("version ")) + 8;
    let mut numbers = try_opt!(output[start..].split_whitespace().next()).split('.');
    let major = try_opt!(numbers.next().and_then(parse_version_number));
    let minor = try_opt!(numbers.next().and_then(parse_version_number));
    let subminor = numbers.next().and_then(parse_version_number).unwrap_or(0);
    Some(CXVersion {
        Major: major,
        Minor: minor,
        Subminor: subminor,
    })
}

/// Parses the search paths from the output of a `clang` executable if possible.
fn parse_search_paths(path: &Path, language: &str, args: &[String]) -> Option<Vec<PathBuf>> {
    let mut clang_args = vec!["-E", "-x", language, "-", "-v"];
    clang_args.extend(args.iter().map(|s| &**s));
    let output = run_clang(path, &clang_args).1;
    let start = try_opt!(output.find("#include <...> search starts here:")) + 34;
    let end = try_opt!(output.find("End of search list."));
    let paths = output[start..end].replace("(framework directory)", "");
    Some(
        paths
            .lines()
            .filter(|l| !l.is_empty())
            .map(|l| Path::new(l.trim()).into())
            .collect(),
    )
}
<commit_msg>Trim trailing newline from command output before converting to path<commit_after>// Copyright 2016 Kyle Mayes
//
// 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.

//! Provides helper functionality.

use std::path::{Path, PathBuf};
use std::process::Command;
use std::{env, io};

use glob;

use libc::c_int;

use super::CXVersion;

//================================================
// Macros
//================================================

macro_rules! try_opt {
    ($option:expr) => {{
        match $option {
            Some(some) => some,
            None => return None,
        }
    }};
}

//================================================
// Structs
//================================================

/// A `clang` executable.
#[derive(Clone, Debug)]
pub struct Clang {
    /// The path to this `clang` executable.
    pub path: PathBuf,
    /// The version of this `clang` executable if it could be parsed.
    pub version: Option<CXVersion>,
    /// The directories searched by this `clang` executable for C headers if
    /// they could be parsed.
    pub c_search_paths: Option<Vec<PathBuf>>,
    /// The directories searched by this `clang` executable for C++ headers if
    /// they could be parsed.
    pub cpp_search_paths: Option<Vec<PathBuf>>,
}

impl Clang {
    fn new(path: impl AsRef<Path>, args: &[String]) -> Self {
        Self {
            path: path.as_ref().into(),
            version: parse_version(path.as_ref()),
            c_search_paths: parse_search_paths(path.as_ref(), "c", args),
            cpp_search_paths: parse_search_paths(path.as_ref(), "c++", args),
        }
    }

    /// Returns a `clang` executable if one can be found.
    ///
    /// If the `CLANG_PATH` environment variable is set, that is the instance of
    /// `clang` used. Otherwise, a series of directories are searched. First, if
    /// a path is supplied, that is the first directory searched. Then, the
    /// directory returned by `llvm-config --bindir` is searched. On macOS
    /// systems, `xcodebuild -find clang` will next be queried. Last, the
    /// directories in the system's `PATH` are searched.
    pub fn find(path: Option<&Path>, args: &[String]) -> Option<Clang> {
        if let Ok(path) = env::var("CLANG_PATH") {
            return Some(Clang::new(path, args));
        }

        let mut paths = vec![];
        if let Some(path) = path {
            paths.push(path.into());
        }
        if let Ok(path) = run_llvm_config(&["--bindir"]) {
            paths.push(path.lines().next().unwrap().into());
        }
        if cfg!(target_os = "macos") {
            if let Ok((path, _)) = run("xcodebuild", &["-find", "clang"]) {
                paths.push(path.lines().next().unwrap().into());
            }
        }
        paths.extend(env::split_paths(&env::var("PATH").unwrap()));

        let default = format!("clang{}", env::consts::EXE_SUFFIX);
        let versioned = format!("clang-[0-9]*{}", env::consts::EXE_SUFFIX);
        let patterns = &[&default[..], &versioned[..]];
        for path in paths {
            if let Some(path) = find(&path, patterns) {
                return Some(Clang::new(path, args));
            }
        }

        None
    }
}

//================================================
// Functions
//================================================

/// Returns the first match to the supplied glob patterns in the supplied
/// directory if there are any matches.
fn find(directory: &Path, patterns: &[&str]) -> Option<PathBuf> {
    for pattern in patterns {
        let pattern = directory.join(pattern).to_string_lossy().into_owned();
        if let Some(path) = try_opt!(glob::glob(&pattern).ok())
            .filter_map(|p| p.ok())
            .next()
        {
            if path.is_file() && is_executable(&path).unwrap_or(false) {
                return Some(path);
            }
        }
    }

    None
}

#[cfg(unix)]
fn is_executable(path: &Path) -> io::Result<bool> {
    use std::ffi::CString;
    use std::os::unix::ffi::OsStrExt;

    let path = CString::new(path.as_os_str().as_bytes())?;
    unsafe { Ok(libc::access(path.as_ptr(), libc::X_OK) == 0) }
}

#[cfg(not(unix))]
fn is_executable(_: &Path) -> io::Result<bool> {
    Ok(true)
}

/// Attempts to run an executable, returning the `stdout` and `stderr` output if
/// successful.
fn run(executable: &str, arguments: &[&str]) -> Result<(String, String), String> {
    Command::new(executable)
        .args(arguments)
        .output()
        .map(|o| {
            let stdout = String::from_utf8_lossy(&o.stdout).into_owned();
            let stderr = String::from_utf8_lossy(&o.stderr).into_owned();
            (stdout, stderr)
        })
        .map_err(|e| format!("could not run executable `{}`: {}", executable, e))
}

/// Runs `clang`, returning the `stdout` and `stderr` output.
fn run_clang(path: &Path, arguments: &[&str]) -> (String, String) {
    run(&path.to_string_lossy().into_owned(), arguments).unwrap()
}

/// Runs `llvm-config`, returning the `stdout` output if successful.
fn run_llvm_config(arguments: &[&str]) -> Result<String, String> {
    let config = env::var("LLVM_CONFIG_PATH").unwrap_or_else(|_| "llvm-config".to_string());
    run(&config, arguments).map(|(o, _)| o)
}

/// Parses a version number if possible, ignoring trailing non-digit characters.
fn parse_version_number(number: &str) -> Option<c_int> {
    number
        .chars()
        .take_while(|c| c.is_digit(10))
        .collect::<String>()
        .parse()
        .ok()
}

/// Parses the version from the output of a `clang` executable if possible.
fn parse_version(path: &Path) -> Option<CXVersion> {
    let output = run_clang(path, &["--version"]).0;
    let start = try_opt!(output.find("version ")) + 8;
    let mut numbers = try_opt!(output[start..].split_whitespace().next()).split('.');
    let major = try_opt!(numbers.next().and_then(parse_version_number));
    let minor = try_opt!(numbers.next().and_then(parse_version_number));
    let subminor = numbers.next().and_then(parse_version_number).unwrap_or(0);
    Some(CXVersion {
        Major: major,
        Minor: minor,
        Subminor: subminor,
    })
}

/// Parses the search paths from the output of a `clang` executable if possible.
fn parse_search_paths(path: &Path, language: &str, args: &[String]) -> Option<Vec<PathBuf>> {
    let mut clang_args = vec!["-E", "-x", language, "-", "-v"];
    clang_args.extend(args.iter().map(|s| &**s));
    let output = run_clang(path, &clang_args).1;
    let start = try_opt!(output.find("#include <...> search starts here:")) + 34;
    let end = try_opt!(output.find("End of search list."));
    let paths = output[start..end].replace("(framework directory)", "");
    Some(
        paths
            .lines()
            .filter(|l| !l.is_empty())
            .map(|l| Path::new(l.trim()).into())
            .collect(),
    )
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate timely;
extern crate timely_sort;
extern crate differential_dataflow;
extern crate vec_map;

use timely::dataflow::*;
use timely::dataflow::operators::*;

use rand::{Rng, SeedableRng, StdRng};

use differential_dataflow::AsCollection;
use differential_dataflow::operators::arrange::ArrangeByKey;
use differential_dataflow::trace::Cursor;
use differential_dataflow::trace::Batch;

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();

    // define a new timely dataflow computation.
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

        let index = worker.index();
        let peers = worker.peers();

        // create a a degree counting differential dataflow
        let (mut input, probe, trace) = worker.scoped(|scope| {

            // create edge input, count a few ways.
            let (input, edges) = scope.new_input();

            // pull off source, and count.
            let arranged = edges.as_collection()
                                .arrange_by_key_hashed();

            (input, arranged.stream.probe().0, arranged.trace.clone())
        });

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions

        // load up graph dataz
        let &time = input.time();
        for edge in 0..edges {
            if edge % peers == index {
                input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
            }

            // move the data along a bit
            if edge % 10000 == 9999 {
                worker.step();
            }
        }

        let timer = ::std::time::Instant::now();

        input.advance_to(1);
        worker.step_while(|| probe.lt(input.time()));

        if index == 0 {
            let timer = timer.elapsed();
            let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
            println!("Loading finished after {:?}", nanos);
        }

        // change graph, forever
        if batch > 0 {

            for edge in 0usize .. {
                let &time = input.time();
                if edge % peers == index {
                    input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
                    input.send(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), time,-1));
                }

                if edge % batch == (batch - 1) {

                    let timer = ::std::time::Instant::now();

                    let next = input.epoch() + 1;
                    input.advance_to(next);
                    worker.step_while(|| probe.lt(input.time()));

                    if index == 0 {
                        let timer = timer.elapsed();
                        let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
                        println!("Round {} finished after {:?}", next - 1, nanos);

                        let mut count = 0;

                        // we can directly interrogate the trace...
                        let timer = ::std::time::Instant::now();
                        let mut cursor = trace.cursor();
                        while cursor.key_valid() {
                            while cursor.val_valid() {
                                let mut sum = 0;
                                cursor.map_times(|_,d| sum += d);
                                if sum > 0 { count += 1; }
                                cursor.step_val();
                            }

                            cursor.step_key()
                        }

                        println!("count: {} in {:?}", count, timer.elapsed());

                        // or we can monitor data from a shared queue...
                        let queue = trace.new_listener();
                        let mut borrow = queue.borrow_mut();
                        while let Some((frontier, batch)) = borrow.pop_front() {
                            println!("received from queue:");
                            println!("  frontier: {:?}", frontier);
                            if let Some(batch) = batch {
                                println!("  batch from: {:?} -> {:?}, since: {:?}", batch.lower(), batch.upper(), batch.description().since());
                            }
                        }
                    }
                }
            }
        }

    }).unwrap();
}<commit_msg>arrange example allows trace compaction<commit_after>extern crate rand;
extern crate timely;
extern crate timely_sort;
extern crate differential_dataflow;
extern crate vec_map;

use timely::dataflow::*;
use timely::dataflow::operators::*;

use rand::{Rng, SeedableRng, StdRng};

use differential_dataflow::AsCollection;
use differential_dataflow::operators::arrange::ArrangeByKey;
use differential_dataflow::trace::Cursor;
use differential_dataflow::trace::Batch;

fn main() {

    let nodes: u32 = std::env::args().nth(1).unwrap().parse().unwrap();
    let edges: usize = std::env::args().nth(2).unwrap().parse().unwrap();
    let batch: usize = std::env::args().nth(3).unwrap().parse().unwrap();

    // define a new timely dataflow computation.
    timely::execute_from_args(std::env::args().skip(4), move |worker| {

        let index = worker.index();
        let peers = worker.peers();

        // create a a degree counting differential dataflow
        let (mut input, probe, mut trace) = worker.scoped(|scope| {

            // create edge input, count a few ways.
            let (input, edges) = scope.new_input();

            // pull off source, and count.
            let arranged = edges.as_collection()
                                .arrange_by_key_hashed();

            (input, arranged.stream.probe().0, arranged.trace.clone())
        });

        let seed: &[_] = &[1, 2, 3, index];
        let mut rng1: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions
        let mut rng2: StdRng = SeedableRng::from_seed(seed);    // rng for edge additions

        // load up graph dataz
        let &time = input.time();
        for edge in 0..edges {
            if edge % peers == index {
                input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
            }

            // move the data along a bit
            if edge % 10000 == 9999 {
                worker.step();
            }
        }

        let timer = ::std::time::Instant::now();

        input.advance_to(1);
        worker.step_while(|| probe.lt(input.time()));

        if index == 0 {
            let timer = timer.elapsed();
            let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
            println!("Loading finished after {:?}", nanos);
        }

        // change graph, forever
        if batch > 0 {

            for edge in 0usize .. {
                let &time = input.time();
                if edge % peers == index {
                    input.send(((rng1.gen_range(0, nodes), rng1.gen_range(0, nodes)), time, 1));
                    input.send(((rng2.gen_range(0, nodes), rng2.gen_range(0, nodes)), time,-1));
                }

                if edge % batch == (batch - 1) {

                    let timer = ::std::time::Instant::now();

                    trace.advance_by(&[input.time().clone()]);
                    trace.distinguish_since(&[input.time().clone()]);

                    let next = input.epoch() + 1;
                    input.advance_to(next);
                    worker.step_while(|| probe.lt(input.time()));

                    if index == 0 {
                        let timer = timer.elapsed();
                        let nanos = timer.as_secs() * 1000000000 + timer.subsec_nanos() as u64;
                        println!("Round {} finished after {:?}", next - 1, nanos);

                        let mut count = 0;

                        // we can directly interrogate the trace...
                        let timer = ::std::time::Instant::now();
                        let mut cursor = trace.cursor();
                        while cursor.key_valid() {
                            while cursor.val_valid() {
                                let mut sum = 0;
                                cursor.map_times(|_,d| sum += d);
                                if sum > 0 { count += 1; }
                                cursor.step_val();
                            }

                            cursor.step_key()
                        }

                        println!("count: {} in {:?}", count, timer.elapsed());

                        // or we can monitor data from a shared queue...
                        let queue = trace.new_listener();
                        let mut borrow = queue.borrow_mut();
                        while let Some((frontier, batch)) = borrow.pop_front() {
                            println!("received from queue:");
                            println!("  frontier: {:?}", frontier);
                            if let Some(batch) = batch {
                                println!("  batch from: {:?} -> {:?}, since: {:?}", batch.lower(), batch.upper(), batch.description().since());
                            }
                        }
                    }
                }
            }
        }

    }).unwrap();
}<|endoftext|>


<commit_before>extern crate mpi;

use mpi::traits::*;

fn main() {
    let universe = mpi::initialize().unwrap();
    let world = universe.world();

    println!("Before barrier, rank {}.", world.rank());
    world.barrier();
    println!("After barrier, rank {}.", world.rank());
}
<commit_msg>Add assertions to barrier example.<commit_after>extern crate mpi;

use mpi::traits::*;

fn main() {
    let universe = mpi::initialize().unwrap();
    let world = universe.world();

    if world.rank() > 0 {
        let msg = 1u64;
        world.process_at_rank(0).send(&msg);
        world.barrier();
        let msg = 2u64;
        world.process_at_rank(0).send(&msg);
    } else {
        let n = (world.size() - 1) as usize;
        let mut buf = vec![0u64; 2 * n];
        for x in buf[0..n].iter_mut() {
            world.receive_into(x);
        }
        world.barrier();
        for x in buf[n..2 * n].iter_mut() {
            world.receive_into(x);
        }
        println!("{:?}", buf);
        assert!(buf[0..n].iter().all(|&x| { x == 1 }));
        assert!(buf[n..2 * n].iter().all(|&x| { x == 2 }));
    }
}
<|endoftext|>


<commit_before>//! Modules for events in the *m.key.verification* namespace.
//!
//! This module also contains types shared by events in its child namespaces.
//!
//! The MSC for the in-room variants of the `m.key.verification.*` events can be found
//! [here](https://github.com/matrix-org/matrix-doc/pull/2241).

#[cfg(feature = "unstable-pre-spec")]
use std::convert::TryFrom;

#[cfg(feature = "unstable-pre-spec")]
use ruma_identifiers::EventId;
use ruma_serde::StringEnum;
#[cfg(feature = "unstable-pre-spec")]
use serde::{Deserialize, Serialize};

#[cfg(feature = "unstable-pre-spec")]
use crate::room::relationships::{Reference, RelatesToJsonRepr, RelationJsonRepr};

pub mod accept;
pub mod cancel;
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
pub mod done;
pub mod key;
pub mod mac;
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
pub mod ready;
pub mod request;
pub mod start;

/// A hash algorithm.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "snake_case")]
pub enum HashAlgorithm {
    /// The SHA256 hash algorithm.
    Sha256,

    #[doc(hidden)]
    _Custom(String),
}

/// A key agreement protocol.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "kebab-case")]
pub enum KeyAgreementProtocol {
    /// The [Curve25519](https://cr.yp.to/ecdh.html) key agreement protocol.
    Curve25519,

    /// The Curve25519 key agreement protocol with check for public keys.
    Curve25519HkdfSha256,

    #[doc(hidden)]
    _Custom(String),
}

/// A message authentication code algorithm.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "kebab-case")]
pub enum MessageAuthenticationCode {
    /// The HKDF-HMAC-SHA256 MAC.
    HkdfHmacSha256,

    /// The HMAC-SHA256 MAC.
    HmacSha256,

    #[doc(hidden)]
    _Custom(String),
}

/// A Short Authentication String method.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "snake_case")]
pub enum ShortAuthenticationString {
    /// The decimal method.
    Decimal,

    /// The emoji method.
    Emoji,

    #[doc(hidden)]
    _Custom(String),
}

/// The relation that contains info which event the reaction is applying to.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(try_from = "RelatesToJsonRepr", into = "RelatesToJsonRepr")]
pub struct Relation {
    /// The event that is being referenced.
    pub event_id: EventId,
}

#[cfg(feature = "unstable-pre-spec")]
impl Relation {
    /// Creates a new `Relation` with the given event ID.
    pub fn new(event_id: EventId) -> Self {
        Self { event_id }
    }
}

#[cfg(feature = "unstable-pre-spec")]
impl From<Relation> for RelatesToJsonRepr {
    fn from(relation: Relation) -> Self {
        RelatesToJsonRepr::Relation(RelationJsonRepr::Reference(Reference {
            event_id: relation.event_id,
        }))
    }
}

#[cfg(feature = "unstable-pre-spec")]
impl TryFrom<RelatesToJsonRepr> for Relation {
    type Error = &'static str;

    fn try_from(value: RelatesToJsonRepr) -> Result<Self, Self::Error> {
        if let RelatesToJsonRepr::Relation(RelationJsonRepr::Reference(r)) = value {
            Ok(Relation { event_id: r.event_id })
        } else {
            Err("Expected a relation with a rel_type of `reference`")
        }
    }
}

/// A Short Authentication String (SAS) verification method.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
pub enum VerificationMethod {
    /// The *m.sas.v1* verification method.
    #[ruma_enum(rename = "m.sas.v1")]
    MSasV1,

    /// The *m.qr_code.scan.v1* verification method.
    #[cfg(feature = "unstable-pre-spec")]
    #[ruma_enum(rename = "m.qr_code.scan.v1")]
    MQrScanShowV1,

    /// The *m.qr_code.show.v1* verification method.
    #[cfg(feature = "unstable-pre-spec")]
    #[ruma_enum(rename = "m.qr_code.show.v1")]
    MQrCodeShowV1,

    /// The *m.reciprocate.v1* verification method.
    #[cfg(feature = "unstable-pre-spec")]
    #[ruma_enum(rename = "m.reciprocate.v1")]
    MReciprocateV1,

    #[doc(hidden)]
    _Custom(String),
}

#[cfg(test)]
mod tests {
    use serde_json::{from_value as from_json_value, json};

    use super::{KeyAgreementProtocol, MessageAuthenticationCode};

    #[test]
    fn serialize_key_agreement() {
        let serialized =
            serde_json::to_string(&KeyAgreementProtocol::Curve25519HkdfSha256).unwrap();
        assert_eq!(serialized, "\"curve25519-hkdf-sha256\"");

        let deserialized: KeyAgreementProtocol = serde_json::from_str(&serialized).unwrap();
        assert_eq!(deserialized, KeyAgreementProtocol::Curve25519HkdfSha256);
    }

    #[test]
    fn deserialize_mac_method() {
        let json = json!(["hkdf-hmac-sha256", "hmac-sha256"]);

        let deserialized: Vec<MessageAuthenticationCode> = from_json_value(json).unwrap();
        assert!(deserialized.contains(&MessageAuthenticationCode::HkdfHmacSha256));
    }

    #[test]
    fn serialize_mac_method() {
        let serialized = serde_json::to_string(&MessageAuthenticationCode::HkdfHmacSha256).unwrap();
        let deserialized: MessageAuthenticationCode = serde_json::from_str(&serialized).unwrap();
        assert_eq!(serialized, "\"hkdf-hmac-sha256\"");
        assert_eq!(deserialized, MessageAuthenticationCode::HkdfHmacSha256);

        let serialized = serde_json::to_string(&MessageAuthenticationCode::HmacSha256).unwrap();
        let deserialized: MessageAuthenticationCode = serde_json::from_str(&serialized).unwrap();
        assert_eq!(serialized, "\"hmac-sha256\"");
        assert_eq!(deserialized, MessageAuthenticationCode::HmacSha256);
    }
}
<commit_msg>events: Fix the name of the qr code scan verification method<commit_after>//! Modules for events in the *m.key.verification* namespace.
//!
//! This module also contains types shared by events in its child namespaces.
//!
//! The MSC for the in-room variants of the `m.key.verification.*` events can be found
//! [here](https://github.com/matrix-org/matrix-doc/pull/2241).

#[cfg(feature = "unstable-pre-spec")]
use std::convert::TryFrom;

#[cfg(feature = "unstable-pre-spec")]
use ruma_identifiers::EventId;
use ruma_serde::StringEnum;
#[cfg(feature = "unstable-pre-spec")]
use serde::{Deserialize, Serialize};

#[cfg(feature = "unstable-pre-spec")]
use crate::room::relationships::{Reference, RelatesToJsonRepr, RelationJsonRepr};

pub mod accept;
pub mod cancel;
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
pub mod done;
pub mod key;
pub mod mac;
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
pub mod ready;
pub mod request;
pub mod start;

/// A hash algorithm.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "snake_case")]
pub enum HashAlgorithm {
    /// The SHA256 hash algorithm.
    Sha256,

    #[doc(hidden)]
    _Custom(String),
}

/// A key agreement protocol.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "kebab-case")]
pub enum KeyAgreementProtocol {
    /// The [Curve25519](https://cr.yp.to/ecdh.html) key agreement protocol.
    Curve25519,

    /// The Curve25519 key agreement protocol with check for public keys.
    Curve25519HkdfSha256,

    #[doc(hidden)]
    _Custom(String),
}

/// A message authentication code algorithm.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "kebab-case")]
pub enum MessageAuthenticationCode {
    /// The HKDF-HMAC-SHA256 MAC.
    HkdfHmacSha256,

    /// The HMAC-SHA256 MAC.
    HmacSha256,

    #[doc(hidden)]
    _Custom(String),
}

/// A Short Authentication String method.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
#[ruma_enum(rename_all = "snake_case")]
pub enum ShortAuthenticationString {
    /// The decimal method.
    Decimal,

    /// The emoji method.
    Emoji,

    #[doc(hidden)]
    _Custom(String),
}

/// The relation that contains info which event the reaction is applying to.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg(feature = "unstable-pre-spec")]
#[cfg_attr(docsrs, doc(cfg(feature = "unstable-pre-spec")))]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[serde(try_from = "RelatesToJsonRepr", into = "RelatesToJsonRepr")]
pub struct Relation {
    /// The event that is being referenced.
    pub event_id: EventId,
}

#[cfg(feature = "unstable-pre-spec")]
impl Relation {
    /// Creates a new `Relation` with the given event ID.
    pub fn new(event_id: EventId) -> Self {
        Self { event_id }
    }
}

#[cfg(feature = "unstable-pre-spec")]
impl From<Relation> for RelatesToJsonRepr {
    fn from(relation: Relation) -> Self {
        RelatesToJsonRepr::Relation(RelationJsonRepr::Reference(Reference {
            event_id: relation.event_id,
        }))
    }
}

#[cfg(feature = "unstable-pre-spec")]
impl TryFrom<RelatesToJsonRepr> for Relation {
    type Error = &'static str;

    fn try_from(value: RelatesToJsonRepr) -> Result<Self, Self::Error> {
        if let RelatesToJsonRepr::Relation(RelationJsonRepr::Reference(r)) = value {
            Ok(Relation { event_id: r.event_id })
        } else {
            Err("Expected a relation with a rel_type of `reference`")
        }
    }
}

/// A Short Authentication String (SAS) verification method.
#[derive(Clone, Debug, PartialEq, Eq, StringEnum)]
pub enum VerificationMethod {
    /// The *m.sas.v1* verification method.
    #[ruma_enum(rename = "m.sas.v1")]
    MSasV1,

    /// The *m.qr_code.scan.v1* verification method.
    #[cfg(feature = "unstable-pre-spec")]
    #[ruma_enum(rename = "m.qr_code.scan.v1")]
    MQrCodeScanV1,

    /// The *m.qr_code.show.v1* verification method.
    #[cfg(feature = "unstable-pre-spec")]
    #[ruma_enum(rename = "m.qr_code.show.v1")]
    MQrCodeShowV1,

    /// The *m.reciprocate.v1* verification method.
    #[cfg(feature = "unstable-pre-spec")]
    #[ruma_enum(rename = "m.reciprocate.v1")]
    MReciprocateV1,

    #[doc(hidden)]
    _Custom(String),
}

#[cfg(test)]
mod tests {
    use serde_json::{from_value as from_json_value, json};

    use super::{KeyAgreementProtocol, MessageAuthenticationCode};

    #[test]
    fn serialize_key_agreement() {
        let serialized =
            serde_json::to_string(&KeyAgreementProtocol::Curve25519HkdfSha256).unwrap();
        assert_eq!(serialized, "\"curve25519-hkdf-sha256\"");

        let deserialized: KeyAgreementProtocol = serde_json::from_str(&serialized).unwrap();
        assert_eq!(deserialized, KeyAgreementProtocol::Curve25519HkdfSha256);
    }

    #[test]
    fn deserialize_mac_method() {
        let json = json!(["hkdf-hmac-sha256", "hmac-sha256"]);

        let deserialized: Vec<MessageAuthenticationCode> = from_json_value(json).unwrap();
        assert!(deserialized.contains(&MessageAuthenticationCode::HkdfHmacSha256));
    }

    #[test]
    fn serialize_mac_method() {
        let serialized = serde_json::to_string(&MessageAuthenticationCode::HkdfHmacSha256).unwrap();
        let deserialized: MessageAuthenticationCode = serde_json::from_str(&serialized).unwrap();
        assert_eq!(serialized, "\"hkdf-hmac-sha256\"");
        assert_eq!(deserialized, MessageAuthenticationCode::HkdfHmacSha256);

        let serialized = serde_json::to_string(&MessageAuthenticationCode::HmacSha256).unwrap();
        let deserialized: MessageAuthenticationCode = serde_json::from_str(&serialized).unwrap();
        assert_eq!(serialized, "\"hmac-sha256\"");
        assert_eq!(deserialized, MessageAuthenticationCode::HmacSha256);
    }
}
<|endoftext|>


<commit_before>//
// Copyright 2020 The Project Oak Authors
//
// 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 crate::{
    proto::oak::introspection_events::{event::EventDetails, Event},
    runtime::Runtime,
};
use log::info;
use prost_types::Timestamp;
use std::time::{SystemTime, UNIX_EPOCH};

fn current_timestamp() -> Timestamp {
    let duration_since_unix_epoch = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .expect("Time went backwards");

    Timestamp {
        seconds: duration_since_unix_epoch.as_secs() as i64,
        nanos: duration_since_unix_epoch.subsec_nanos() as i32,
    }
}

// Introspection event related methods for the Runtime.
impl Runtime {
    /// Generates an introspection event recording a modification to the Runtime's
    /// internal data structures
    #[cfg(feature = "oak_debug")]
    pub fn introspection_event(&self, event_details: EventDetails) {
        let event = Event {
            timestamp: Some(current_timestamp()),
            event_details: Some(event_details),
        };

        // TODO(#913): Push the event over to a channel, to be consumed by the
        // introspection aux server.
        info!("Introspection event recorded: {:?}", event);
    }

    /// no-op implementation, introspection events are a debugging feature.
    #[cfg(not(feature = "oak_debug"))]
    pub fn introspection_event(&self, event_details: EventDetails) {}
}
<commit_msg>Move introspection output to debug (#1299)<commit_after>//
// Copyright 2020 The Project Oak Authors
//
// 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 crate::{
    proto::oak::introspection_events::{event::EventDetails, Event},
    runtime::Runtime,
};
use log::debug;
use prost_types::Timestamp;
use std::time::{SystemTime, UNIX_EPOCH};

fn current_timestamp() -> Timestamp {
    let duration_since_unix_epoch = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .expect("Time went backwards");

    Timestamp {
        seconds: duration_since_unix_epoch.as_secs() as i64,
        nanos: duration_since_unix_epoch.subsec_nanos() as i32,
    }
}

// Introspection event related methods for the Runtime.
impl Runtime {
    /// Generates an introspection event recording a modification to the Runtime's
    /// internal data structures
    #[cfg(feature = "oak_debug")]
    pub fn introspection_event(&self, event_details: EventDetails) {
        let event = Event {
            timestamp: Some(current_timestamp()),
            event_details: Some(event_details),
        };

        // TODO(#913): Push the event over to a channel, to be consumed by the
        // introspection aux server.
        debug!("Introspection event recorded: {:?}", event);
    }

    /// no-op implementation, introspection events are a debugging feature.
    #[cfg(not(feature = "oak_debug"))]
    pub fn introspection_event(&self, event_details: EventDetails) {}
}
<|endoftext|>


<commit_before>//! Primitive auto completion and type quering on ASTs

use std::iter::once;
use std::cmp::Ordering;

use base::ast::{Expr, SpannedExpr, SpannedPattern, Pattern, TcIdent, Typed};
use base::instantiate;
use base::pos::{Location, Span};
use base::scoped_map::ScopedMap;
use base::symbol::Symbol;
use base::types::{TcType, Type, TypeEnv};

trait OnFound {
    fn on_ident(&mut self, ident: &TcIdent<Symbol>) {
        let _ = ident;
    }

    fn on_pattern(&mut self, pattern: &SpannedPattern<TcIdent<Symbol>>) {
        let _ = pattern;
    }

    fn expr(&mut self, expr: &SpannedExpr<TcIdent<Symbol>>);

    fn ident(&mut self, context: &SpannedExpr<TcIdent<Symbol>>, ident: &TcIdent<Symbol>);

    /// Location points to whitespace
    fn nothing(&mut self);
}

struct GetType<E> {
    env: E,
    typ: Option<TcType>,
}

impl<E: TypeEnv> OnFound for GetType<E> {
    fn expr(&mut self, expr: &SpannedExpr<TcIdent<Symbol>>) {
        self.typ = Some(expr.env_type_of(&self.env));
    }

    fn ident(&mut self, _context: &SpannedExpr<TcIdent<Symbol>>, ident: &TcIdent<Symbol>) {
        self.typ = Some(ident.env_type_of(&self.env));
    }
    fn nothing(&mut self) {}
}

pub struct Suggestion {
    pub name: String,
    pub typ: TcType,
}

struct Suggest<E> {
    env: E,
    stack: ScopedMap<Symbol, TcType>,
    result: Vec<Suggestion>,
}

impl<E: TypeEnv> OnFound for Suggest<E> {
    fn on_ident(&mut self, ident: &TcIdent<Symbol>) {
        self.stack.insert(ident.name.clone(), ident.typ.clone());
    }

    fn on_pattern(&mut self, pattern: &SpannedPattern<TcIdent<Symbol>>) {
        match pattern.value {
            Pattern::Record { ref id, fields: ref field_ids, .. } => {
                let unaliased = instantiate::remove_aliases(&self.env, id.typ.clone());
                if let Type::Record { ref fields, .. } = *unaliased {
                    for (field, field_type) in field_ids.iter().zip(fields) {
                        let f = field.1.as_ref().unwrap_or(&field.0).clone();
                        self.stack.insert(f, field_type.typ.clone());
                    }
                }
            }
            Pattern::Identifier(ref id) => {
                self.stack.insert(id.name.clone(), id.typ.clone());
            }
            Pattern::Constructor(_, ref args) => {
                for arg in args {
                    self.stack.insert(arg.name.clone(), arg.typ.clone());
                }
            }
        }
    }

    fn expr(&mut self, expr: &SpannedExpr<TcIdent<Symbol>>) {
        if let Expr::Identifier(ref ident) = expr.value {
            for (k, typ) in self.stack.iter() {
                if k.declared_name().starts_with(ident.name.declared_name()) {
                    self.result.push(Suggestion {
                        name: k.declared_name().into(),
                        typ: typ.clone(),
                    });
                }
            }
        }
    }

    fn ident(&mut self, context: &SpannedExpr<TcIdent<Symbol>>, ident: &TcIdent<Symbol>) {
        if let Expr::FieldAccess(ref expr, _) = context.value {
            let typ = instantiate::remove_aliases(&self.env, expr.env_type_of(&self.env));
            if let Type::Record { ref fields, .. } = *typ {
                let id = ident.name.as_ref();
                for field in fields {
                    if field.name.as_ref().starts_with(id) {
                        self.result.push(Suggestion {
                            name: field.name.declared_name().into(),
                            typ: field.typ.clone(),
                        });
                    }
                }
            }
        }
    }

    fn nothing(&mut self) {
        self.result.extend(self.stack.iter().map(|(name, typ)| {
            Suggestion {
                name: name.declared_name().into(),
                typ: typ.clone(),
            }
        }));
    }
}

struct FindVisitor<F> {
    location: Location,
    on_found: F,
}

impl<F> FindVisitor<F> {
    fn select_spanned<'e, I, S, T>(&self, iter: I, mut span: S) -> (bool, Option<&'e T>)
        where I: IntoIterator<Item = &'e T>,
              S: FnMut(&T) -> Span
    {
        let mut iter = iter.into_iter().peekable();
        let mut prev = None;
        loop {
            match iter.peek() {
                Some(expr) => {
                    match span(expr).containment(&self.location) {
                        Ordering::Equal => {
                            break;
                        }
                        Ordering::Less if prev.is_some() => {
                            // Select the previous expression
                            return (true, prev);
                        }
                        _ => (),
                    }
                }
                None => return (true, prev),
            }
            prev = iter.next();
        }
        (false, iter.next())
    }
}

impl<F> FindVisitor<F>
    where F: OnFound
{
    fn visit_one<'e, I>(&mut self, iter: I)
        where I: IntoIterator<Item = &'e SpannedExpr<TcIdent<Symbol>>>
    {
        let (_, expr) = self.select_spanned(iter, |e| e.span);
        self.visit_expr(expr.unwrap());
    }

    fn visit_pattern(&mut self, pattern: &SpannedPattern<TcIdent<Symbol>>) {
        self.on_found.on_pattern(pattern);
    }

    fn visit_expr(&mut self, current: &SpannedExpr<TcIdent<Symbol>>) {
        use base::ast::Expr::*;

        match current.value {
            Identifier(_) | Literal(_) => {
                if current.span(self.env).containment(&self.location) == Ordering::Equal {
                    self.on_found.expr(current)
                } else {
                    self.on_found.nothing()
                }
            }
            Call(ref func, ref args) => {
                self.visit_one(once(&**func).chain(args));
            }
            IfElse(ref pred, ref if_true, ref if_false) => {
                self.visit_one([pred, if_true, if_false.as_ref().expect("false branch")]
                    .iter()
                    .map(|x| &***x))
            }
            Match(ref expr, ref alts) => {
                self.visit_one(once(&**expr).chain(alts.iter().map(|alt| &alt.expression)))
            }
            BinOp(ref l, ref op, ref r) => {
                match (l.span.containment(&self.location), r.span.containment(&self.location)) {
                    (Ordering::Greater, Ordering::Less) => self.on_found.ident(current, op),
                    (_, Ordering::Greater) |
                    (_, Ordering::Equal) => self.visit_expr(r),
                    _ => self.visit_expr(l),
                }
            }
            Let(ref bindings, ref expr) => {
                for bind in bindings {
                    self.visit_pattern(&bind.name);
                }
                match self.select_spanned(bindings, |b| b.expression.span) {
                    (false, Some(bind)) => {
                        for arg in &bind.arguments {
                            self.on_found.on_ident(arg);
                        }
                        self.visit_expr(&bind.expression)
                    }
                    _ => self.visit_expr(expr),
                }
            }
            Type(_, ref expr) => self.visit_expr(expr),
            FieldAccess(ref expr, ref id) => {
                if expr.span.containment(&self.location) <= Ordering::Equal {
                    self.visit_expr(expr);
                } else {
                    self.on_found.ident(current, id);
                }
            }
            Array(ref array) => self.visit_one(&array.expressions),
            Record { ref exprs, .. } => {
                let exprs = exprs.iter().filter_map(|tup| tup.1.as_ref());
                if let (_, Some(expr)) = self.select_spanned(exprs, |e| e.span) {
                    self.visit_expr(expr);
                }
            }
            Lambda(ref lambda) => {
                for arg in &lambda.arguments {
                    self.on_found.on_ident(arg);
                }
                self.visit_expr(&lambda.body)
            }
            Tuple(ref args) => self.visit_one(args),
            Block(ref exprs) => self.visit_one(exprs),
        };
    }
}

pub fn find<T>(env: &T, expr: &SpannedExpr<TcIdent<Symbol>>, location: Location) -> Result<TcType, ()>
    where T: TypeEnv
{
    let mut visitor = FindVisitor {
        location: location,
        on_found: GetType {
            env: env,
            typ: None,
        },
    };
    visitor.visit_expr(expr);
    visitor.on_found.typ.ok_or(())
}

pub fn suggest<T>(env: &T,
                  expr: &SpannedExpr<TcIdent<Symbol>>,
                  location: Location)
                  -> Vec<TcIdent<Symbol>>
    where T: TypeEnv
{
    let mut visitor = FindVisitor {
        location: location,
        on_found: Suggest {
            env: env,
            stack: ScopedMap::new(),
            result: Vec::new(),
        },
    };
    visitor.visit_expr(expr);
    visitor.on_found.result
}
<commit_msg>fix(completion): expr.span() -> expr.span<commit_after>//! Primitive auto completion and type quering on ASTs

use std::iter::once;
use std::cmp::Ordering;

use base::ast::{Expr, SpannedExpr, SpannedPattern, Pattern, TcIdent, Typed};
use base::instantiate;
use base::pos::{Location, Span};
use base::scoped_map::ScopedMap;
use base::symbol::Symbol;
use base::types::{TcType, Type, TypeEnv};

trait OnFound {
    fn on_ident(&mut self, ident: &TcIdent<Symbol>) {
        let _ = ident;
    }

    fn on_pattern(&mut self, pattern: &SpannedPattern<TcIdent<Symbol>>) {
        let _ = pattern;
    }

    fn expr(&mut self, expr: &SpannedExpr<TcIdent<Symbol>>);

    fn ident(&mut self, context: &SpannedExpr<TcIdent<Symbol>>, ident: &TcIdent<Symbol>);

    /// Location points to whitespace
    fn nothing(&mut self);
}

struct GetType<E> {
    env: E,
    typ: Option<TcType>,
}

impl<E: TypeEnv> OnFound for GetType<E> {
    fn expr(&mut self, expr: &SpannedExpr<TcIdent<Symbol>>) {
        self.typ = Some(expr.env_type_of(&self.env));
    }

    fn ident(&mut self, _context: &SpannedExpr<TcIdent<Symbol>>, ident: &TcIdent<Symbol>) {
        self.typ = Some(ident.env_type_of(&self.env));
    }
    fn nothing(&mut self) {}
}

pub struct Suggestion {
    pub name: String,
    pub typ: TcType,
}

struct Suggest<E> {
    env: E,
    stack: ScopedMap<Symbol, TcType>,
    result: Vec<Suggestion>,
}

impl<E: TypeEnv> OnFound for Suggest<E> {
    fn on_ident(&mut self, ident: &TcIdent<Symbol>) {
        self.stack.insert(ident.name.clone(), ident.typ.clone());
    }

    fn on_pattern(&mut self, pattern: &SpannedPattern<TcIdent<Symbol>>) {
        match pattern.value {
            Pattern::Record { ref id, fields: ref field_ids, .. } => {
                let unaliased = instantiate::remove_aliases(&self.env, id.typ.clone());
                if let Type::Record { ref fields, .. } = *unaliased {
                    for (field, field_type) in field_ids.iter().zip(fields) {
                        let f = field.1.as_ref().unwrap_or(&field.0).clone();
                        self.stack.insert(f, field_type.typ.clone());
                    }
                }
            }
            Pattern::Identifier(ref id) => {
                self.stack.insert(id.name.clone(), id.typ.clone());
            }
            Pattern::Constructor(_, ref args) => {
                for arg in args {
                    self.stack.insert(arg.name.clone(), arg.typ.clone());
                }
            }
        }
    }

    fn expr(&mut self, expr: &SpannedExpr<TcIdent<Symbol>>) {
        if let Expr::Identifier(ref ident) = expr.value {
            for (k, typ) in self.stack.iter() {
                if k.declared_name().starts_with(ident.name.declared_name()) {
                    self.result.push(Suggestion {
                        name: k.declared_name().into(),
                        typ: typ.clone(),
                    });
                }
            }
        }
    }

    fn ident(&mut self, context: &SpannedExpr<TcIdent<Symbol>>, ident: &TcIdent<Symbol>) {
        if let Expr::FieldAccess(ref expr, _) = context.value {
            let typ = instantiate::remove_aliases(&self.env, expr.env_type_of(&self.env));
            if let Type::Record { ref fields, .. } = *typ {
                let id = ident.name.as_ref();
                for field in fields {
                    if field.name.as_ref().starts_with(id) {
                        self.result.push(Suggestion {
                            name: field.name.declared_name().into(),
                            typ: field.typ.clone(),
                        });
                    }
                }
            }
        }
    }

    fn nothing(&mut self) {
        self.result.extend(self.stack.iter().map(|(name, typ)| {
            Suggestion {
                name: name.declared_name().into(),
                typ: typ.clone(),
            }
        }));
    }
}

struct FindVisitor<F> {
    location: Location,
    on_found: F,
}

impl<F> FindVisitor<F> {
    fn select_spanned<'e, I, S, T>(&self, iter: I, mut span: S) -> (bool, Option<&'e T>)
        where I: IntoIterator<Item = &'e T>,
              S: FnMut(&T) -> Span
    {
        let mut iter = iter.into_iter().peekable();
        let mut prev = None;
        loop {
            match iter.peek() {
                Some(expr) => {
                    match span(expr).containment(&self.location) {
                        Ordering::Equal => {
                            break;
                        }
                        Ordering::Less if prev.is_some() => {
                            // Select the previous expression
                            return (true, prev);
                        }
                        _ => (),
                    }
                }
                None => return (true, prev),
            }
            prev = iter.next();
        }
        (false, iter.next())
    }
}

impl<F> FindVisitor<F>
    where F: OnFound
{
    fn visit_one<'e, I>(&mut self, iter: I)
        where I: IntoIterator<Item = &'e SpannedExpr<TcIdent<Symbol>>>
    {
        let (_, expr) = self.select_spanned(iter, |e| e.span);
        self.visit_expr(expr.unwrap());
    }

    fn visit_pattern(&mut self, pattern: &SpannedPattern<TcIdent<Symbol>>) {
        self.on_found.on_pattern(pattern);
    }

    fn visit_expr(&mut self, current: &SpannedExpr<TcIdent<Symbol>>) {
        use base::ast::Expr::*;

        match current.value {
            Identifier(_) | Literal(_) => {
                if current.span.containment(&self.location) == Ordering::Equal {
                    self.on_found.expr(current)
                } else {
                    self.on_found.nothing()
                }
            }
            Call(ref func, ref args) => {
                self.visit_one(once(&**func).chain(args));
            }
            IfElse(ref pred, ref if_true, ref if_false) => {
                self.visit_one([pred, if_true, if_false.as_ref().expect("false branch")]
                    .iter()
                    .map(|x| &***x))
            }
            Match(ref expr, ref alts) => {
                self.visit_one(once(&**expr).chain(alts.iter().map(|alt| &alt.expression)))
            }
            BinOp(ref l, ref op, ref r) => {
                match (l.span.containment(&self.location), r.span.containment(&self.location)) {
                    (Ordering::Greater, Ordering::Less) => self.on_found.ident(current, op),
                    (_, Ordering::Greater) |
                    (_, Ordering::Equal) => self.visit_expr(r),
                    _ => self.visit_expr(l),
                }
            }
            Let(ref bindings, ref expr) => {
                for bind in bindings {
                    self.visit_pattern(&bind.name);
                }
                match self.select_spanned(bindings, |b| b.expression.span) {
                    (false, Some(bind)) => {
                        for arg in &bind.arguments {
                            self.on_found.on_ident(arg);
                        }
                        self.visit_expr(&bind.expression)
                    }
                    _ => self.visit_expr(expr),
                }
            }
            Type(_, ref expr) => self.visit_expr(expr),
            FieldAccess(ref expr, ref id) => {
                if expr.span.containment(&self.location) <= Ordering::Equal {
                    self.visit_expr(expr);
                } else {
                    self.on_found.ident(current, id);
                }
            }
            Array(ref array) => self.visit_one(&array.expressions),
            Record { ref exprs, .. } => {
                let exprs = exprs.iter().filter_map(|tup| tup.1.as_ref());
                if let (_, Some(expr)) = self.select_spanned(exprs, |e| e.span) {
                    self.visit_expr(expr);
                }
            }
            Lambda(ref lambda) => {
                for arg in &lambda.arguments {
                    self.on_found.on_ident(arg);
                }
                self.visit_expr(&lambda.body)
            }
            Tuple(ref args) => self.visit_one(args),
            Block(ref exprs) => self.visit_one(exprs),
        };
    }
}

pub fn find<T>(env: &T, expr: &SpannedExpr<TcIdent<Symbol>>, location: Location) -> Result<TcType, ()>
    where T: TypeEnv
{
    let mut visitor = FindVisitor {
        location: location,
        on_found: GetType {
            env: env,
            typ: None,
        },
    };
    visitor.visit_expr(expr);
    visitor.on_found.typ.ok_or(())
}

pub fn suggest<T>(env: &T,
                  expr: &SpannedExpr<TcIdent<Symbol>>,
                  location: Location)
                  -> Vec<Suggestion>
    where T: TypeEnv
{
    let mut visitor = FindVisitor {
        location: location,
        on_found: Suggest {
            env: env,
            stack: ScopedMap::new(),
            result: Vec::new(),
        },
    };
    visitor.visit_expr(expr);
    visitor.on_found.result
}
<|endoftext|>


<commit_before>extern crate tinyexpr;

fn main()
{
    let r = tinyexpr::interp("2*1/sin(3.14/2)").unwrap_or_else(|e| {
        panic!("{}", e);
    });

    println!("{:?}", r);
}
<commit_msg>removed old example<commit_after><|endoftext|>


<commit_before>/* SiFive U34 hardware-specific code
 *
 * (c) Chris Williams, 2018.
 *
 * See LICENSE for usage and copying.
 */

#![no_std]
extern crate hermit_dtb;

/* get_ram_size
   => device_tree_buf = pointer to device tree in kernel-accessible RAM
   <= number of bytes in system memory, or None for failure
*/
pub fn get_ram_size(device_tree_buf: &u8) -> Option<usize>
{
  let dev_tree = match unsafe { hermit_dtb::Dtb::from_raw(device_tree_buf) }
  {
    Some(x) => x,
    None => return None
  };

  let mem_params = match dev_tree.get_property("/memory@80000000", "reg")
  {
    Some(x) => x,
    None => return None
  };

  /* reconstruct memory params from bytes */
  let mem_size = (mem_params[15] as usize) << 0  |
                 (mem_params[14] as usize) << 8  |
                 (mem_params[13] as usize) << 16 |
                 (mem_params[12] as usize) << 24;
  return Some(mem_size);
}
<commit_msg>properly calculate memory size as a 64-bit value<commit_after>/* SiFive U34 hardware-specific code
 *
 * (c) Chris Williams, 2018.
 *
 * See LICENSE for usage and copying.
 */

#![no_std]
extern crate hermit_dtb;

/* get_ram_size
   => device_tree_buf = pointer to device tree in kernel-accessible RAM
   <= number of bytes in system memory, or None for failure
*/
pub fn get_ram_size(device_tree_buf: &u8) -> Option<u64>
{
  let dev_tree = match unsafe { hermit_dtb::Dtb::from_raw(device_tree_buf) }
  {
    Some(x) => x,
    None => return None
  };

  let mem_params = match dev_tree.get_property("/memory@80000000", "reg")
  {
    Some(x) => x,
    None => return None
  };

  /* reconstruct memory params from bytes in the DT array. the format is:
     bytes  contents
     0-3    DRAM base address (upper 32 bits)
     4-7    DRAM base address (lower 32 bits)
     8-11   DRAM size (upper 32 bits)
     12-15  DRAM size (lower 32 bits) */
  let mem_size =  (mem_params[15] as u64) << 0  |
                  (mem_params[14] as u64) << 8  |
                  (mem_params[13] as u64) << 16 |
                  (mem_params[12] as u64) << 24 |
                  (mem_params[11] as u64) << 32 |
                  (mem_params[10] as u64) << 40 |
                  (mem_params[ 9] as u64) << 48 |
                  (mem_params[ 8] as u64) << 56;
  return Some(mem_size);
}
<|endoftext|>


<commit_before>use rustfm_scrobble::{Scrobble, Scrobbler};

// Example rustfm-scrobble client showing authentication, now playing and
// scrobbling.
// Replace credential values with your own to test.

fn main() {
    let api_key = "{{api_key}}";
    let api_secret = "{{api_secret}}";
    let username = "{{username}}";
    let password = "{{password}}";

    let mut scrobbler = Scrobbler::new(api_key, api_secret);

    match scrobbler.authenticate_with_password(username, password) {
        Ok(_) => {
            println!("Authenticated!");
        }
        Err(e) => {
            println!("{}", e);
        }
    };

    let track_one = Scrobble::new("Los Campesinos!", "As Lucerne / The Low", "No Blues");
    match scrobbler.now_playing(track_one) {
        Ok(_) => {
            println!("Sent now playing! ");
        }
        Err(e) => {
            println!("{}", e);
        }
    }

    let track_two = Scrobble::new("Los Campesinos!", "The Time Before the Last", "No Blues");
    match scrobbler.scrobble(track_two) {
        Ok(_) => {
            println!("Sent scrobble!");
        }
        Err(e) => {
            println!("{}", e);
        }
    }

    let track_three = Scrobble::new("Los Campesinos!", "Selling Rope", "No Blues");
    match scrobbler.now_playing(track_three) {
        Ok(_) => {
            println!("Sent now playing! ");
        }
        Err(e) => {
            println!("{}", e);
        }
    }
}
<commit_msg>Simplify and expand example code (#22)<commit_after>use rustfm_scrobble::{Scrobble, Scrobbler};

// Example rustfm-scrobble client showing authentication, now playing and
// scrobbling.
// Replace credential values with your own to test.

fn main() {
    let api_key = "{{api_key}}";
    let api_secret = "{{api_secret}}";
    let username = "{{username}}";
    let password = "{{password}}";

    let mut scrobbler = Scrobbler::new(api_key, api_secret);

    match scrobbler.authenticate_with_password(username, password) {
        Ok(_) => {
            println!("Authenticated!");
        }
        Err(e) => {
            println!("Authentication failed: {}", e);
        }
    };

    let track = Scrobble::new("Los Campesinos!", "As Lucerne / The Low", "No Blues");
    match scrobbler.now_playing(track.clone()) {
        Ok(resp) => {
            println!("Now playing: {} - {}", resp.artist.text, resp.track.text);
        }
        Err(e) => {
            println!("Now playing failed: {}", e);
        }
    }

    match scrobbler.scrobble(track) {
        Ok(resp) => {
            println!("Scrobbled {} - {} at timestamp: {}", resp.artist.text, resp.track.text, resp.timestamp);
        }
        Err(e) => {
            println!("Scrobble failed: {}", e);
        }
    }

}
<|endoftext|>


<commit_before>#![crate_name = "helloworld-server"]

/// Hello World server in Rust
/// Binds REP socket to tcp://*:5555
/// Expects "Hello" from client, replies with "World"

extern crate zmq;

use std::io;

fn main() {
    let mut context = zmq::Context::new();
    let mut responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new();
    loop {
        responder.recv(&mut msg, 0).unwrap();
        msg.with_str(|s| {
            println!("Received {}", s);
        });
        responder.send_str("World", 0).unwrap();
        io::timer::sleep(1000);
    }
}
<commit_msg>Use std::time::Duration<commit_after>#![crate_name = "helloworld-server"]

/// Hello World server in Rust
/// Binds REP socket to tcp://*:5555
/// Expects "Hello" from client, replies with "World"

extern crate zmq;

use std::io;
use std::time::Duration;

fn main() {
    let mut context = zmq::Context::new();
    let mut responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new();
    loop {
        responder.recv(&mut msg, 0).unwrap();
        msg.with_str(|s| {
            println!("Received {}", s);
        });
        responder.send_str("World", 0).unwrap();
        io::timer::sleep(Duration::seconds(1));
    }
}
<|endoftext|>


<commit_before>extern crate pancurses;

use pancurses::*;

fn main() {
    let window = initscr();

    start_color();
    use_default_colors();

    cbreak();
    noecho();

    window.clear();
    window.refresh();

    window.keypad(true);

    init_pair(1, 15, COLOR_BLACK);
    init_pair(2, COLOR_BLACK, COLOR_YELLOW);

    set_title("NewTest: tests various pancurses features");

    mousemask(ALL_MOUSE_EVENTS, std::ptr::null_mut());

    window.attrset(COLOR_PAIR(1));

    let mut quit = false;
    let mut redraw = true;

    const COL1: i32 = 2;
    const COL2: i32 = COL1 + 30;
    const COL3: i32 = 72;

    let mut unicode_offset = 0x80;

    while !quit {
        let (y_max, x_max) = window.get_max_yx();
        let color_block_start = 54;
        let mut color_block_cols = (x_max - color_block_start) / 2;
        let color_block_lines = 19;

        if color_block_cols < 0 {
            color_block_cols = 0;
        }

        if redraw {
            window.mvaddstr(1, COL1, "'Normal' white-on-black");

            window.attron(A_DIM);
            window.mvaddstr(2, COL1, "Dimmed text");
            window.attroff(A_DIM);

            window.attron(A_BLINK);
            window.mvaddstr(6, 40, "Blinking");
            window.attron(A_BOLD);
            window.mvaddstr(8, 40, "BlinkBold");
            window.attron(A_ITALIC);
            window.mvaddstr(0, COL2, "BlinkBoldItalic");
            window.attrset(COLOR_PAIR(3));
            window.attron(A_UNDERLINE);

            window.mvaddstr(1, COL2, "Underlined");

            window.attrset(COLOR_PAIR(1));
            window.attron(A_UNDERLINE | A_ITALIC);
            window.mvaddstr(2, COL2, "UnderlinedItalic");
            window.attrset(COLOR_PAIR(2));
            window.mvaddstr(4, COL1, "Black-on-yellow blinking");
            window.attron(A_BLINK);

            window.attrset(COLOR_PAIR(1));
            window.mv(4, COL2);
            text_in_a_box("Text in a box", &window);

            window.attrset(COLOR_PAIR(6));
            window.attron(A_STRIKEOUT);
            window.mvaddstr(10, 40, "Strikeout");
            window.attrset(COLOR_PAIR(1));

            window.mv(11, 40);
            text_in_a_box("Next Ucode pg", &window);
            if unicode_offset != 0 {
                window.mv(12, 40);
                text_in_a_box("Prev Ucode pg", &window);
            }
            window.mvprintw(13, 40, &format!("U+{:04X} ", unicode_offset));
        }

        // These two lines are just here to allow running this until its finished
        window.getch();
        break;
    }

    endwin();
}

fn text_in_a_box(text: &str, window: &Window) {
    let len = text.len();

    window.attron(A_OVERLINE | A_UNDERLINE | A_LEFTLINE);
    if len == 1 {
        window.attron(A_RIGHTLINE);
    }

    window.addnstr(text, 1);
    if len > 1 {
        window.attroff(A_LEFTLINE);
        if len > 2 {
            window.addnstr(&text[1..], len - 2);
        }
        window.attron(A_RIGHTLINE);
        window.addnstr(&text[len - 1..], 1);
    }

    window.attroff(A_OVERLINE | A_UNDERLINE | A_LEFTLINE | A_RIGHTLINE);
}
<commit_msg>Display character table<commit_after>extern crate pancurses;

use pancurses::*;

fn main() {
    let window = initscr();

    start_color();
    use_default_colors();

    cbreak();
    noecho();

    window.clear();
    window.refresh();

    window.keypad(true);

    init_pair(1, 15, COLOR_BLACK);
    init_pair(2, COLOR_BLACK, COLOR_YELLOW);

    set_title("NewTest: tests various pancurses features");

    mousemask(ALL_MOUSE_EVENTS, std::ptr::null_mut());

    window.attrset(COLOR_PAIR(1));

    let mut quit = false;
    let mut redraw = true;

    const COL1: i32 = 2;
    const COL2: i32 = COL1 + 30;
    const COL3: i32 = 72;

    let mut unicode_offset = 0x80;

    while !quit {
        let (y_max, x_max) = window.get_max_yx();
        let color_block_start = 54;
        let mut color_block_cols = (x_max - color_block_start) / 2;
        let color_block_lines = 19;

        if color_block_cols < 0 {
            color_block_cols = 0;
        }

        if redraw {
            window.mvaddstr(1, COL1, "'Normal' white-on-black");

            window.attron(A_DIM);
            window.mvaddstr(2, COL1, "Dimmed text");
            window.attroff(A_DIM);

            window.attron(A_BLINK);
            window.mvaddstr(6, 40, "Blinking");
            window.attron(A_BOLD);
            window.mvaddstr(8, 40, "BlinkBold");
            window.attron(A_ITALIC);
            window.mvaddstr(0, COL2, "BlinkBoldItalic");
            window.attrset(COLOR_PAIR(3));
            window.attron(A_UNDERLINE);

            window.mvaddstr(1, COL2, "Underlined");

            window.attrset(COLOR_PAIR(1));
            window.attron(A_UNDERLINE | A_ITALIC);
            window.mvaddstr(2, COL2, "UnderlinedItalic");
            window.attrset(COLOR_PAIR(2));
            window.mvaddstr(4, COL1, "Black-on-yellow blinking");
            window.attron(A_BLINK);

            window.attrset(COLOR_PAIR(1));
            window.mv(4, COL2);
            text_in_a_box("Text in a box", &window);

            window.attrset(COLOR_PAIR(6));
            window.attron(A_STRIKEOUT);
            window.mvaddstr(10, 40, "Strikeout");
            window.attrset(COLOR_PAIR(1));

            window.mv(11, 40);
            text_in_a_box("Next Ucode pg", &window);
            if unicode_offset != 0 {
                window.mv(12, 40);
                text_in_a_box("Prev Ucode pg", &window);
            }
            window.mvprintw(13, 40, &format!("U+{:04X} ", unicode_offset));

            for i in 0..128 { // Show extended characters
                window.mvaddstr(5 + i % 16, (i / 16) * 5, &format!("{:02X} ", i + unicode_offset));
                if i + unicode_offset > ' ' as i32 {
                   window.addch((i + unicode_offset) as chtype);
                } else {
                   window.addch(' ');
                }
                window.addch(' ');
            }
        }

        // These two lines are just here to allow running this until its finished
        window.getch();
        break;
    }

    endwin();
}

fn text_in_a_box(text: &str, window: &Window) {
    let len = text.len();

    window.attron(A_OVERLINE | A_UNDERLINE | A_LEFTLINE);
    if len == 1 {
        window.attron(A_RIGHTLINE);
    }

    window.addnstr(text, 1);
    if len > 1 {
        window.attroff(A_LEFTLINE);
        if len > 2 {
            window.addnstr(&text[1..], len - 2);
        }
        window.attron(A_RIGHTLINE);
        window.addnstr(&text[len - 1..], 1);
    }

    window.attroff(A_OVERLINE | A_UNDERLINE | A_LEFTLINE | A_RIGHTLINE);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;

use glium::Surface;
use glium::glutin;

mod support;

#[derive(Copy, Clone, Debug)]
struct PerInstance {
    pub id: u32,
    pub w_position: (f32, f32, f32),
    pub color: (f32, f32, f32),
}
implement_vertex!(PerInstance, id, w_position, color);

fn main() {
    use glium::DisplayBuild;

    // building the display, ie. the main object
    let display = glutin::WindowBuilder::new()
        .with_depth_buffer(24)
        .build_glium()
        .unwrap();

    // building the vertex and index buffers
    let vertex_buffer = support::load_wavefront(&display, include_bytes!("support/teapot.obj"));

    // the program
    let program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 persp_matrix;
                uniform mat4 view_matrix;

                in uint id;
                in vec3 w_position;
                in vec3 color;
                in vec3 position;
                in vec3 normal;
                out vec3 v_normal;
                out vec3 v_color;

                void main() {
                    v_normal = normal;
                    v_color = color;
                    gl_Position = persp_matrix * view_matrix * vec4(position * 0.005 + w_position, 1.0);
                }
            ",

            fragment: "
                #version 140

                in vec3 v_normal;
                in vec3 v_color;
                out vec4 f_color;

                const vec3 LIGHT = vec3(-0.2, 0.8, 0.1);

                void main() {
                    float lum = max(dot(normalize(v_normal), normalize(LIGHT)), 0.0);
                    vec3 color = (0.3 + 0.7 * lum) * v_color;
                    f_color = vec4(color, 1.0);
                }
            ",
        },
    ).unwrap();

    let picking_program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 persp_matrix;
                uniform mat4 view_matrix;

                in uint id;
                in vec3 w_position;
                in vec3 color;
                in vec3 position;
                in vec3 normal;
                flat out uint v_id;

                void main() {
                    v_id = id;
                    gl_Position = persp_matrix * view_matrix * vec4(position * 0.005 + w_position, 1.0);
                }
            ",

            fragment: "
                #version 140

                flat in uint v_id;
                out uint f_id;

                void main() {
                    f_id = v_id;
                }
            ",
        },
    ).unwrap();

    //
    let mut camera = support::camera::CameraState::new();
    camera.set_position((0.0, 0.0, 1.5));
    camera.set_direction((0.0, 0.0, 1.0));

    let mut per_instance = vec![
        PerInstance { id: 1, w_position: (-1.0, 0.0, 0.0), color: (1.0, 0.0, 0.0)},
        PerInstance { id: 2, w_position: ( 0.0, 0.0, 0.0), color: (1.0, 0.0, 0.0)},
        PerInstance { id: 3, w_position: ( 1.0, 0.0, 0.0), color: (1.0, 0.0, 0.0)},
    ];

    let mut picking_texture: Option<glium::texture::UnsignedTexture2d> = None;
    let mut picking_pbo: glium::texture::pixel_buffer::PixelBuffer<u32>
        = glium::texture::pixel_buffer::PixelBuffer::new_empty(&display, 1);

    let mut cursor_position: Option<(i32, i32)> = None;

    // the main loop
    support::start_loop(|| {
        camera.update();

        // determing which object has been picked at the previous frame
        let picked_object = {
            let data = picking_pbo.read().map(|d| d[0]).unwrap_or(0);
            if data != 0 {
                Some(data - 1)//for this to work the id of a PerInstance has to be the index of it +1
            } else {
                None
            }
        };

        if let Some(index) = picked_object {
            per_instance[index as usize] = PerInstance { id: index + 1, w_position: per_instance[index as usize].w_position, color: (0.0, 1.0, 0.0) };
        } else {
            per_instance = vec![
                PerInstance { id: 1, w_position: (-1.0, 0.0, 0.0), color: (1.0, 0.0, 0.0)},
                PerInstance { id: 2, w_position: ( 0.0, 0.0, 0.0), color: (1.0, 0.0, 0.0)},
                PerInstance { id: 3, w_position: ( 1.0, 0.0, 0.0), color: (1.0, 0.0, 0.0)},
            ];
        }

        // building the uniforms
        let uniforms = uniform! {
            persp_matrix: camera.get_perspective(),
            view_matrix: camera.get_view(),
        };

        // draw parameters
        let params = glium::DrawParameters {
            depth: glium::Depth {
                test: glium::DepthTest::IfLess,
                write: true,
                .. Default::default()
            },
            .. Default::default()
        };

        let per_instance_buffer = glium::vertex::VertexBuffer::new(&display, &per_instance).unwrap();

        // drawing a frame
        let mut target = display.draw();
        target.clear_color_and_depth((0.0, 0.0, 0.0, 0.0), 1.0);

        //update picking texture
        if picking_texture.is_none()
        || (picking_texture.as_ref().unwrap().get_width(), picking_texture.as_ref().unwrap().get_height().unwrap()) != target.get_dimensions() {
            println!("new pick_tex: {:?}", target.get_dimensions());
            picking_texture = Some(glium::texture::UnsignedTexture2d::empty_with_format(
                &display,
                glium::texture::UncompressedUintFormat::U32,
                glium::texture::MipmapsOption::NoMipmap,
                target.get_dimensions().0, target.get_dimensions().1
            ).unwrap())
        }

        // drawing the models and pass the picking texture
        if let Some(picking_tex) = picking_texture.as_ref() {
            let depth_buffer = glium::framebuffer::DepthRenderBuffer::new(
                &display,
                glium::texture::DepthFormat::F32,
                picking_texture.as_ref().unwrap().get_width(),
                picking_texture.as_ref().unwrap().get_height().unwrap()
            ).unwrap();
            let mut picking_target = glium::framebuffer::SimpleFrameBuffer::with_depth_buffer(&display, picking_tex, &depth_buffer).unwrap();
            picking_target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
            picking_target.draw((&vertex_buffer, per_instance_buffer.per_instance().unwrap()),
                        &glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList),
                        &picking_program, &uniforms, &params).unwrap();
        }
        target.draw((&vertex_buffer, per_instance_buffer.per_instance().unwrap()),
                    &glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList),
                    &program, &uniforms, &params).unwrap();
        target.finish().unwrap();

        // committing into the picking pbo
        if let (Some(cursor), Some(ref picking_texture)) = (cursor_position, picking_texture.as_ref()) {
            let read_target = glium::Rect {
                //left: ((cursor.0 as f32 + 1.0) * 0.5 * picking_texture.get_width() as f32) as u32,
                //bottom: ((cursor.1 as f32 + 1.0) * 0.5 * picking_texture.get_height().unwrap() as f32) as u32,
                left: cursor.0 as u32,
                bottom: picking_texture.get_height().unwrap() - cursor.1 as u32,
                width: 1,
                height: 1,
            };

            if read_target.left >= 0 && read_target.left < picking_texture.get_width() &&
               read_target.bottom >= 0 && read_target.bottom < picking_texture.get_height().unwrap() {
                //println!("writing to pixel_buffer");
                picking_texture.main_level()
                    .first_layer()
                    .into_image(None).unwrap()
                    .raw_read_to_pixel_buffer(&read_target, &picking_pbo);
            } else {
                picking_pbo.write(&[0]);
            }
        } else {
            picking_pbo.write(&[0]);
        }

        // polling and handling the events received by the window
        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return support::Action::Stop,
                glutin::Event::MouseMoved(m) => cursor_position = Some(m),
                ev => camera.process_input(&ev),
            }
        }

        support::Action::Continue
    });
}
<commit_msg>cleaned up and fixed<commit_after>#[macro_use]
extern crate glium;

use glium::Surface;
use glium::glutin;

mod support;

#[derive(Copy, Clone, Debug)]
struct PerInstance {
    pub id: u32,
    pub w_position: (f32, f32, f32),
    pub color: (f32, f32, f32),
}
implement_vertex!(PerInstance, id, w_position, color);

fn main() {
    use glium::DisplayBuild;

    // building the display, ie. the main object
    let display = glutin::WindowBuilder::new()
        .with_depth_buffer(24)
        .build_glium()
        .unwrap();

    // building the vertex and index buffers
    let vertex_buffer = support::load_wavefront(&display, include_bytes!("support/teapot.obj"));

    // the program
    let program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 persp_matrix;
                uniform mat4 view_matrix;

                in uint id;
                in vec3 w_position;
                in vec3 color;
                in vec3 position;
                in vec3 normal;
                out vec3 v_normal;
                out vec3 v_color;

                void main() {
                    v_normal = normal;
                    v_color = color;
                    gl_Position = persp_matrix * view_matrix * vec4(position * 0.005 + w_position, 1.0);
                }
            ",

            fragment: "
                #version 140

                in vec3 v_normal;
                in vec3 v_color;
                out vec4 f_color;

                const vec3 LIGHT = vec3(-0.2, 0.8, 0.1);

                void main() {
                    float lum = max(dot(normalize(v_normal), normalize(LIGHT)), 0.0);
                    vec3 color = (0.3 + 0.7 * lum) * v_color;
                    f_color = vec4(color, 1.0);
                }
            ",
        },
    ).unwrap();

    let picking_program = program!(&display,
        140 => {
            vertex: "
                #version 140

                uniform mat4 persp_matrix;
                uniform mat4 view_matrix;

                in uint id;
                in vec3 w_position;
                in vec3 color;
                in vec3 position;
                in vec3 normal;
                flat out uint v_id;

                void main() {
                    v_id = id;
                    gl_Position = persp_matrix * view_matrix * vec4(position * 0.005 + w_position, 1.0);
                }
            ",

            fragment: "
                #version 140

                flat in uint v_id;
                out uint f_id;

                void main() {
                    f_id = v_id;
                }
            ",
        },
    ).unwrap();

    //
    let mut camera = support::camera::CameraState::new();
    camera.set_position((0.0, 0.0, 1.5));
    camera.set_direction((0.0, 0.0, 1.0));

    //id's must be unique and != 0
    let mut per_instance = vec![
        PerInstance { id: 1, w_position: (-1.0, 0.0, 0.0), color: (1.0, 0.0, 0.0)},
        PerInstance { id: 2, w_position: ( 0.0, 0.0, 0.0), color: (1.0, 0.0, 0.0)},
        PerInstance { id: 3, w_position: ( 1.0, 0.0, 0.0), color: (1.0, 0.0, 0.0)},
    ];
    per_instance.sort_by(|a, b| a.id.cmp(&b.id));
    let original = per_instance.clone();

    let mut picking_attachments: Option<(glium::texture::UnsignedTexture2d, glium::framebuffer::DepthRenderBuffer)> = None;
    let picking_pbo: glium::texture::pixel_buffer::PixelBuffer<u32>
        = glium::texture::pixel_buffer::PixelBuffer::new_empty(&display, 1);

    let mut cursor_position: Option<(i32, i32)> = None;

    // the main loop
    support::start_loop(|| {
        camera.update();

        // determing which object has been picked at the previous frame
        let picked_object = {
            let data = picking_pbo.read().map(|d| d[0]).unwrap_or(0);
            if data != 0 {
                per_instance.binary_search_by(|x| x.id.cmp(&data)).ok()
            } else {
                None
            }
        };

        if let Some(index) = picked_object {
            per_instance[index as usize] = PerInstance {
                id: per_instance[index as usize].id,
                w_position: per_instance[index as usize].w_position,
                color: (0.0, 1.0, 0.0)
            };
        } else {
            per_instance = original.clone();
        }

        // building the uniforms
        let uniforms = uniform! {
            persp_matrix: camera.get_perspective(),
            view_matrix: camera.get_view(),
        };

        // draw parameters
        let params = glium::DrawParameters {
            depth: glium::Depth {
                test: glium::DepthTest::IfLess,
                write: true,
                .. Default::default()
            },
            .. Default::default()
        };

        let per_instance_buffer = glium::vertex::VertexBuffer::new(&display, &per_instance).unwrap();

        // drawing a frame
        let mut target = display.draw();
        target.clear_color_and_depth((0.0, 0.0, 0.0, 0.0), 1.0);

        //update picking texture
        if picking_attachments.is_none() || (
            picking_attachments.as_ref().unwrap().0.get_width(),
            picking_attachments.as_ref().unwrap().0.get_height().unwrap()
        ) != target.get_dimensions() {
            let (width, height) = target.get_dimensions();
            picking_attachments = Some((
                glium::texture::UnsignedTexture2d::empty_with_format(
                    &display,
                    glium::texture::UncompressedUintFormat::U32,
                    glium::texture::MipmapsOption::NoMipmap,
                    width, height,
                ).unwrap(),
                glium::framebuffer::DepthRenderBuffer::new(
                    &display,
                    glium::texture::DepthFormat::F32,
                    width, height,
                ).unwrap()
            ))
        }

        // drawing the models and pass the picking texture
        if let Some((ref picking_tex, ref depth_buffer)) = picking_attachments {
            let mut picking_target = glium::framebuffer::SimpleFrameBuffer::with_depth_buffer(&display, picking_tex, depth_buffer).unwrap();
            picking_target.clear_color_and_depth((0.0, 0.0, 0.0, 1.0), 1.0);
            picking_target.draw((&vertex_buffer, per_instance_buffer.per_instance().unwrap()),
                        &glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList),
                        &picking_program, &uniforms, &params).unwrap();
        }
        target.draw((&vertex_buffer, per_instance_buffer.per_instance().unwrap()),
                    &glium::index::NoIndices(glium::index::PrimitiveType::TrianglesList),
                    &program, &uniforms, &params).unwrap();
        target.finish().unwrap();

        // committing into the picking pbo
        if let (Some(cursor), Some(&(ref picking_texture, _))) = (cursor_position, picking_attachments.as_ref()) {
            let read_target = glium::Rect {
                //left: ((cursor.0 as f32 + 1.0) * 0.5 * picking_texture.get_width() as f32) as u32,
                //bottom: ((cursor.1 as f32 + 1.0) * 0.5 * picking_texture.get_height().unwrap() as f32) as u32,
                left: cursor.0 as u32,
                bottom: picking_texture.get_height().unwrap() - cursor.1 as u32,
                width: 1,
                height: 1,
            };

            if read_target.left < picking_texture.get_width()
            && read_target.bottom < picking_texture.get_height().unwrap() {
                //println!("writing to pixel_buffer");
                picking_texture.main_level()
                    .first_layer()
                    .into_image(None).unwrap()
                    .raw_read_to_pixel_buffer(&read_target, &picking_pbo);
            } else {
                picking_pbo.write(&[0]);
            }
        } else {
            picking_pbo.write(&[0]);
        }

        // polling and handling the events received by the window
        for event in display.poll_events() {
            match event {
                glutin::Event::Closed => return support::Action::Stop,
                glutin::Event::MouseMoved(m) => cursor_position = Some(m),
                ev => camera.process_input(&ev),
            }
        }

        support::Action::Continue
    });
}
<|endoftext|>


<commit_before>//! This is NOT a real example. This is a test designed to see if we can actually run the turtle
//! process

use std::process;

use turtle::Turtle;

fn main() {
    let mut turtle = Turtle::new();

    turtle.set_speed(2);
    turtle.right(90.0);
    turtle.forward(50.0);

    //TODO: Exiting the process currently doesn't cause the window to get closed. We should add a
    // `close(self)` or `quit(self)` method to `Drawing` that closes the window explicitly.
    process::exit(0);
}
<commit_msg>update runtest.rs example with Drawing::destroy()<commit_after>//! This is NOT a real example. This is a test designed to see if we can actually run the turtle
//! process
// To run, use the command: cargo run --features unstable --example runtest
#[cfg(all(not(feature = "unstable")))]
compile_error!("This example relies on unstable features. Run with `--features unstable`");

use turtle::Drawing;

fn main() {
    let mut drawing = Drawing::new();
    let mut turtle = drawing.add_turtle();

    turtle.set_speed(2);
    turtle.right(90.0);
    turtle.forward(50.0);

    drawing.destroy();
}
<|endoftext|>