<commit_before>//! Driver for rust-analyzer.
//!
//! Based on cli flags, either spawns an LSP server, or runs a batch analysis
mod logger;
mod rustc_wrapper;

use std::{env, fs, path::Path, process};

use lsp_server::Connection;
use project_model::ProjectManifest;
use rust_analyzer::{cli::flags, config::Config, from_json, lsp_ext::supports_utf8, Result};
use vfs::AbsPathBuf;

#[cfg(all(feature = "mimalloc"))]
#[global_allocator]
static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;

#[cfg(all(feature = "jemalloc", not(target_env = "msvc")))]
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

fn main() {
    if std::env::var("RA_RUSTC_WRAPPER").is_ok() {
        let mut args = std::env::args_os();
        let _me = args.next().unwrap();
        let rustc = args.next().unwrap();
        let code = match rustc_wrapper::run_rustc_skipping_cargo_checking(rustc, args.collect()) {
            Ok(rustc_wrapper::ExitCode(code)) => code.unwrap_or(102),
            Err(err) => {
                eprintln!("{}", err);
                101
            }
        };
        process::exit(code);
    }

    if let Err(err) = try_main() {
        tracing::error!("Unexpected error: {}", err);
        eprintln!("{}", err);
        process::exit(101);
    }
}

fn try_main() -> Result<()> {
    let flags = flags::RustAnalyzer::from_env()?;

    #[cfg(debug_assertions)]
    if flags.wait_dbg || env::var("RA_WAIT_DBG").is_ok() {
        #[allow(unused_mut)]
        let mut d = 4;
        while d == 4 {
            d = 4;
        }
    }

    let mut log_file = flags.log_file.as_deref();

    let env_log_file = env::var("RA_LOG_FILE").ok();
    if let Some(env_log_file) = env_log_file.as_deref() {
        log_file = Some(Path::new(env_log_file));
    }

    setup_logging(log_file)?;
    let verbosity = flags.verbosity();

    match flags.subcommand {
        flags::RustAnalyzerCmd::LspServer(cmd) => {
            if cmd.print_config_schema {
                println!("{:#}", Config::json_schema());
                return Ok(());
            }
            if cmd.version {
                println!("rust-analyzer {}", env!("REV"));
                return Ok(());
            }
            if cmd.help {
                println!("{}", flags::RustAnalyzer::HELP);
                return Ok(());
            }
            with_extra_thread("rust-analyzer server thread", run_server)?;
        }
        flags::RustAnalyzerCmd::ProcMacro(flags::ProcMacro) => {
            with_extra_thread("rust-analyzer proc-macro expander", || {
                proc_macro_srv::cli::run().map_err(Into::into)
            })?;
        }
        flags::RustAnalyzerCmd::Parse(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::Symbols(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::Highlight(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::AnalysisStats(cmd) => cmd.run(verbosity)?,
        flags::RustAnalyzerCmd::Diagnostics(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::Ssr(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::Search(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::Lsif(cmd) => cmd.run()?,
    }
    Ok(())
}

fn setup_logging(log_file: Option<&Path>) -> Result<()> {
    if cfg!(windows) {
        // This is required so that windows finds our pdb that is placed right beside the exe.
        // By default it doesn't look at the folder the exe resides in, only in the current working
        // directory which we set to the project workspace.
        // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/general-environment-variables
        // https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/nf-dbghelp-syminitialize
        if let Ok(path) = env::current_exe() {
            if let Some(path) = path.parent() {
                env::set_var("_NT_SYMBOL_PATH", path);
            }
        }
    }
    if env::var("RUST_BACKTRACE").is_err() {
        env::set_var("RUST_BACKTRACE", "short");
    }

    let log_file = match log_file {
        Some(path) => {
            if let Some(parent) = path.parent() {
                let _ = fs::create_dir_all(parent);
            }
            Some(fs::File::create(path)?)
        }
        None => None,
    };
    let filter = env::var("RA_LOG").ok();
    // deliberately enable all `error` logs if the user has not set RA_LOG, as there is usually useful
    // information in there for debugging
    logger::Logger::new(log_file, filter.as_deref().or(Some("error"))).install()?;

    profile::init();

    Ok(())
}

const STACK_SIZE: usize = 1024 * 1024 * 8;

/// Parts of rust-analyzer can use a lot of stack space, and some operating systems only give us
/// 1 MB by default (eg. Windows), so this spawns a new thread with hopefully sufficient stack
/// space.
fn with_extra_thread(
    thread_name: impl Into<String>,
    f: impl FnOnce() -> Result<()> + Send + 'static,
) -> Result<()> {
    let handle =
        std::thread::Builder::new().name(thread_name.into()).stack_size(STACK_SIZE).spawn(f)?;
    match handle.join() {
        Ok(res) => res,
        Err(panic) => std::panic::resume_unwind(panic),
    }
}

fn run_server() -> Result<()> {
    tracing::info!("server version {} will start", env!("REV"));

    let (connection, io_threads) = Connection::stdio();

    let (initialize_id, initialize_params) = connection.initialize_start()?;
    tracing::info!("InitializeParams: {}", initialize_params);
    let initialize_params =
        from_json::<lsp_types::InitializeParams>("InitializeParams", &initialize_params)?;

    let root_path = match initialize_params
        .root_uri
        .and_then(|it| it.to_file_path().ok())
        .and_then(|it| AbsPathBuf::try_from(it).ok())
    {
        Some(it) => it,
        None => {
            let cwd = env::current_dir()?;
            AbsPathBuf::assert(cwd)
        }
    };

    let mut config = Config::new(root_path, initialize_params.capabilities);
    if let Some(json) = initialize_params.initialization_options {
        if let Err(e) = config.update(json) {
            use lsp_types::{
                notification::{Notification, ShowMessage},
                MessageType, ShowMessageParams,
            };
            let not = lsp_server::Notification::new(
                ShowMessage::METHOD.to_string(),
                ShowMessageParams { typ: MessageType::WARNING, message: e.to_string() },
            );
            connection.sender.send(lsp_server::Message::Notification(not)).unwrap();
        }
    }

    let server_capabilities = rust_analyzer::server_capabilities(&config);

    let initialize_result = lsp_types::InitializeResult {
        capabilities: server_capabilities,
        server_info: Some(lsp_types::ServerInfo {
            name: String::from("rust-analyzer"),
            version: Some(String::from(env!("REV"))),
        }),
        offset_encoding: if supports_utf8(config.caps()) {
            Some("utf-8".to_string())
        } else {
            None
        },
    };

    let initialize_result = serde_json::to_value(initialize_result).unwrap();

    connection.initialize_finish(initialize_id, initialize_result)?;

    if let Some(client_info) = initialize_params.client_info {
        tracing::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default());
    }

    if config.linked_projects().is_empty() && config.detached_files().is_empty() {
        let workspace_roots = initialize_params
            .workspace_folders
            .map(|workspaces| {
                workspaces
                    .into_iter()
                    .filter_map(|it| it.uri.to_file_path().ok())
                    .filter_map(|it| AbsPathBuf::try_from(it).ok())
                    .collect::<Vec<_>>()
            })
            .filter(|workspaces| !workspaces.is_empty())
            .unwrap_or_else(|| vec![config.root_path().clone()]);

        let discovered = ProjectManifest::discover_all(&workspace_roots);
        tracing::info!("discovered projects: {:?}", discovered);
        if discovered.is_empty() {
            tracing::error!("failed to find any projects in {:?}", workspace_roots);
        }
        config.discovered_projects = Some(discovered);
    }

    rust_analyzer::main_loop(config, connection)?;

    io_threads.join()?;
    tracing::info!("server did shut down");
    Ok(())
}
<commit_msg>Shorten main thread name<commit_after>//! Driver for rust-analyzer.
//!
//! Based on cli flags, either spawns an LSP server, or runs a batch analysis
mod logger;
mod rustc_wrapper;

use std::{env, fs, path::Path, process};

use lsp_server::Connection;
use project_model::ProjectManifest;
use rust_analyzer::{cli::flags, config::Config, from_json, lsp_ext::supports_utf8, Result};
use vfs::AbsPathBuf;

#[cfg(all(feature = "mimalloc"))]
#[global_allocator]
static ALLOC: mimalloc::MiMalloc = mimalloc::MiMalloc;

#[cfg(all(feature = "jemalloc", not(target_env = "msvc")))]
#[global_allocator]
static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;

fn main() {
    if std::env::var("RA_RUSTC_WRAPPER").is_ok() {
        let mut args = std::env::args_os();
        let _me = args.next().unwrap();
        let rustc = args.next().unwrap();
        let code = match rustc_wrapper::run_rustc_skipping_cargo_checking(rustc, args.collect()) {
            Ok(rustc_wrapper::ExitCode(code)) => code.unwrap_or(102),
            Err(err) => {
                eprintln!("{}", err);
                101
            }
        };
        process::exit(code);
    }

    if let Err(err) = try_main() {
        tracing::error!("Unexpected error: {}", err);
        eprintln!("{}", err);
        process::exit(101);
    }
}

fn try_main() -> Result<()> {
    let flags = flags::RustAnalyzer::from_env()?;

    #[cfg(debug_assertions)]
    if flags.wait_dbg || env::var("RA_WAIT_DBG").is_ok() {
        #[allow(unused_mut)]
        let mut d = 4;
        while d == 4 {
            d = 4;
        }
    }

    let mut log_file = flags.log_file.as_deref();

    let env_log_file = env::var("RA_LOG_FILE").ok();
    if let Some(env_log_file) = env_log_file.as_deref() {
        log_file = Some(Path::new(env_log_file));
    }

    setup_logging(log_file)?;
    let verbosity = flags.verbosity();

    match flags.subcommand {
        flags::RustAnalyzerCmd::LspServer(cmd) => {
            if cmd.print_config_schema {
                println!("{:#}", Config::json_schema());
                return Ok(());
            }
            if cmd.version {
                println!("rust-analyzer {}", env!("REV"));
                return Ok(());
            }
            if cmd.help {
                println!("{}", flags::RustAnalyzer::HELP);
                return Ok(());
            }
            with_extra_thread("LspServer", run_server)?;
        }
        flags::RustAnalyzerCmd::ProcMacro(flags::ProcMacro) => {
            with_extra_thread("MacroExpander", || proc_macro_srv::cli::run().map_err(Into::into))?;
        }
        flags::RustAnalyzerCmd::Parse(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::Symbols(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::Highlight(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::AnalysisStats(cmd) => cmd.run(verbosity)?,
        flags::RustAnalyzerCmd::Diagnostics(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::Ssr(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::Search(cmd) => cmd.run()?,
        flags::RustAnalyzerCmd::Lsif(cmd) => cmd.run()?,
    }
    Ok(())
}

fn setup_logging(log_file: Option<&Path>) -> Result<()> {
    if cfg!(windows) {
        // This is required so that windows finds our pdb that is placed right beside the exe.
        // By default it doesn't look at the folder the exe resides in, only in the current working
        // directory which we set to the project workspace.
        // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/general-environment-variables
        // https://docs.microsoft.com/en-us/windows/win32/api/dbghelp/nf-dbghelp-syminitialize
        if let Ok(path) = env::current_exe() {
            if let Some(path) = path.parent() {
                env::set_var("_NT_SYMBOL_PATH", path);
            }
        }
    }
    if env::var("RUST_BACKTRACE").is_err() {
        env::set_var("RUST_BACKTRACE", "short");
    }

    let log_file = match log_file {
        Some(path) => {
            if let Some(parent) = path.parent() {
                let _ = fs::create_dir_all(parent);
            }
            Some(fs::File::create(path)?)
        }
        None => None,
    };
    let filter = env::var("RA_LOG").ok();
    // deliberately enable all `error` logs if the user has not set RA_LOG, as there is usually useful
    // information in there for debugging
    logger::Logger::new(log_file, filter.as_deref().or(Some("error"))).install()?;

    profile::init();

    Ok(())
}

const STACK_SIZE: usize = 1024 * 1024 * 8;

/// Parts of rust-analyzer can use a lot of stack space, and some operating systems only give us
/// 1 MB by default (eg. Windows), so this spawns a new thread with hopefully sufficient stack
/// space.
fn with_extra_thread(
    thread_name: impl Into<String>,
    f: impl FnOnce() -> Result<()> + Send + 'static,
) -> Result<()> {
    let handle =
        std::thread::Builder::new().name(thread_name.into()).stack_size(STACK_SIZE).spawn(f)?;
    match handle.join() {
        Ok(res) => res,
        Err(panic) => std::panic::resume_unwind(panic),
    }
}

fn run_server() -> Result<()> {
    tracing::info!("server version {} will start", env!("REV"));

    let (connection, io_threads) = Connection::stdio();

    let (initialize_id, initialize_params) = connection.initialize_start()?;
    tracing::info!("InitializeParams: {}", initialize_params);
    let initialize_params =
        from_json::<lsp_types::InitializeParams>("InitializeParams", &initialize_params)?;

    let root_path = match initialize_params
        .root_uri
        .and_then(|it| it.to_file_path().ok())
        .and_then(|it| AbsPathBuf::try_from(it).ok())
    {
        Some(it) => it,
        None => {
            let cwd = env::current_dir()?;
            AbsPathBuf::assert(cwd)
        }
    };

    let mut config = Config::new(root_path, initialize_params.capabilities);
    if let Some(json) = initialize_params.initialization_options {
        if let Err(e) = config.update(json) {
            use lsp_types::{
                notification::{Notification, ShowMessage},
                MessageType, ShowMessageParams,
            };
            let not = lsp_server::Notification::new(
                ShowMessage::METHOD.to_string(),
                ShowMessageParams { typ: MessageType::WARNING, message: e.to_string() },
            );
            connection.sender.send(lsp_server::Message::Notification(not)).unwrap();
        }
    }

    let server_capabilities = rust_analyzer::server_capabilities(&config);

    let initialize_result = lsp_types::InitializeResult {
        capabilities: server_capabilities,
        server_info: Some(lsp_types::ServerInfo {
            name: String::from("rust-analyzer"),
            version: Some(String::from(env!("REV"))),
        }),
        offset_encoding: if supports_utf8(config.caps()) {
            Some("utf-8".to_string())
        } else {
            None
        },
    };

    let initialize_result = serde_json::to_value(initialize_result).unwrap();

    connection.initialize_finish(initialize_id, initialize_result)?;

    if let Some(client_info) = initialize_params.client_info {
        tracing::info!("Client '{}' {}", client_info.name, client_info.version.unwrap_or_default());
    }

    if config.linked_projects().is_empty() && config.detached_files().is_empty() {
        let workspace_roots = initialize_params
            .workspace_folders
            .map(|workspaces| {
                workspaces
                    .into_iter()
                    .filter_map(|it| it.uri.to_file_path().ok())
                    .filter_map(|it| AbsPathBuf::try_from(it).ok())
                    .collect::<Vec<_>>()
            })
            .filter(|workspaces| !workspaces.is_empty())
            .unwrap_or_else(|| vec![config.root_path().clone()]);

        let discovered = ProjectManifest::discover_all(&workspace_roots);
        tracing::info!("discovered projects: {:?}", discovered);
        if discovered.is_empty() {
            tracing::error!("failed to find any projects in {:?}", workspace_roots);
        }
        config.discovered_projects = Some(discovered);
    }

    rust_analyzer::main_loop(config, connection)?;

    io_threads.join()?;
    tracing::info!("server did shut down");
    Ok(())
}
<|endoftext|>


<commit_before>// only-linux: Uses Linux-only APIs

#![feature(rustc_private)]
extern crate libc;

fn main() {
    let mut buf = [0u8; 5];
    unsafe {
		assert_eq!(libc::syscall(libc::SYS_getrandom, 0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0);
        assert_eq!(libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5);
    }
}
<commit_msg>Test 'libc::getrandom' as well<commit_after>// only-linux: Uses Linux-only APIs

#![feature(rustc_private)]
extern crate libc;

fn main() {
    let mut buf = [0u8; 5];
    unsafe {
		assert_eq!(libc::syscall(libc::SYS_getrandom, 0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0);
        assert_eq!(libc::syscall(libc::SYS_getrandom, buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5);

        assert_eq!(libc::getrandom(0 as *mut libc::c_void, 0 as libc::size_t, 0 as libc::c_uint), 0);
        assert_eq!(libc::getrandom(buf.as_mut_ptr() as *mut libc::c_void, 5 as libc::size_t, 0 as libc::c_uint), 5);
    }
}
<|endoftext|>


<commit_before>extern crate time;

use std::rand::{Rng, SeedableRng, StdRng};
use std::collections::HashMap;
use time::precise_time_ns;
use std::io::{File, BufferedReader};
use std::fmt;

pub type Node = uint;

#[deriving(Show)]
pub struct NodePt {
    id: Node,
    x: f64,
    y: f64
}

impl NodePt {
    fn new(nodeId: Node, x: f64, y: f64) -> NodePt {
        NodePt {
            id: nodeId,
            x: x,
            y: y
        }
    }

    fn distance_to(self, other: NodePt) -> f64 {
        let xx = (self.x - other.x) * (self.x - other.x);
        let yy = (self.y - other.y) * (self.y - other.y);

        (xx+yy).sqrt()
    }
}

impl PartialEq for NodePt {
    fn eq(&self, other: &NodePt) -> bool {
        self.id == other.id
    }

    fn ne(&self, other: &NodePt) -> bool {
        self.id != other.id
    }
}

#[deriving(Show, Clone)]
pub struct Edge {
    from: Node,
    to: Node,
    weight: f64
}

impl Edge {
    fn new(a: NodePt, b: NodePt) -> Edge {
        Edge {
            from: a.id,
            to: b.id,
            weight: a.distance_to(b)
        }
    }
}

#[deriving(Show, Clone)]
pub struct Tour {
    nodes: Vec<Node>,
    total_weight: f64
}

impl PartialEq for Tour {
    fn eq(&self, other: &Tour) -> bool {
        self.nodes == other.nodes
    }

    fn ne(&self, other: &Tour) -> bool {
        self.nodes != other.nodes
    }
}

impl PartialOrd for Tour {
    fn lt(&self, other: &Tour) -> bool {
        self.total_weight < other.total_weight
    }
}

impl Tour {
    fn new(nodes: Vec<Node>, weight: f64) -> Tour {
        Tour {
            nodes: nodes,
            total_weight: weight
        }
    }

    // TODO add weight between first and last node to the tour weight
    fn calc_tour_weight(tour: &Vec<Node>, graph: &Graph) -> f64 {
        let mut tour_weight = 0.0;
        let mut last_node = tour.get(0u);

        for node in tour.iter() {
            tour_weight += graph.get(*last_node, *node);
            last_node = node;
        }

        tour_weight
    }
    // TODO for ease of crossover between tours, don't add the
    //      first node again
    fn random_tour<R: Rng>(rng: &mut R, graph: &Graph) -> Tour {
        let mut tour_nodes = graph.nodes();
        rng.shuffle(tour_nodes.as_mut_slice());
        let last: Node = *tour_nodes.last().unwrap();
        tour_nodes.insert(0, last);
        let tour_weight = Tour::calc_tour_weight(&tour_nodes, graph);
        Tour::new(tour_nodes, tour_weight)
    }

    fn mutate<R: Rng>(&self, rng: &mut R, graph: &Graph, mutation_rate: f64) -> Tour {
        let size = self.nodes.len() as f64;
        let mut mutated: Vec<Node> = self.nodes.clone();

        for i in range(0, self.nodes.len()) {
            let t = rng.gen::<f64>();
            if t < mutation_rate {
                let j = (rng.gen::<f64>() * size) as uint;
                mutated.as_mut_slice().swap(i, j);
            }
        }
        let weight = Tour::calc_tour_weight(&mutated, graph);
        Tour {
            nodes: mutated,
            total_weight: weight
        }
    }

    fn crossover<R: Rng>(&self, other: Tour, graph: &Graph, rng: &mut R) -> Tour {
        let size = self.nodes.len();
        let mut start = (rng.gen::<f64>() * (size as f64)) as uint;
        let mut end = (rng.gen::<f64>() * (size as f64)) as uint;
        if start == end {
            return self.clone()
        }

        if end > start {
            std::mem::swap(&mut start, &mut end);
        }
        // TODO fix this (produces invalid tours)
        let new_tour = Vec::from_fn(size, |i| {
            if i >= start && i <= end {
                *self.nodes.get(i)
            } else {
                *other.nodes.get(i)
            }
        });

        let tour_weight = Tour::calc_tour_weight(&new_tour, graph);
        Tour::new(new_tour, tour_weight)
    }
}

#[deriving(Show, Clone)]
pub struct Graph {
    adj_list: HashMap<Node, Vec<Edge>>
}

impl Graph {
    fn new(adj_list: HashMap<Node, Vec<Edge>>) -> Graph {
        Graph {
            adj_list: adj_list
        }
    }

    fn from_nodes(nodes: Vec<NodePt>) -> Graph {
        let mut map: HashMap<Node, Vec<Edge>> = HashMap::new();
        for i in range(0, nodes.len()) {
            let mut adj_edges: Vec<Edge> = Vec::new();

            for j in range(0, nodes.len()) {
                let a = nodes.get(i);
                let b = nodes.get(j);
                if i != j {
                    adj_edges.push(Edge::new(*a, *b));
                }
            }

            map.insert(i, adj_edges);
        }

        Graph::new(map)
    }

    fn random_graph<R: Rng>(rng: &mut R, num_nodes: uint, x_max: f64, y_max: f64) -> Graph {
        let points = rng.gen_iter::<(f64, f64)>()
            .enumerate()
            .map(|(idx, (x, y))| NodePt::new(idx, x * x_max, y * y_max))
            .take(num_nodes)
            .collect();

        Graph::from_nodes(points)
    }

    fn get(&self, n: Node, m: Node) -> f64 {
        if n == m {
            0.0
        } else {
            let edges = self.adj_list.get(&n);
            let result = edges.iter().filter(|edge| edge.to == m).nth(0);
            match result {
                Some(edge) => edge.weight,
                None => fail!("No edge found!")
            }
        }
    }

    fn size(&self) -> uint {
        self.adj_list.len()
    }

    fn nodes(&self) -> Vec<Node> {
        range(0, self.size()).collect()
    }

    #[allow(dead_code)]
    fn from_file(file_path: &str) -> Graph {
        let path = Path::new(file_path);
        let mut file = BufferedReader::new(File::open(&path));
        let mut nodes: Vec<NodePt> = Vec::new();
        let mut i = 0u;

        for line in file.lines() {
            let mut numbers: Vec<f64> = Vec::new();
            // This could be a lot nicer
            match line {
                Ok(val) => {
                    for token in val.as_slice().split(' ') {
                        if token == "\n" {
                            continue
                        }

                        let n = match from_str::<f64>(token) {
                            Some(num) => num,
                            None => continue
                        };
                        numbers.push(n);
                    }
                },
                Err(_) => fail!("Failed reading file.")
            }

            if numbers.len() == 2 {
                let point = NodePt::new(i, *numbers.get(0), *numbers.get(1));
                nodes.push(point);
            }

            i += 1;
        }

        Graph::from_nodes(nodes)
    }
}

struct Population {
    rng: StdRng,
    graph: Box<Graph>,
    population: Vec<Tour>,
    mutation_rate: f64,
    tournament_size: uint
}

impl Population {
    fn new(population_count: uint, graph: Box<Graph>, mutation_rate: f64, tournament_size: uint, mut rng: StdRng) -> Population {
        let population = Vec::from_fn(population_count, |_| Tour::random_tour(&mut rng, graph));

        Population {
            rng: rng,
            graph: graph,
            population: population,
            mutation_rate: mutation_rate,
            tournament_size: tournament_size
        }
    }

    fn fittest(&self) -> Tour {
        find_min(&self.population)
    }

    fn tournament_selection(&mut self) -> Tour {
        let size = self.population.len();
        let mut buffer: Vec<Tour> = Vec::new();
        for _ in range(0, self.tournament_size) {
            let t = (self.rng.gen::<f64>() * (size as f64)) as uint;
            buffer.push(self.population.get(t).clone());
        }
        find_min(&buffer)
    }

    fn evolve(&mut self) -> Population {
        let mut new_population: Vec<Tour> = Vec::new();

        for _ in range(0, self.population.len()) {
            let parent1 = self.tournament_selection();
            let parent2 = self.tournament_selection();
            let child: Tour = parent1.crossover(parent2, self.graph, &mut self.rng);
            new_population.push(child);
        }

        let mutated = new_population.iter().map(|tour| tour.mutate(&mut self.rng, self.graph, self.mutation_rate)).collect();

        Population {
            rng: self.rng,
            graph: self.graph.clone(),
            population: mutated,
            mutation_rate: self.mutation_rate,
            tournament_size: self.tournament_size
        }
    }
}

impl fmt::Show for Population {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Population: {}", self.population)
    }
}

fn find_min<E: PartialOrd+Clone>(xs: &Vec<E>) -> E {
    let ref min = *xs.iter().fold(xs.get(0), |min, next| if next < min {next} else {min});
    min.clone()
}

fn main() {
    // let mut rng: StdRng = match StdRng::new() {
    //     Ok(r) => r,
    //     Err(why) => fail!("failed to acquire RNG")
    // };
    let mut rng: StdRng = SeedableRng::from_seed(&[12, 13, 14, 15]);
    let graph = Graph::random_graph(&mut rng, 10, 200.0, 200.0);
    //let graph = Graph::from_file("graph.txt");

    let mut pop = Population::new(10000, box graph, 0.01, 15, rng);
    println!("Fittest at start: {}", pop.fittest())

    let t0 = precise_time_ns();
    for _ in range(0, 100) {
        pop = pop.evolve();
    }
    let t1 = precise_time_ns();

    println!("Fittest at end: {}", pop.fittest())
    let dt = ((t1-t0) as f64) / 1e6;
    println!("t_avg = {} ms", dt / 100.0);
}<commit_msg>fixed todos and cleaned up main<commit_after>extern crate time;

use std::rand::{Rng, SeedableRng, StdRng};
use std::collections::HashMap;
use time::precise_time_ns;
use std::io::{File, BufferedReader};
use std::fmt;

pub type Node = uint;

#[deriving(Show)]
pub struct NodePt {
    id: Node,
    x: f64,
    y: f64
}

impl NodePt {
    fn new(nodeId: Node, x: f64, y: f64) -> NodePt {
        NodePt {
            id: nodeId,
            x: x,
            y: y
        }
    }

    fn distance_to(self, other: NodePt) -> f64 {
        let xx = (self.x - other.x) * (self.x - other.x);
        let yy = (self.y - other.y) * (self.y - other.y);

        (xx+yy).sqrt()
    }
}

impl PartialEq for NodePt {
    fn eq(&self, other: &NodePt) -> bool {
        self.id == other.id
    }

    fn ne(&self, other: &NodePt) -> bool {
        self.id != other.id
    }
}

#[deriving(Show, Clone)]
pub struct Edge {
    from: Node,
    to: Node,
    weight: f64
}

impl Edge {
    fn new(a: NodePt, b: NodePt) -> Edge {
        Edge {
            from: a.id,
            to: b.id,
            weight: a.distance_to(b)
        }
    }
}

#[deriving(Show, Clone)]
pub struct Tour {
    nodes: Vec<Node>,
    total_weight: f64
}

impl PartialEq for Tour {
    fn eq(&self, other: &Tour) -> bool {
        self.nodes == other.nodes
    }

    fn ne(&self, other: &Tour) -> bool {
        self.nodes != other.nodes
    }
}

impl PartialOrd for Tour {
    fn lt(&self, other: &Tour) -> bool {
        self.total_weight < other.total_weight
    }
}

impl Tour {
    fn new(nodes: Vec<Node>, weight: f64) -> Tour {
        Tour {
            nodes: nodes,
            total_weight: weight
        }
    }

    fn calc_tour_weight(tour: &Vec<Node>, graph: &Graph) -> f64 {
        let mut tour_weight = 0.0;
        let mut last_node = tour.get(0u);

        for node in tour.iter() {
            tour_weight += graph.get(*last_node, *node);
            last_node = node;
        }
        let last = match tour.last() {
            Some(l) => l,
            None => fail!("Empty tour!")
        };
        tour_weight += graph.get(*tour.get(0), *last);
        tour_weight
    }

    fn random_tour<R: Rng>(rng: &mut R, graph: &Graph) -> Tour {
        let mut tour_nodes = graph.nodes();
        rng.shuffle(tour_nodes.as_mut_slice());
        let tour_weight = Tour::calc_tour_weight(&tour_nodes, graph);
        Tour::new(tour_nodes, tour_weight)
    }

    fn mutate<R: Rng>(&self, rng: &mut R, graph: &Graph, mutation_rate: f64) -> Tour {
        let size = self.nodes.len() as f64;
        let mut mutated: Vec<Node> = self.nodes.clone();

        for i in range(0, self.nodes.len()) {
            let t = rng.gen::<f64>();
            if t < mutation_rate {
                let j = (rng.gen::<f64>() * size) as uint;
                mutated.as_mut_slice().swap(i, j);
            }
        }
        let weight = Tour::calc_tour_weight(&mutated, graph);
        Tour {
            nodes: mutated,
            total_weight: weight
        }
    }

    fn crossover<R: Rng>(&self, other: Tour, graph: &Graph, rng: &mut R) -> Tour {
        let size = self.nodes.len();
        let mut start = (rng.gen::<f64>() * (size as f64)) as uint;
        let mut end = (rng.gen::<f64>() * (size as f64)) as uint;
        if start == end {
            return self.clone()
        }

        if end > start {
            std::mem::swap(&mut start, &mut end);
        }

        let new_tour = Vec::from_fn(size, |i| {
            if i >= start && i <= end {
                Some(*self.nodes.get(i))
            } else {
                None
            }
        });

        let mut i = 0;
        let mut new_tour_2: Vec<Node> = Vec::new();
        for node in new_tour.iter() {
            match *node {
                Some(n) => new_tour_2.push(n),
                None => {
                    let v = Some(*other.nodes.get(i));
                    if !new_tour.contains(&v) {
                        new_tour_2.push(v.unwrap());
                    }
                    i += 1;
                }
            }
        }

        let tour_weight = Tour::calc_tour_weight(&new_tour_2, graph);
        Tour::new(new_tour_2, tour_weight)
    }
}

#[deriving(Show, Clone)]
pub struct Graph {
    adj_list: HashMap<Node, Vec<Edge>>
}

impl Graph {
    fn new(adj_list: HashMap<Node, Vec<Edge>>) -> Graph {
        Graph {
            adj_list: adj_list
        }
    }

    fn from_nodes(nodes: Vec<NodePt>) -> Graph {
        let mut map: HashMap<Node, Vec<Edge>> = HashMap::new();
        for i in range(0, nodes.len()) {
            let mut adj_edges: Vec<Edge> = Vec::new();

            for j in range(0, nodes.len()) {
                let a = nodes.get(i);
                let b = nodes.get(j);
                if i != j {
                    adj_edges.push(Edge::new(*a, *b));
                }
            }

            map.insert(i, adj_edges);
        }

        Graph::new(map)
    }

    fn random_graph<R: Rng>(rng: &mut R, num_nodes: uint, x_max: f64, y_max: f64) -> Graph {
        let points = rng.gen_iter::<(f64, f64)>()
            .enumerate()
            .map(|(idx, (x, y))| NodePt::new(idx, x * x_max, y * y_max))
            .take(num_nodes)
            .collect();

        Graph::from_nodes(points)
    }

    fn get(&self, n: Node, m: Node) -> f64 {
        if n == m {
            0.0
        } else {
            let edges = self.adj_list.get(&n);
            let result = edges.iter().filter(|edge| edge.to == m).nth(0);
            match result {
                Some(edge) => edge.weight,
                None => fail!("No edge found!")
            }
        }
    }

    fn size(&self) -> uint {
        self.adj_list.len()
    }

    fn nodes(&self) -> Vec<Node> {
        range(0, self.size()).collect()
    }

    #[allow(dead_code)]
    fn from_file(file_path: &str) -> Graph {
        let path = Path::new(file_path);
        let mut file = BufferedReader::new(File::open(&path));
        let mut nodes: Vec<NodePt> = Vec::new();
        let mut i = 0u;

        for line in file.lines() {
            let mut numbers: Vec<f64> = Vec::new();
            // This could be a lot nicer
            match line {
                Ok(val) => {
                    for token in val.as_slice().split(' ') {
                        if token == "\n" {
                            continue
                        }

                        let n = match from_str::<f64>(token) {
                            Some(num) => num,
                            None => continue
                        };
                        numbers.push(n);
                    }
                },
                Err(_) => fail!("Failed reading file.")
            }

            if numbers.len() == 2 {
                let point = NodePt::new(i, *numbers.get(0), *numbers.get(1));
                nodes.push(point);
            }

            i += 1;
        }

        Graph::from_nodes(nodes)
    }
}

struct Population {
    rng: StdRng,
    graph: Box<Graph>,
    population: Vec<Tour>,
    mutation_rate: f64,
    tournament_size: uint
}

impl Population {
    fn new(population_count: uint, graph: Box<Graph>, mutation_rate: f64, tournament_size: uint, mut rng: StdRng) -> Population {
        let population = Vec::from_fn(population_count, |_| Tour::random_tour(&mut rng, graph));

        Population {
            rng: rng,
            graph: graph,
            population: population,
            mutation_rate: mutation_rate,
            tournament_size: tournament_size
        }
    }

    fn fittest(&self) -> Tour {
        find_min(&self.population)
    }

    fn tournament_selection(&mut self) -> Tour {
        let size = self.population.len();
        let mut buffer: Vec<Tour> = Vec::new();
        for _ in range(0, self.tournament_size) {
            let t = (self.rng.gen::<f64>() * (size as f64)) as uint;
            buffer.push(self.population.get(t).clone());
        }
        find_min(&buffer)
    }

    fn evolve(&mut self) -> Population {
        let mut new_population: Vec<Tour> = Vec::new();

        for _ in range(0, self.population.len()) {
            let parent1 = self.tournament_selection();
            let parent2 = self.tournament_selection();
            let child: Tour = parent1.crossover(parent2, self.graph, &mut self.rng);
            new_population.push(child);
        }

        let mutated = new_population.iter().map(|tour| tour.mutate(&mut self.rng, self.graph, self.mutation_rate)).collect();

        Population {
            rng: self.rng,
            graph: self.graph.clone(),
            population: mutated,
            mutation_rate: self.mutation_rate,
            tournament_size: self.tournament_size
        }
    }
}

impl fmt::Show for Population {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Population: {}", self.population)
    }
}

fn find_min<E: PartialOrd+Clone>(xs: &Vec<E>) -> E {
    let ref min = *xs.iter().fold(xs.get(0), |min, next| if next < min {next} else {min});
    min.clone()
}

fn main() {
    let iter_count = 100;
    let node_count = 15;
    let mutation_rate = 0.03;
    let tournament_size = 5;
    let population_size = 10000;
    let scale = 200.0;

    let rng: StdRng = match StdRng::new() {
        Ok(r) => r,
        Err(_) => fail!("failed to acquire RNG")
    };
    let mut s_rng: StdRng = SeedableRng::from_seed(&[12, 13, 14, 15]);

    let graph = Graph::random_graph(&mut s_rng, node_count, scale, scale);
    let mut pop = Population::new(population_size, box graph, mutation_rate, tournament_size, rng);
    println!("Fittest at start: {}", pop.fittest().total_weight)

    let t0 = precise_time_ns();
    for _ in range(0, iter_count) {
        pop = pop.evolve();
    }
    let t1 = precise_time_ns();

    println!("Fittest at end: {}", pop.fittest().total_weight)
    let dt = ((t1-t0) as f64) / 1e6;
    println!("t_avg = {} ms", dt / iter_count as f64);
}<|endoftext|>


<commit_before>use rustc_serialize::json::Json;
use rustc_serialize::json;
use matrix::json as mjson;
use std::fmt;

#[derive(Clone, Debug, PartialEq)]
pub struct EventID {
    pub id: String,
    pub homeserver: String
}

impl EventID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        EventID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug)]
pub struct UserID {
    pub nickname: String,
    pub homeserver: String
}

impl UserID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        UserID {
            nickname: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct RoomID {
    pub id: String,
    pub homeserver: String
}

impl fmt::Display for RoomID {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "!{}:{}", self.id, self.homeserver)
    }
}

impl RoomID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        RoomID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Debug)]
pub enum MembershipAction {
    Join,
    Leave,
    Ban,
    Invite,
}

impl MembershipAction {
    pub fn from_str(s: &str) -> Self {
        match s {
            "join" => MembershipAction::Join,
            "leave" => MembershipAction::Leave,
            "ban" => MembershipAction::Ban,
            "invite" => MembershipAction::Invite,
            _ => panic!("unknown membership action {:?}", s)
        }
    }
}

#[derive(Debug)]
pub enum RoomEvent {
    CanonicalAlias(String),
    JoinRules(String),
    Membership(UserID, MembershipAction),
    HistoryVisibility(String),
    Create,
    Aliases,
    Message(UserID, String),
    PowerLevels,
    Name(UserID, String)
}

#[derive(Debug)]
pub struct TypingEvent {
    pub users: Vec<UserID>,
    pub room: RoomID,
}

#[derive(Debug)]
pub enum EventData {
    Room(RoomID, RoomEvent),
    Typing(TypingEvent),
    Presence(PresenceEvent),
    Unknown(Json)
}

impl EventData {
    pub fn type_str(&self) -> &'static str {
        match self {
            &EventData::Room(_, RoomEvent::Message(_, _)) => {
                "m.room.message"
            },
            _ => unreachable!()
        }
    }

    pub fn to_json(&self) -> json::Json {
        let mut ret = json::Object::new();
        match self {
            &EventData::Room(ref id, ref evt) => {
                match evt {
                    &RoomEvent::Message(ref sender, ref text) => {
                        ret.insert("msgtype".to_string(), json::Json::String("m.text".to_string()));
                        ret.insert("body".to_string(), json::Json::String(text.clone()));
                    },
                    _ => unreachable!()
                }
            },
            _ => unreachable!()
        }
        json::Json::Object(ret)
    }
}

#[derive(Debug)]
pub struct Event {
    pub id: Option<EventID>,
    pub data: EventData
}

#[derive(Debug)]
pub struct PresenceEvent {
    pub presence: String,
    pub user: UserID
}

impl Event {
    pub fn from_json(json: &Json) -> Self {
        let tokens: Vec<&str> = mjson::string(json, "type").trim().split(".").collect();
        let id = match json.as_object().unwrap().get("event_id") {
            Some(i) => Some(EventID::from_str(i.as_string().unwrap())),
            None => None
        };
        if tokens[0] != "m" {
            Event {
                id: id,
                data: EventData::Unknown(json.clone()),
            }
        } else {
            Event {
                id: id,
                data: match tokens[1] {
                    "room" =>
                        Self::from_room_json(tokens[2], json),
                    "typing" =>
                        EventData::Typing(TypingEvent {
                            users: vec![],
                            room: RoomID::from_str(mjson::string(json, "room_id"))
                        }),
                    "presence" =>
                        EventData::Presence(PresenceEvent{
                            presence: mjson::string(json, "content.presence").to_string(),
                            user: UserID::from_str(mjson::string(json, "content.user_id"))
                        }),
                    e => panic!("Unknown event {:?}!\nRaw JSON: {:?}", e, json)
                }
            }
        }
    }

    fn from_room_json(event_type: &str, json: &Json) -> EventData {
        EventData::Room(
            RoomID::from_str(mjson::string(json, "room_id")),
            match event_type {
                "canonical_alias" =>
                    RoomEvent::CanonicalAlias(mjson::string(json, "content.alias").to_string()),
                "join_rules" =>
                    RoomEvent::JoinRules(mjson::string(json, "content.join_rule").to_string()),
                "member" =>
                    RoomEvent::Membership(UserID::from_str(mjson::string(json, "user_id")), MembershipAction::from_str(mjson::string(json, "content.membership"))),
                "history_visibility" =>
                    RoomEvent::HistoryVisibility(mjson::string(json, "content.history_visibility").to_string()),
                "create" =>
                    RoomEvent::Create,
                "aliases" =>
                    RoomEvent::Aliases,
                "power_levels" =>
                    RoomEvent::PowerLevels,
                "message" =>
                    RoomEvent::Message(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.body").to_string()),
                "name" =>
                    RoomEvent::Name(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.name").to_string()),
                e => panic!("Unknown room event {:?}: {:?}", e, json)
            }
        )
    }
}
<commit_msg>matrix: events: handle topic and avatar events<commit_after>use rustc_serialize::json::Json;
use rustc_serialize::json;
use matrix::json as mjson;
use std::fmt;

#[derive(Clone, Debug, PartialEq)]
pub struct EventID {
    pub id: String,
    pub homeserver: String
}

impl EventID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        EventID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug)]
pub struct UserID {
    pub nickname: String,
    pub homeserver: String
}

impl UserID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        UserID {
            nickname: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct RoomID {
    pub id: String,
    pub homeserver: String
}

impl fmt::Display for RoomID {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "!{}:{}", self.id, self.homeserver)
    }
}

impl RoomID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        RoomID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Debug)]
pub enum MembershipAction {
    Join,
    Leave,
    Ban,
    Invite,
}

impl MembershipAction {
    pub fn from_str(s: &str) -> Self {
        match s {
            "join" => MembershipAction::Join,
            "leave" => MembershipAction::Leave,
            "ban" => MembershipAction::Ban,
            "invite" => MembershipAction::Invite,
            _ => panic!("unknown membership action {:?}", s)
        }
    }
}

#[derive(Debug)]
pub enum RoomEvent {
    CanonicalAlias(String),
    JoinRules(String),
    Membership(UserID, MembershipAction),
    HistoryVisibility(String),
    Create,
    Aliases,
    Message(UserID, String),
    PowerLevels,
    Name(UserID, String),
    Avatar(UserID, String),
    Topic(UserID, String),
    Unknown(Json)
}

#[derive(Debug)]
pub struct TypingEvent {
    pub users: Vec<UserID>,
    pub room: RoomID,
}

#[derive(Debug)]
pub enum EventData {
    Room(RoomID, RoomEvent),
    Typing(TypingEvent),
    Presence(PresenceEvent),
    Unknown(Json)
}

impl EventData {
    pub fn type_str(&self) -> &'static str {
        match self {
            &EventData::Room(_, RoomEvent::Message(_, _)) => {
                "m.room.message"
            },
            _ => unreachable!()
        }
    }

    pub fn to_json(&self) -> json::Json {
        let mut ret = json::Object::new();
        match self {
            &EventData::Room(ref id, ref evt) => {
                match evt {
                    &RoomEvent::Message(ref sender, ref text) => {
                        ret.insert("msgtype".to_string(), json::Json::String("m.text".to_string()));
                        ret.insert("body".to_string(), json::Json::String(text.clone()));
                    },
                    _ => unreachable!()
                }
            },
            _ => unreachable!()
        }
        json::Json::Object(ret)
    }
}

#[derive(Debug)]
pub struct Event {
    pub id: Option<EventID>,
    pub data: EventData
}

#[derive(Debug)]
pub struct PresenceEvent {
    pub presence: String,
    pub user: UserID
}

impl Event {
    pub fn from_json(json: &Json) -> Self {
        let tokens: Vec<&str> = mjson::string(json, "type").trim().split(".").collect();
        let id = match json.as_object().unwrap().get("event_id") {
            Some(i) => Some(EventID::from_str(i.as_string().unwrap())),
            None => None
        };
        if tokens[0] != "m" {
            Event {
                id: id,
                data: EventData::Unknown(json.clone()),
            }
        } else {
            Event {
                id: id,
                data: match tokens[1] {
                    "room" =>
                        Self::from_room_json(tokens[2], json),
                    "typing" =>
                        EventData::Typing(TypingEvent {
                            users: vec![],
                            room: RoomID::from_str(mjson::string(json, "room_id"))
                        }),
                    "presence" =>
                        EventData::Presence(PresenceEvent{
                            presence: mjson::string(json, "content.presence").to_string(),
                            user: UserID::from_str(mjson::string(json, "content.user_id"))
                        }),
                    e => panic!("Unknown event {:?}!\nRaw JSON: {:?}", e, json)
                }
            }
        }
    }

    fn from_room_json(event_type: &str, json: &Json) -> EventData {
        EventData::Room(
            RoomID::from_str(mjson::string(json, "room_id")),
            match event_type {
                "canonical_alias" =>
                    RoomEvent::CanonicalAlias(mjson::string(json, "content.alias").to_string()),
                "join_rules" => {
                        if json.find_path(&["content", "join_rules"]) == None {
                            RoomEvent::Unknown(json.clone())
                        } else {
                            RoomEvent::JoinRules(mjson::string(json, "content.join_rules").to_string())
                        }
                    },
                "member" =>
                    RoomEvent::Membership(UserID::from_str(mjson::string(json, "user_id")), MembershipAction::from_str(mjson::string(json, "content.membership"))),
                "history_visibility" =>
                    RoomEvent::HistoryVisibility(mjson::string(json, "content.history_visibility").to_string()),
                "create" =>
                    RoomEvent::Create,
                "aliases" =>
                    RoomEvent::Aliases,
                "power_levels" =>
                    RoomEvent::PowerLevels,
                "message" =>
                    RoomEvent::Message(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.body").to_string()),
                "name" =>
                    RoomEvent::Name(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.name").to_string()),
                "topic" =>
                    RoomEvent::Topic(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.topic").to_string()),
                "avatar" =>
                    RoomEvent::Avatar(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.url").to_string()),
                e => panic!("Unknown room event {:?}: {:?}", e, json)
            }
        )
    }
}
<|endoftext|>


<commit_before>//! This module defines Concrete Syntax Tree (CST), used by rust-analyzer.
//!
//! The CST includes comments and whitespace, provides a single node type,
//! `SyntaxNode`, and a basic traversal API (parent, children, siblings).
//!
//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
//! module just wraps its API.

use rowan::{GreenNodeBuilder, Language};

use crate::{Parse, SyntaxError, SyntaxKind, TextSize};

pub(crate) use rowan::{GreenNode, GreenToken, NodeOrToken};

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum RustLanguage {}
impl Language for RustLanguage {
    type Kind = SyntaxKind;

    fn kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind {
        SyntaxKind::from(raw.0)
    }

    fn kind_to_raw(kind: SyntaxKind) -> rowan::SyntaxKind {
        rowan::SyntaxKind(kind.into())
    }
}

pub type SyntaxNode = rowan::SyntaxNode<RustLanguage>;
pub type SyntaxToken = rowan::SyntaxToken<RustLanguage>;
pub type SyntaxElement = rowan::SyntaxElement<RustLanguage>;
pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren<RustLanguage>;
pub type SyntaxElementChildren = rowan::SyntaxElementChildren<RustLanguage>;
pub type PreorderWithTokens = rowan::api::PreorderWithTokens<RustLanguage>;

#[derive(Default)]
pub struct SyntaxTreeBuilder {
    errors: Vec<SyntaxError>,
    inner: GreenNodeBuilder<'static>,
}

impl SyntaxTreeBuilder {
    pub(crate) fn finish_raw(self) -> (GreenNode, Vec<SyntaxError>) {
        let green = self.inner.finish();
        (green, self.errors)
    }

    pub fn finish(self) -> Parse<SyntaxNode> {
        let (green, errors) = self.finish_raw();
        if cfg!(debug_assertions) && false {
            let node = SyntaxNode::new_root(green.clone());
            crate::validation::validate_block_structure(&node);
        }
        Parse::new(green, errors)
    }

    pub fn token(&mut self, kind: SyntaxKind, text: &str) {
        let kind = RustLanguage::kind_to_raw(kind);
        self.inner.token(kind, text);
    }

    pub fn start_node(&mut self, kind: SyntaxKind) {
        let kind = RustLanguage::kind_to_raw(kind);
        self.inner.start_node(kind);
    }

    pub fn finish_node(&mut self) {
        self.inner.finish_node();
    }

    pub fn error(&mut self, error: parser::ParseError, text_pos: TextSize) {
        self.errors.push(SyntaxError::new_at_offset(*error.0, text_pos));
    }
}
<commit_msg>Add code comment<commit_after>//! This module defines Concrete Syntax Tree (CST), used by rust-analyzer.
//!
//! The CST includes comments and whitespace, provides a single node type,
//! `SyntaxNode`, and a basic traversal API (parent, children, siblings).
//!
//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
//! module just wraps its API.

use rowan::{GreenNodeBuilder, Language};

use crate::{Parse, SyntaxError, SyntaxKind, TextSize};

pub(crate) use rowan::{GreenNode, GreenToken, NodeOrToken};

#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum RustLanguage {}
impl Language for RustLanguage {
    type Kind = SyntaxKind;

    fn kind_from_raw(raw: rowan::SyntaxKind) -> SyntaxKind {
        SyntaxKind::from(raw.0)
    }

    fn kind_to_raw(kind: SyntaxKind) -> rowan::SyntaxKind {
        rowan::SyntaxKind(kind.into())
    }
}

pub type SyntaxNode = rowan::SyntaxNode<RustLanguage>;
pub type SyntaxToken = rowan::SyntaxToken<RustLanguage>;
pub type SyntaxElement = rowan::SyntaxElement<RustLanguage>;
pub type SyntaxNodeChildren = rowan::SyntaxNodeChildren<RustLanguage>;
pub type SyntaxElementChildren = rowan::SyntaxElementChildren<RustLanguage>;
pub type PreorderWithTokens = rowan::api::PreorderWithTokens<RustLanguage>;

#[derive(Default)]
pub struct SyntaxTreeBuilder {
    errors: Vec<SyntaxError>,
    inner: GreenNodeBuilder<'static>,
}

impl SyntaxTreeBuilder {
    pub(crate) fn finish_raw(self) -> (GreenNode, Vec<SyntaxError>) {
        let green = self.inner.finish();
        (green, self.errors)
    }

    pub fn finish(self) -> Parse<SyntaxNode> {
        let (green, errors) = self.finish_raw();
        // NOTE Why you're disabling assertions.
        // ref: https://github.com/rust-analyzer/rust-analyzer/pull/10357
        if cfg!(debug_assertions) && false {
            let node = SyntaxNode::new_root(green.clone());
            crate::validation::validate_block_structure(&node);
        }
        Parse::new(green, errors)
    }

    pub fn token(&mut self, kind: SyntaxKind, text: &str) {
        let kind = RustLanguage::kind_to_raw(kind);
        self.inner.token(kind, text);
    }

    pub fn start_node(&mut self, kind: SyntaxKind) {
        let kind = RustLanguage::kind_to_raw(kind);
        self.inner.start_node(kind);
    }

    pub fn finish_node(&mut self) {
        self.inner.finish_node();
    }

    pub fn error(&mut self, error: parser::ParseError, text_pos: TextSize) {
        self.errors.push(SyntaxError::new_at_offset(*error.0, text_pos));
    }
}
<|endoftext|>


<commit_before>use diesel::*;
use schema::{connection_without_transaction, DropTable};

table! {
    auto_time {
        id -> Integer,
        n -> Integer,
        updated_at -> Timestamp,
    }
}

#[test]
#[cfg(any(feature = "postgres", feature = "sqlite"))]
fn managing_updated_at_for_table() {
    use self::auto_time::dsl::*;
    use chrono::NaiveDateTime;
    use schema_dsl::*;
    use std::{thread, time::Duration};

    // transactions have frozen time, so we can't use them
    let connection = connection_without_transaction();
    create_table(
        "auto_time",
        (
            integer("id").primary_key().auto_increment(),
            integer("n"),
            timestamp("updated_at"),
        ),
    )
    .execute(&connection)
    .unwrap();
    let _guard = DropTable {
        connection: &connection,
        table_name: "auto_time",
    };
    sql_query("SELECT diesel_manage_updated_at('auto_time')")
        .execute(&connection)
        .unwrap();

    insert_into(auto_time)
        .values(&vec![n.eq(2), n.eq(1), n.eq(5)])
        .execute(&connection)
        .unwrap();

    let result = auto_time
        .count()
        .filter(updated_at.is_null())
        .get_result::<i64>(&connection);
    assert_eq!(Ok(3), result);

    update(auto_time)
        .set(n.eq(n + 1))
        .execute(&connection)
        .unwrap();

    let result = auto_time
        .count()
        .filter(updated_at.is_null())
        .get_result::<i64>(&connection);
    assert_eq!(Ok(0), result);

    if cfg!(feature = "sqlite") {
        // SQLite only has second precision
        thread::sleep(Duration::from_millis(1000));
    }

    let query = auto_time.find(2).select(updated_at);
    let old_time: NaiveDateTime = query.first(&connection).unwrap();
    update(auto_time.find(2))
        .set(n.eq(0))
        .execute(&connection)
        .unwrap();
    let new_time: NaiveDateTime = query.first(&connection).unwrap();
    assert!(old_time < new_time);
}
<commit_msg>Add test for stripping sqlite:// from paths<commit_after>use diesel::*;
use schema::{connection_without_transaction, DropTable};

table! {
    auto_time {
        id -> Integer,
        n -> Integer,
        updated_at -> Timestamp,
    }
}

#[test]
#[cfg(any(feature = "postgres", feature = "sqlite"))]
fn managing_updated_at_for_table() {
    use self::auto_time::dsl::*;
    use chrono::NaiveDateTime;
    use schema_dsl::*;
    use std::{thread, time::Duration};

    // transactions have frozen time, so we can't use them
    let connection = connection_without_transaction();
    create_table(
        "auto_time",
        (
            integer("id").primary_key().auto_increment(),
            integer("n"),
            timestamp("updated_at"),
        ),
    )
    .execute(&connection)
    .unwrap();
    let _guard = DropTable {
        connection: &connection,
        table_name: "auto_time",
    };
    sql_query("SELECT diesel_manage_updated_at('auto_time')")
        .execute(&connection)
        .unwrap();

    insert_into(auto_time)
        .values(&vec![n.eq(2), n.eq(1), n.eq(5)])
        .execute(&connection)
        .unwrap();

    let result = auto_time
        .count()
        .filter(updated_at.is_null())
        .get_result::<i64>(&connection);
    assert_eq!(Ok(3), result);

    update(auto_time)
        .set(n.eq(n + 1))
        .execute(&connection)
        .unwrap();

    let result = auto_time
        .count()
        .filter(updated_at.is_null())
        .get_result::<i64>(&connection);
    assert_eq!(Ok(0), result);

    if cfg!(feature = "sqlite") {
        // SQLite only has second precision
        thread::sleep(Duration::from_millis(1000));
    }

    let query = auto_time.find(2).select(updated_at);
    let old_time: NaiveDateTime = query.first(&connection).unwrap();
    update(auto_time.find(2))
        .set(n.eq(0))
        .execute(&connection)
        .unwrap();
    let new_time: NaiveDateTime = query.first(&connection).unwrap();
    assert!(old_time < new_time);
}

#[test]
#[cfg(feature = "sqlite")]
fn strips_sqlite_url_prefix() {
    let mut path = std::env::temp_dir();
    path.push("diesel_test_sqlite.db");
    assert!(SqliteConnection::establish(&format!("sqlite://{}", path.display())).is_ok());
}
<|endoftext|>


<commit_before>// crypto_auth_hmacsha512.h

pub const crypto_auth_hmacsha512_BYTES: usize = 64;
pub const crypto_auth_hmacsha512_KEYBYTES: usize = 32;

extern {
    pub fn crypto_auth_hmacsha512(
        a: *mut [u8; crypto_auth_hmacsha512_BYTES],
        m: *const u8,
        mlen: c_ulonglong,
        k: *const [u8; crypto_auth_hmacsha512_KEYBYTES]) -> c_int;
    pub fn crypto_auth_hmacsha512_verify(
        a: *const [u8; crypto_auth_hmacsha512_BYTES],
        m: *const u8,
        mlen: c_ulonglong,
        k: *const [u8; crypto_auth_hmacsha512_KEYBYTES]) -> c_int;
    pub fn crypto_auth_hmacsha512_bytes() -> size_t;
    pub fn crypto_auth_hmacsha512_keybytes() -> size_t;
}

#[test]
fn test_crypto_auth_hmacsha512_bytes() {
    assert!(unsafe { crypto_auth_hmacsha512_bytes() as usize } ==
            crypto_auth_hmacsha512_BYTES)
}
#[test]
fn test_crypto_auth_hmacsha512_keybytes() {
    assert!(unsafe { crypto_auth_hmacsha512_keybytes() as usize } ==
            crypto_auth_hmacsha512_KEYBYTES)
}
<commit_msg>libsodium-sys: definitions from crypto_auth_hmacsha512.h complete<commit_after>// crypto_auth_hmacsha512.h

#[repr(C)]
#[derive(Copy)]
pub struct crypto_auth_hmacsha512_state {
    ictx: crypto_hash_sha512_state,
    octx: crypto_hash_sha512_state,
}

pub const crypto_auth_hmacsha512_BYTES: usize = 64;
pub const crypto_auth_hmacsha512_KEYBYTES: usize = 32;

extern {
    pub fn crypto_auth_hmacsha512_bytes() -> size_t;
    pub fn crypto_auth_hmacsha512_keybytes() -> size_t;
    pub fn crypto_auth_hmacsha512(
        a: *mut [u8; crypto_auth_hmacsha512_BYTES],
        m: *const u8,
        mlen: c_ulonglong,
        k: *const [u8; crypto_auth_hmacsha512_KEYBYTES]) -> c_int;
    pub fn crypto_auth_hmacsha512_verify(
        a: *const [u8; crypto_auth_hmacsha512_BYTES],
        m: *const u8,
        mlen: c_ulonglong,
        k: *const [u8; crypto_auth_hmacsha512_KEYBYTES]) -> c_int;
    pub fn crypto_auth_hmacsha512_init(
        state: *mut crypto_auth_hmacsha512_state,
        key: *const u8,
        keylen: size_t) -> c_int;
    pub fn crypto_auth_hmacsha512_update(
        state: *mut crypto_auth_hmacsha512_state,
        m: *const u8,
        mlen: c_ulonglong) -> c_int;
    pub fn crypto_auth_hmacsha512_final(
        state: *mut crypto_auth_hmacsha512_state,
        a: *mut [u8; crypto_auth_hmacsha512_BYTES]) -> c_int;
}

#[test]
fn test_crypto_auth_hmacsha512_bytes() {
    assert!(unsafe { crypto_auth_hmacsha512_bytes() as usize } ==
            crypto_auth_hmacsha512_BYTES)
}
#[test]
fn test_crypto_auth_hmacsha512_keybytes() {
    assert!(unsafe { crypto_auth_hmacsha512_keybytes() as usize } ==
            crypto_auth_hmacsha512_KEYBYTES)
}
<|endoftext|>


<commit_before>extern crate ggez;

use std::path;

use ggez::conf;
use ggez::game::{Game, GameState};
use ggez::{GameResult, Context};
use ggez::graphics;
use ggez::graphics::Drawable;
use ggez::timer;
use std::time::Duration;

struct MainState {
    text: graphics::Text,
}

impl GameState for MainState {
    fn load(ctx: &mut Context, _conf: &conf::Conf) -> GameResult<MainState> {
        let fontpath = path::Path::new("DejaVuSerif.ttf");
        let font = graphics::Font::new(ctx, fontpath, 48).unwrap();
        let text = graphics::Text::new(ctx, "Hello world!", &font).unwrap();

        let s = MainState { text: text };
        Ok(s)
    }

    fn update(&mut self, _ctx: &mut Context, _dt: Duration) -> GameResult<()> {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        ctx.renderer.clear();
        try!(graphics::draw(ctx, &mut self.text, None, None));
        ctx.renderer.present();
        timer::sleep_until_next_frame(ctx, 60);
        Ok(())
    }
}

pub fn main() {
    let c = conf::Conf::new();
    let mut e: Game<MainState> = Game::new("helloworld", c).unwrap();
    let result = e.run();
    if let Err(e) = result {
        println!("Error encountered: {:?}", e);
    } else {
        println!("Game exited cleanly.");
    }
}
<commit_msg>Updated hello world example with docs<commit_after>extern crate ggez;
use std::path;
use ggez::conf;
use ggez::game::{Game, GameState};
use ggez::{GameResult, Context};
use ggez::graphics;
use ggez::timer;
use std::time::Duration;

// First we make a structure to contain the game's state
struct MainState {
    text: graphics::Text,
}

// Then we implement the `ggez::game::GameState` trait on it, which
// requires callbacks for creating the game state, updating it each
// frame, and drawing it.
//
// The `GameState` trait also contains callbacks for event handling
// that you can override if you wish, but the defaults are fine.
impl GameState for MainState {
    fn load(ctx: &mut Context, _conf: &conf::Conf) -> GameResult<MainState> {
        let fontpath = path::Path::new("DejaVuSerif.ttf");
        let font = graphics::Font::new(ctx, fontpath, 48).unwrap();
        let text = graphics::Text::new(ctx, "Hello world!", &font).unwrap();

        let s = MainState { text: text };
        Ok(s)
    }

    fn update(&mut self, _ctx: &mut Context, _dt: Duration) -> GameResult<()> {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult<()> {
        ctx.renderer.clear();
        try!(graphics::draw(ctx, &mut self.text, None, None));
        ctx.renderer.present();
        timer::sleep_until_next_frame(ctx, 60);
        Ok(())
    }
}

// Now our main function, which does three things:
//
// * First, create a new `ggez::conf::Conf`
// object which contains configuration info on things such
// as screen resolution and window title,
// * Second, create a `ggez::game::Game` object which will
// do the work of creating our MainState and running our game,
// * then just call `game.run()` which runs the `Game` mainloop.
pub fn main() {
    let c = conf::Conf::new();
    let mut game: Game<MainState> = Game::new("helloworld", c).unwrap();
    if let Err(e) = game.run() {
        println!("Error encountered: {:?}", e);
    } else {
        println!("Game exited cleanly.");
    }
}
<|endoftext|>


<commit_before>//! Futures task based helpers

#![allow(clippy::mutex_atomic)]

use std::future::Future;
use std::mem;
use std::ops;
use std::pin::Pin;
use std::sync::{Arc, Condvar, Mutex};
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};

use tokio::stream::Stream;

/// TOOD: dox
pub fn spawn<T>(task: T) -> Spawn<T> {
    Spawn {
        task: MockTask::new(),
        future: Box::pin(task),
    }
}

/// Future spawned on a mock task
#[derive(Debug)]
pub struct Spawn<T> {
    task: MockTask,
    future: Pin<Box<T>>,
}

/// Mock task
///
/// A mock task is able to intercept and track wake notifications.
#[derive(Debug, Clone)]
struct MockTask {
    waker: Arc<ThreadWaker>,
}

#[derive(Debug)]
struct ThreadWaker {
    state: Mutex<usize>,
    condvar: Condvar,
}

const IDLE: usize = 0;
const WAKE: usize = 1;
const SLEEP: usize = 2;

impl<T> Spawn<T> {
    /// Consumes `self` returning the inner value
    pub fn into_inner(mut self) -> T
    where
        T: Unpin,
    {
        drop(self.task);

        // Pin::into_inner is unstable, so we work around it
        //
        // Safety: `T` is bound by `Unpin`.
        unsafe {
            let ptr = Pin::get_mut(self.future.as_mut()) as *mut T;
            let future = Box::from_raw(ptr);
            mem::forget(self.future);
            *future
        }
    }

    /// Returns `true` if the inner future has received a wake notification
    /// since the last call to `enter`.
    pub fn is_woken(&self) -> bool {
        self.task.is_woken()
    }

    /// Returns the number of references to the task waker
    ///
    /// The task itself holds a reference. The return value will never be zero.
    pub fn waker_ref_count(&self) -> usize {
        self.task.waker_ref_count()
    }

    /// Enter the task context
    pub fn enter<F, R>(&mut self, f: F) -> R
    where
        F: FnOnce(&mut Context<'_>, Pin<&mut T>) -> R,
    {
        let fut = self.future.as_mut();
        self.task.enter(|cx| f(cx, fut))
    }
}

impl<T: Unpin> ops::Deref for Spawn<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.future
    }
}

impl<T: Unpin> ops::DerefMut for Spawn<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.future
    }
}

impl<T: Future> Spawn<T> {
    /// Polls a future
    pub fn poll(&mut self) -> Poll<T::Output> {
        let fut = self.future.as_mut();
        self.task.enter(|cx| fut.poll(cx))
    }
}

impl<T: Stream> Spawn<T> {
    /// Polls a stream
    pub fn poll_next(&mut self) -> Poll<Option<T::Item>> {
        let stream = self.future.as_mut();
        self.task.enter(|cx| stream.poll_next(cx))
    }
}

impl<T: Future> Future for Spawn<T> {
    type Output = T::Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        // Safety: we only expose &mut T if T: Unpin therefore this is safe.
        let future = unsafe { self.map_unchecked_mut(|s| &mut s.future) };
        future.poll(cx)
    }
}

impl<T: Stream> Stream for Spawn<T> {
    type Item = T::Item;

    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        // Safety: we only expose &mut T if T: Unpin therefore this is safe.
        let stream = unsafe { self.map_unchecked_mut(|s| &mut s.future) };
        stream.poll_next(cx)
    }
}

impl MockTask {
    /// Creates new mock task
    fn new() -> Self {
        MockTask {
            waker: Arc::new(ThreadWaker::new()),
        }
    }

    /// Runs a closure from the context of the task.
    ///
    /// Any wake notifications resulting from the execution of the closure are
    /// tracked.
    fn enter<F, R>(&mut self, f: F) -> R
    where
        F: FnOnce(&mut Context<'_>) -> R,
    {
        self.waker.clear();
        let waker = self.waker();
        let mut cx = Context::from_waker(&waker);

        f(&mut cx)
    }

    /// Returns `true` if the inner future has received a wake notification
    /// since the last call to `enter`.
    fn is_woken(&self) -> bool {
        self.waker.is_woken()
    }

    /// Returns the number of references to the task waker
    ///
    /// The task itself holds a reference. The return value will never be zero.
    fn waker_ref_count(&self) -> usize {
        Arc::strong_count(&self.waker)
    }

    fn waker(&self) -> Waker {
        unsafe {
            let raw = to_raw(self.waker.clone());
            Waker::from_raw(raw)
        }
    }
}

impl Default for MockTask {
    fn default() -> Self {
        Self::new()
    }
}

impl ThreadWaker {
    fn new() -> Self {
        ThreadWaker {
            state: Mutex::new(IDLE),
            condvar: Condvar::new(),
        }
    }

    /// Clears any previously received wakes, avoiding potential spurrious
    /// wake notifications. This should only be called immediately before running the
    /// task.
    fn clear(&self) {
        *self.state.lock().unwrap() = IDLE;
    }

    fn is_woken(&self) -> bool {
        match *self.state.lock().unwrap() {
            IDLE => false,
            WAKE => true,
            _ => unreachable!(),
        }
    }

    fn wake(&self) {
        // First, try transitioning from IDLE -> NOTIFY, this does not require a lock.
        let mut state = self.state.lock().unwrap();
        let prev = *state;

        if prev == WAKE {
            return;
        }

        *state = WAKE;

        if prev == IDLE {
            return;
        }

        // The other half is sleeping, so we wake it up.
        assert_eq!(prev, SLEEP);
        self.condvar.notify_one();
    }
}

static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop_waker);

unsafe fn to_raw(waker: Arc<ThreadWaker>) -> RawWaker {
    RawWaker::new(Arc::into_raw(waker) as *const (), &VTABLE)
}

unsafe fn from_raw(raw: *const ()) -> Arc<ThreadWaker> {
    Arc::from_raw(raw as *const ThreadWaker)
}

unsafe fn clone(raw: *const ()) -> RawWaker {
    let waker = from_raw(raw);

    // Increment the ref count
    mem::forget(waker.clone());

    to_raw(waker)
}

unsafe fn wake(raw: *const ()) {
    let waker = from_raw(raw);
    waker.wake();
}

unsafe fn wake_by_ref(raw: *const ()) {
    let waker = from_raw(raw);
    waker.wake();

    // We don't actually own a reference to the unparker
    mem::forget(waker);
}

unsafe fn drop_waker(raw: *const ()) {
    let _ = from_raw(raw);
}
<commit_msg>test: remove unnecessary unsafe code (#2424)<commit_after>//! Futures task based helpers

#![allow(clippy::mutex_atomic)]

use std::future::Future;
use std::mem;
use std::ops;
use std::pin::Pin;
use std::sync::{Arc, Condvar, Mutex};
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};

use tokio::stream::Stream;

/// TOOD: dox
pub fn spawn<T>(task: T) -> Spawn<T> {
    Spawn {
        task: MockTask::new(),
        future: Box::pin(task),
    }
}

/// Future spawned on a mock task
#[derive(Debug)]
pub struct Spawn<T> {
    task: MockTask,
    future: Pin<Box<T>>,
}

/// Mock task
///
/// A mock task is able to intercept and track wake notifications.
#[derive(Debug, Clone)]
struct MockTask {
    waker: Arc<ThreadWaker>,
}

#[derive(Debug)]
struct ThreadWaker {
    state: Mutex<usize>,
    condvar: Condvar,
}

const IDLE: usize = 0;
const WAKE: usize = 1;
const SLEEP: usize = 2;

impl<T> Spawn<T> {
    /// Consumes `self` returning the inner value
    pub fn into_inner(mut self) -> T
    where
        T: Unpin,
    {
        drop(self.task);

        // Pin::into_inner is unstable, so we work around it
        //
        // Safety: `T` is bound by `Unpin`.
        unsafe {
            let ptr = Pin::get_mut(self.future.as_mut()) as *mut T;
            let future = Box::from_raw(ptr);
            mem::forget(self.future);
            *future
        }
    }

    /// Returns `true` if the inner future has received a wake notification
    /// since the last call to `enter`.
    pub fn is_woken(&self) -> bool {
        self.task.is_woken()
    }

    /// Returns the number of references to the task waker
    ///
    /// The task itself holds a reference. The return value will never be zero.
    pub fn waker_ref_count(&self) -> usize {
        self.task.waker_ref_count()
    }

    /// Enter the task context
    pub fn enter<F, R>(&mut self, f: F) -> R
    where
        F: FnOnce(&mut Context<'_>, Pin<&mut T>) -> R,
    {
        let fut = self.future.as_mut();
        self.task.enter(|cx| f(cx, fut))
    }
}

impl<T: Unpin> ops::Deref for Spawn<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.future
    }
}

impl<T: Unpin> ops::DerefMut for Spawn<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.future
    }
}

impl<T: Future> Spawn<T> {
    /// Polls a future
    pub fn poll(&mut self) -> Poll<T::Output> {
        let fut = self.future.as_mut();
        self.task.enter(|cx| fut.poll(cx))
    }
}

impl<T: Stream> Spawn<T> {
    /// Polls a stream
    pub fn poll_next(&mut self) -> Poll<Option<T::Item>> {
        let stream = self.future.as_mut();
        self.task.enter(|cx| stream.poll_next(cx))
    }
}

impl<T: Future> Future for Spawn<T> {
    type Output = T::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        self.future.as_mut().poll(cx)
    }
}

impl<T: Stream> Stream for Spawn<T> {
    type Item = T::Item;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        self.future.as_mut().poll_next(cx)
    }
}

impl MockTask {
    /// Creates new mock task
    fn new() -> Self {
        MockTask {
            waker: Arc::new(ThreadWaker::new()),
        }
    }

    /// Runs a closure from the context of the task.
    ///
    /// Any wake notifications resulting from the execution of the closure are
    /// tracked.
    fn enter<F, R>(&mut self, f: F) -> R
    where
        F: FnOnce(&mut Context<'_>) -> R,
    {
        self.waker.clear();
        let waker = self.waker();
        let mut cx = Context::from_waker(&waker);

        f(&mut cx)
    }

    /// Returns `true` if the inner future has received a wake notification
    /// since the last call to `enter`.
    fn is_woken(&self) -> bool {
        self.waker.is_woken()
    }

    /// Returns the number of references to the task waker
    ///
    /// The task itself holds a reference. The return value will never be zero.
    fn waker_ref_count(&self) -> usize {
        Arc::strong_count(&self.waker)
    }

    fn waker(&self) -> Waker {
        unsafe {
            let raw = to_raw(self.waker.clone());
            Waker::from_raw(raw)
        }
    }
}

impl Default for MockTask {
    fn default() -> Self {
        Self::new()
    }
}

impl ThreadWaker {
    fn new() -> Self {
        ThreadWaker {
            state: Mutex::new(IDLE),
            condvar: Condvar::new(),
        }
    }

    /// Clears any previously received wakes, avoiding potential spurrious
    /// wake notifications. This should only be called immediately before running the
    /// task.
    fn clear(&self) {
        *self.state.lock().unwrap() = IDLE;
    }

    fn is_woken(&self) -> bool {
        match *self.state.lock().unwrap() {
            IDLE => false,
            WAKE => true,
            _ => unreachable!(),
        }
    }

    fn wake(&self) {
        // First, try transitioning from IDLE -> NOTIFY, this does not require a lock.
        let mut state = self.state.lock().unwrap();
        let prev = *state;

        if prev == WAKE {
            return;
        }

        *state = WAKE;

        if prev == IDLE {
            return;
        }

        // The other half is sleeping, so we wake it up.
        assert_eq!(prev, SLEEP);
        self.condvar.notify_one();
    }
}

static VTABLE: RawWakerVTable = RawWakerVTable::new(clone, wake, wake_by_ref, drop_waker);

unsafe fn to_raw(waker: Arc<ThreadWaker>) -> RawWaker {
    RawWaker::new(Arc::into_raw(waker) as *const (), &VTABLE)
}

unsafe fn from_raw(raw: *const ()) -> Arc<ThreadWaker> {
    Arc::from_raw(raw as *const ThreadWaker)
}

unsafe fn clone(raw: *const ()) -> RawWaker {
    let waker = from_raw(raw);

    // Increment the ref count
    mem::forget(waker.clone());

    to_raw(waker)
}

unsafe fn wake(raw: *const ()) {
    let waker = from_raw(raw);
    waker.wake();
}

unsafe fn wake_by_ref(raw: *const ()) {
    let waker = from_raw(raw);
    waker.wake();

    // We don't actually own a reference to the unparker
    mem::forget(waker);
}

unsafe fn drop_waker(raw: *const ()) {
    let _ = from_raw(raw);
}
<|endoftext|>


<commit_before>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.1

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::{arc, priority_queue};
use std::comm::*;

static PORT:    int = 4414;
static IP: &'static str = "127.0.0.1";

struct sched_msg {
	in_charlottesville: bool,
	file_req_size: uint,
	request_id: uint,
	stream: Option<std::rt::io::net::tcp::TcpStream>,
	filepath: ~std::path::PosixPath
}

impl Ord for sched_msg {
	// Higher priority programs are given priority on the queue.
	fn lt(&self, other: &sched_msg) -> bool {
		if (self.in_charlottesville ^ other.in_charlottesville) {
			!self.in_charlottesville && other.in_charlottesville
				// If you are not in charlottesville but other is, let other go first
		}
		else if (self.file_req_size != other.file_req_size) {
			self.file_req_size > other.file_req_size
				// If your file size is bigger than other's, let other go first.
		}
		else {
			self.request_id > other.request_id
				//tie breaker is id, oldest request goes first.
		}
	}
}

fn main() {
	println("Starting server...");
	let req_vec: ~[sched_msg] = ~[];
	let req_vec = priority_queue::PriorityQueue::from_vec(req_vec);
	let shared_req_vec = arc::RWArc::new(req_vec);
	let take_vec = shared_req_vec.clone();

	let (port, chan) = stream();
	let chan = SharedChan::new(chan);

	do spawn {
		let (sm_port, sm_chan) = stream();
		let (lock_port, lock_chan) = stream();

		// take file requests from queue, and send a response.
		do spawn {
			lock_chan.send("");
			loop {
				let mut tf:sched_msg = sm_port.recv();
				match io::read_whole_file(tf.filepath) {
					Ok(file_data) => {
						println(fmt!("begin serving file [%?]", tf.filepath));
						tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream; charset=UTF-8\r\n\r\n".as_bytes());
						tf.stream.write(file_data);
						println(fmt!("finish file [%?]", tf.filepath));
					}
					Err(err) => {
						println(err);
					}
				}
				lock_chan.send("");
			}
		}

		loop {
			port.recv(); //Wait for arriving notifications
			lock_port.recv(); //wait for file to finish serving
			do take_vec.write |vec| {
				if (*vec).len() > 0 {
					let tf = (*vec).pop();
					println(fmt!("popped from queue with queue size = %u", (*vec).len()));
					sm_chan.send(tf);
				}
			}
		}
	}

	let ip = match FromStr::from_str(IP) {
		Some(ip) => ip,
			None => { println(fmt!("Error: Invalid IP address <%s>", IP)); return;},
	};
	let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});
	//let socket = net::tcp::TcpListener::bind(SocketAddr {ip: Ipv4Addr(127,0,0,1), port: PORT as u16});

	println(fmt!("Listening on tcp port %d ...", PORT));
	let mut acceptor = socket.listen().unwrap();

	let visitor_count_master = arc::RWArc::new(0);

	// we can limit the incoming connection count.
	//for stream in acceptor.incoming().take(10 as uint) {
	for stream in acceptor.incoming() {
		let stream = Cell::new(stream);

		// Start a new task to handle the connection
		let child_chan = chan.clone();
		let child_vec = shared_req_vec.clone();
		let visitor_count = visitor_count_master.clone();
		do spawn {
			visitor_count.write( |count| { *count += 1;} );

			let mut stream = stream.take().unwrap();

			let in_charlottesville = match stream.peer_name() {
				Some(pn) => {
					let s = pn.to_str();
					s.slice_chars(0, 6) == "137.54" || s.slice_chars(0,7)=="128.143"
				},
				None => false
			};

			let mut buf = [0, ..500];
			stream.read(buf);
			let request_str = str::from_utf8(buf);

			let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
			if req_group.len() > 2 {
				let mut path = req_group[1].to_owned();
				let mut oldpath = ~"";
				while path != oldpath {
					oldpath = path;
					path = oldpath.replace("/../", "");
				}

				println(fmt!("Request for path: \n%?", path));
				let file_path = ~os::getcwd().push(path);
				if !os::path_exists(file_path) || os::path_is_dir(file_path) {
					println(fmt!("Request received:\n%s", request_str));
					let response: ~str = fmt!(
						"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
			 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

			 \r\n", visitor_count.read(|count| { *count }) );

					stream.write(response.as_bytes());
				}
				else {
					// may do scheduling here
					println("Starting to send file request...");
					let file_size = match io::file_reader(file_path) {
						Ok(file) => {
							file.seek(0, io::SeekEnd);
							file.tell()
						}
						Err(err) => {
							println(err);
							0u
						}
					};
					let req_id = visitor_count.read(|count| { *count });
					let msg: sched_msg = sched_msg{
						file_req_size: file_size,
										   in_charlottesville: in_charlottesville,
										   request_id: req_id,
										   stream: Some(stream),
										   filepath: file_path.clone()
					};
					let (sm_port, sm_chan) = std::comm::stream();
					sm_chan.send(msg);

					do child_vec.write |vec| {
						let msg = sm_port.recv();
						(*vec).push(msg); // enqueue new request.
						println(fmt!("add to queue with queue size %u", (*vec).len()));
					}
					println("Sending file request...");
					child_chan.send(""); //Notify the arriving request

					println(fmt!("get file request: %?", file_path));
				}
			}
			println!("connection terminates")
		}
	}
}
<commit_msg>Caching works!<commit_after>//
// zhtta.rs
//
// Running on Rust 0.8
//
// Starting code for PS3
//
// Note: it would be very unwise to run this server on a machine that is
// on the Internet and contains any sensitive files!
//
// University of Virginia - cs4414 Fall 2013
// Weilin Xu and David Evans
// Version 0.1

extern mod extra;

use std::rt::io::*;
use std::rt::io::net::ip::SocketAddr;
use std::io::println;
use std::cell::Cell;
use std::{os, str, io};
use extra::{arc, priority_queue};
use std::comm::*;

static PORT:    int = 4414;
static IP: &'static str = "127.0.0.1";

struct sched_msg {
	in_charlottesville: bool,
	file_req_size: uint,
	request_id: uint,
	stream: Option<std::rt::io::net::tcp::TcpStream>,
	filepath: ~std::path::PosixPath
}

impl Ord for sched_msg {
	// Higher priority programs are given priority on the queue.
	fn lt(&self, other: &sched_msg) -> bool {
		if (self.in_charlottesville ^ other.in_charlottesville) {
			!self.in_charlottesville && other.in_charlottesville
				// If you are not in charlottesville but other is, let other go first
		}
		else if (self.file_req_size != other.file_req_size) {
			self.file_req_size > other.file_req_size
				// If your file size is bigger than other's, let other go first.
		}
		else {
			self.request_id > other.request_id
				//tie breaker is id, oldest request goes first.
		}
	}
}

struct cached_info {
	filepath: ~std::path::PosixPath,
	filedata: ~[u8],
	id: uint
}

impl Ord for cached_info {
	fn lt(&self, other: &cached_info) -> bool {
		self.id > other.id // If you're older, you get uncached first.
	}
}

fn main() {
	println("Starting server...");
	let req_vec: ~[sched_msg] = ~[];
	let req_vec = priority_queue::PriorityQueue::from_vec(req_vec);
	let shared_req_vec = arc::RWArc::new(req_vec);
	let take_vec = shared_req_vec.clone();

	let (port, chan) = stream();
	let chan = SharedChan::new(chan);

	do spawn {
		let (sm_port, sm_chan) = stream();
		let (lock_port, lock_chan) = stream();

		// take file requests from queue, and send a response.
		do spawn {
			lock_chan.send("");
			let mut id = 0;
			let cache: ~[cached_info] = ~[];
			let mut cache = priority_queue::PriorityQueue::from_vec(cache);
			loop {
				let mut tf:sched_msg = sm_port.recv();

				tf.stream.write("HTTP/1.1 200 OK\r\nContent-Type: application/octet-stream; charset=UTF-8\r\n\r\n".as_bytes());

				let mut in_cache = false;
				if cache.len() == 3 { //Cache is filled up
					for item in cache.iter() {
						if item.filepath == tf.filepath {
							println(fmt!("Serving file from cache [%?]", item.filepath.to_str()));
							tf.stream.write(item.filedata);
							in_cache = true;
						}
					}
				}

				if !in_cache {
					println(fmt!("Reading file because it is not in cache with length [%?]!", cache.len()));
					println(fmt!("begin serving file from disk [%?]", tf.filepath));
					if cache.len() == 3 { cache.pop(); }
					let c =
						cached_info {
							filepath: tf.filepath.clone(),
							filedata: match io::read_whole_file(tf.filepath) {
								Ok(file_data) => file_data,
								Err(err) => {
									println(err);
									~[]
								}
							},
							id: id
						};
					tf.stream.write(c.filedata);
					cache.push(c);
					id+=1;
				}

				println(fmt!("finish file [%?]", tf.filepath));
				lock_chan.send("");
			}
		}

		loop {
			port.recv(); //Wait for arriving notifications
			lock_port.recv(); //wait for file to finish serving
			do take_vec.write |vec| {
				if (*vec).len() > 0 {
					let tf = (*vec).pop();
					println(fmt!("popped from queue with queue size = %u", (*vec).len()));
					sm_chan.send(tf);
				}
			}
		}
	}

	let ip = match FromStr::from_str(IP) {
		Some(ip) => ip,
			None => { println(fmt!("Error: Invalid IP address <%s>", IP)); return;},
	};
	let socket = net::tcp::TcpListener::bind(SocketAddr {ip: ip, port: PORT as u16});
	//let socket = net::tcp::TcpListener::bind(SocketAddr {ip: Ipv4Addr(127,0,0,1), port: PORT as u16});

	println(fmt!("Listening on tcp port %d ...", PORT));
	let mut acceptor = socket.listen().unwrap();

	let visitor_count_master = arc::RWArc::new(0);

	// we can limit the incoming connection count.
	//for stream in acceptor.incoming().take(10 as uint) {
	for stream in acceptor.incoming() {
		let stream = Cell::new(stream);

		// Start a new task to handle the connection
		let child_chan = chan.clone();
		let child_vec = shared_req_vec.clone();
		let visitor_count = visitor_count_master.clone();
		do spawn {
			visitor_count.write( |count| { *count += 1;} );

			let mut stream = stream.take().unwrap();

			let in_charlottesville = match stream.peer_name() {
				Some(pn) => {
					let s = pn.to_str();
					s.slice_chars(0, 6) == "137.54" || s.slice_chars(0,7)=="128.143"
				},
				None => false
			};

			let mut buf = [0, ..500];
			stream.read(buf);
			let request_str = str::from_utf8(buf);

			let req_group : ~[&str]= request_str.splitn_iter(' ', 3).collect();
			if req_group.len() > 2 {
				let mut path = req_group[1].to_owned();
				let mut oldpath = ~"";
				while path != oldpath {
					oldpath = path;
					path = oldpath.replace("/../", "");
				}

				println(fmt!("Request for path: \n%?", path));
				let file_path = ~os::getcwd().push(path);
				if !os::path_exists(file_path) || os::path_is_dir(file_path) {
					println(fmt!("Request received:\n%s", request_str));
					let response: ~str = fmt!(
						"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n\r\n
			 <doctype !html><title>Hello, Rust!</title>

Greetings, Krusty!

Visitor count: %u

			 \r\n", visitor_count.read(|count| { *count }) );

					stream.write(response.as_bytes());
				}
				else {
					// may do scheduling here
					println("Starting to send file request...");
					let file_size = match io::file_reader(file_path) {
						Ok(file) => {
							file.seek(0, io::SeekEnd);
							file.tell()
						}
						Err(err) => {
							println(err);
							0u
						}
					};
					let req_id = visitor_count.read(|count| { *count });
					let msg: sched_msg = sched_msg{
						file_req_size: file_size,
										   in_charlottesville: in_charlottesville,
										   request_id: req_id,
										   stream: Some(stream),
										   filepath: file_path.clone()
					};
					let (sm_port, sm_chan) = std::comm::stream();
					sm_chan.send(msg);

					do child_vec.write |vec| {
						let msg = sm_port.recv();
						(*vec).push(msg); // enqueue new request.
						println(fmt!("add to queue with queue size %u", (*vec).len()));
					}
					println("Sending file request...");
					child_chan.send(""); //Notify the arriving request

					println(fmt!("get file request: %?", file_path));
				}
			}
			println!("connection terminates")
		}
	}
}
<|endoftext|>