<commit_before>use std::collections::BTreeMap;
use std::io::Read;

use serde_derive::{Deserialize, Serialize};
use snap::read::FrameDecoder;

use pueue_lib::log::{get_log_file_handles, read_last_lines};
use pueue_lib::network::message::TaskLogMessage;
use pueue_lib::settings::Settings;
use pueue_lib::task::Task;

/// This is the output struct used for
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TaskLog {
    pub task: Task,
    pub stdout: String,
    pub stderr: String,
}

pub fn print_log_json(
    task_log_messages: BTreeMap<usize, TaskLogMessage>,
    settings: &Settings,
    lines: Option<usize>,
) {
    let mut tasks: BTreeMap<usize, Task> = BTreeMap::new();
    let mut task_log: BTreeMap<usize, (String, String)> = BTreeMap::new();
    // Convert the TaskLogMessage into a proper JSON serializable format.
    // Output in TaskLogMessages, if it exists, is compressed.
    // We need to decompress and convert to normal strings.
    for (id, message) in task_log_messages {
        tasks.insert(id, message.task);

        if settings.client.read_local_logs {
            let output = get_local_logs(settings, id, lines);
            task_log.insert(id, output);
        } else {
            let output = get_remote_logs(message.stdout, message.stderr);
            task_log.insert(id, output);
        }
    }

    // Now assemble the final struct that will be returned
    let mut json = BTreeMap::new();
    for (id, task) in tasks {
        let (id, (stdout, stderr)) = task_log.remove_entry(&id).unwrap();

        json.insert(
            id,
            TaskLog {
                task,
                stdout,
                stderr,
            },
        );
    }

    println!("{}", serde_json::to_string(&json).unwrap());
}

/// Read logs directly from local files for a specific task.
fn get_local_logs(settings: &Settings, id: usize, lines: Option<usize>) -> (String, String) {
    let (mut stdout_file, mut stderr_file) =
        match get_log_file_handles(id, &settings.shared.pueue_directory()) {
            Ok((stdout, stderr)) => (stdout, stderr),
            Err(err) => {
                let error = format!("(Pueue error) Failed to get log file handles: {}", err);
                return (String::new(), error);
            }
        };

    let stdout = if let Some(lines) = lines {
        read_last_lines(&mut stdout_file, lines)
    } else {
        let mut stdout = String::new();
        if let Err(error) = stdout_file.read_to_string(&mut stdout) {
            stdout.push_str(&format!(
                "(Pueue error) Failed to read local log output file: {:?}",
                error
            ))
        };

        stdout
    };

    let stderr = if let Some(lines) = lines {
        read_last_lines(&mut stderr_file, lines)
    } else {
        let mut stderr = String::new();
        if let Err(error) = stderr_file.read_to_string(&mut stderr) {
            stderr.push_str(&format!(
                "(Pueue error) Failed to read local log output file: {:?}",
                error
            ))
        };

        stderr
    };

    (stdout, stderr)
}

/// Read logs from from compressed remote logs.
/// If logs don't exist, an empty string will be returned.
fn get_remote_logs(
    stdout_bytes: Option<Vec<u8>>,
    stderr_bytes: Option<Vec<u8>>,
) -> (String, String) {
    let stdout = if let Some(bytes) = stdout_bytes {
        let mut decoder = FrameDecoder::new(&bytes[..]);
        let mut stdout = String::new();
        if let Err(error) = decoder.read_to_string(&mut stdout) {
            stdout.push_str(&format!(
                "(Pueue error) Failed to decompress remote log output: {:?}",
                error
            ))
        }
        stdout
    } else {
        String::new()
    };

    let stderr = if let Some(bytes) = stderr_bytes {
        let mut decoder = FrameDecoder::new(&bytes[..]);
        let mut stderr = String::new();
        if let Err(error) = decoder.read_to_string(&mut stderr) {
            stderr.push_str(&format!(
                "(Pueue error) Failed to decompress remote log output: {:?}",
                error
            ))
        }

        stderr
    } else {
        String::new()
    };

    (stdout, stderr)
}
<commit_msg>Don't send environment variables in log json<commit_after>use std::collections::{BTreeMap, HashMap};
use std::io::Read;

use serde_derive::{Deserialize, Serialize};
use snap::read::FrameDecoder;

use pueue_lib::log::{get_log_file_handles, read_last_lines};
use pueue_lib::network::message::TaskLogMessage;
use pueue_lib::settings::Settings;
use pueue_lib::task::Task;

/// This is the output struct used for
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct TaskLog {
    pub task: Task,
    pub stdout: String,
    pub stderr: String,
}

pub fn print_log_json(
    task_log_messages: BTreeMap<usize, TaskLogMessage>,
    settings: &Settings,
    lines: Option<usize>,
) {
    let mut tasks: BTreeMap<usize, Task> = BTreeMap::new();
    let mut task_log: BTreeMap<usize, (String, String)> = BTreeMap::new();
    // Convert the TaskLogMessage into a proper JSON serializable format.
    // Output in TaskLogMessages, if it exists, is compressed.
    // We need to decompress and convert to normal strings.
    for (id, message) in task_log_messages {
        tasks.insert(id, message.task);

        if settings.client.read_local_logs {
            let output = get_local_logs(settings, id, lines);
            task_log.insert(id, output);
        } else {
            let output = get_remote_logs(message.stdout, message.stderr);
            task_log.insert(id, output);
        }
    }

    // Now assemble the final struct that will be returned
    let mut json = BTreeMap::new();
    for (id, mut task) in tasks {
        let (id, (stdout, stderr)) = task_log.remove_entry(&id).unwrap();

        task.envs = HashMap::new();
        json.insert(
            id,
            TaskLog {
                task,
                stdout,
                stderr,
            },
        );
    }

    println!("{}", serde_json::to_string(&json).unwrap());
}

/// Read logs directly from local files for a specific task.
fn get_local_logs(settings: &Settings, id: usize, lines: Option<usize>) -> (String, String) {
    let (mut stdout_file, mut stderr_file) =
        match get_log_file_handles(id, &settings.shared.pueue_directory()) {
            Ok((stdout, stderr)) => (stdout, stderr),
            Err(err) => {
                let error = format!("(Pueue error) Failed to get log file handles: {}", err);
                return (String::new(), error);
            }
        };

    let stdout = if let Some(lines) = lines {
        read_last_lines(&mut stdout_file, lines)
    } else {
        let mut stdout = String::new();
        if let Err(error) = stdout_file.read_to_string(&mut stdout) {
            stdout.push_str(&format!(
                "(Pueue error) Failed to read local log output file: {:?}",
                error
            ))
        };

        stdout
    };

    let stderr = if let Some(lines) = lines {
        read_last_lines(&mut stderr_file, lines)
    } else {
        let mut stderr = String::new();
        if let Err(error) = stderr_file.read_to_string(&mut stderr) {
            stderr.push_str(&format!(
                "(Pueue error) Failed to read local log output file: {:?}",
                error
            ))
        };

        stderr
    };

    (stdout, stderr)
}

/// Read logs from from compressed remote logs.
/// If logs don't exist, an empty string will be returned.
fn get_remote_logs(
    stdout_bytes: Option<Vec<u8>>,
    stderr_bytes: Option<Vec<u8>>,
) -> (String, String) {
    let stdout = if let Some(bytes) = stdout_bytes {
        let mut decoder = FrameDecoder::new(&bytes[..]);
        let mut stdout = String::new();
        if let Err(error) = decoder.read_to_string(&mut stdout) {
            stdout.push_str(&format!(
                "(Pueue error) Failed to decompress remote log output: {:?}",
                error
            ))
        }
        stdout
    } else {
        String::new()
    };

    let stderr = if let Some(bytes) = stderr_bytes {
        let mut decoder = FrameDecoder::new(&bytes[..]);
        let mut stderr = String::new();
        if let Err(error) = decoder.read_to_string(&mut stderr) {
            stderr.push_str(&format!(
                "(Pueue error) Failed to decompress remote log output: {:?}",
                error
            ))
        }

        stderr
    } else {
        String::new()
    };

    (stdout, stderr)
}
<|endoftext|>


<commit_before>extern crate redis;
use std::error::Error;
use redis::{Commands, PipelineCommands, transaction};

use std::collections::HashMap;

/// This function demonstrates how a return value can be coerced into a
/// hashmap of tuples.  This is particularly useful for responses like
/// CONFIG GET or all most H functions which will return responses in
/// such list of implied tuples.
fn do_print_max_entry_limits(con: &redis::Connection) -> redis::RedisResult<()> {
    // since rust cannot know what format we actually want we need to be
    // explicit here and define the type of our response.  In this case
    // String -> int fits all the items we query for.
    let config : HashMap<String, isize> = try!(
        redis::cmd("CONFIG").arg("GET").arg("*-max-*-entries").query(con));

    println!("Max entry limits:");

    println!("  max-intset:        {}", config.get(
        "set-max-intset-entries").unwrap_or(&0));
    println!("  hash-max-ziplist:  {}", config.get(
        "hash-max-ziplist-entries").unwrap_or(&0));
    println!("  list-max-ziplist:  {}", config.get(
        "list-max-ziplist-entries").unwrap_or(&0));
    println!("  zset-max-ziplist:  {}", config.get(
        "zset-max-ziplist-entries").unwrap_or(&0));

    Ok(())
}

/// This is a pretty stupid example that demonstrates how to create a large
/// set through a pipeline and how to iterate over it through implied
/// cursors.
fn do_show_scanning(con: &redis::Connection) -> redis::RedisResult<()> {
    // This makes a large pipeline of commands.  Because the pipeline is
    // modified in place we can just ignore the return value upon the end
    // of each iteration.
    let mut pipe = redis::pipe();
    for num in 0..1000 {
        pipe.cmd("SADD").arg("my_set").arg(num).ignore();
    }

    // since we don't care about the return value of the pipeline we can
    // just cast it into the unit type.
    let _ : () = try!(pipe.query(con));

    // since rust currently does not track temporaries for us, we need to
    // store it in a local variable.
    let mut cmd = redis::cmd("SSCAN");
    cmd.arg("my_set").cursor_arg(0);

    // as a simple exercise we just sum up the iterator.  Since the fold
    // method carries an initial value we do not need to define the
    // type of the iterator, rust will figure "int" out for us.
    let sum = try!(cmd.iter(con)).fold(0, |a, b| a + b);

    println!("The sum of all numbers in the set 0-1000: {}", sum);

    Ok(())
}

/// Demonstrates how to do an atomic increment in a very low level way.
fn do_atomic_increment_lowlevel(con: &redis::Connection) -> redis::RedisResult<()> {
    let key = "the_key";
    println!("Run low-level atomic increment:");

    // set the initial value so we have something to test with.
    let _ : () = try!(redis::cmd("SET").arg(key).arg(42).query(con));

    loop {
        // we need to start watching the key we care about, so that our
        // exec fails if the key changes.
        let _ : () = try!(redis::cmd("WATCH").arg(key).query(con));

        // load the old value, so we know what to increment.
        let val : isize = try!(redis::cmd("GET").arg(key).query(con));

        // at this point we can go into an atomic pipe (a multi block)
        // and set up the keys.
        let response : Option<(isize,)> = try!(redis::pipe()
            .atomic()
            .cmd("SET").arg(key).arg(val + 1).ignore()
            .cmd("GET").arg(key)
            .query(con));

        match response {
            None => { continue; }
            Some(response) => {
                let (new_val,) = response;
                println!("  New value: {}", new_val);
                break;
            }
        }
    }

    Ok(())
}

/// Demonstrates how to do an atomic increment with transaction support.
fn do_atomic_increment(con: &redis::Connection) -> redis::RedisResult<()> {
    let key = "the_key";
    println!("Run high-level atomic increment:");

    // set the initial value so we have something to test with.
    let _ : () = try!(con.set(key, 42));

    // run the transaction block.
    let (new_val,) : (isize,) = try!(transaction(con, &[key], |pipe| {
        // load the old value, so we know what to increment.
        let val : isize = try!(con.get(key));
        // increment
        pipe
            .set(key, val + 1).ignore()
            .get(key).query(con)
    }));

    // and print the result
    println!("New value: {}", new_val);

    Ok(())
}

/// Runs all the examples and propagates errors up.
fn do_redis_code() -> redis::RedisResult<()>
{
    // general connection handling
    let client = try!(redis::Client::open("redis://127.0.0.1/"));
    let con = try!(client.get_connection());

    // read some config and print it.
    try!(do_print_max_entry_limits(&con));

    // demonstrate how scanning works.
    try!(do_show_scanning(&con));

    // shows an atomic increment.
    try!(do_atomic_increment_lowlevel(&con));
    try!(do_atomic_increment(&con));

    Ok(())
}

fn main()
{
    // at this point the errors are fatal, let's just fail hard.
    match do_redis_code() {
        Err(err) => {
            println!("Could not execute example:");
            println!("  {}: {}", err.category(), err.description());
        },
        Ok(()) => {},
    }
}
<commit_msg>Fixed a broken example<commit_after>extern crate redis;
use std::error::Error;
use redis::{Commands, PipelineCommands, transaction};

use std::collections::HashMap;

/// This function demonstrates how a return value can be coerced into a
/// hashmap of tuples.  This is particularly useful for responses like
/// CONFIG GET or all most H functions which will return responses in
/// such list of implied tuples.
fn do_print_max_entry_limits(con: &redis::Connection) -> redis::RedisResult<()> {
    // since rust cannot know what format we actually want we need to be
    // explicit here and define the type of our response.  In this case
    // String -> int fits all the items we query for.
    let config : HashMap<String, isize> = try!(
        redis::cmd("CONFIG").arg("GET").arg("*-max-*-entries").query(con));

    println!("Max entry limits:");

    println!("  max-intset:        {}", config.get(
        "set-max-intset-entries").unwrap_or(&0));
    println!("  hash-max-ziplist:  {}", config.get(
        "hash-max-ziplist-entries").unwrap_or(&0));
    println!("  list-max-ziplist:  {}", config.get(
        "list-max-ziplist-entries").unwrap_or(&0));
    println!("  zset-max-ziplist:  {}", config.get(
        "zset-max-ziplist-entries").unwrap_or(&0));

    Ok(())
}

/// This is a pretty stupid example that demonstrates how to create a large
/// set through a pipeline and how to iterate over it through implied
/// cursors.
fn do_show_scanning(con: &redis::Connection) -> redis::RedisResult<()> {
    // This makes a large pipeline of commands.  Because the pipeline is
    // modified in place we can just ignore the return value upon the end
    // of each iteration.
    let mut pipe = redis::pipe();
    for num in 0..1000 {
        pipe.cmd("SADD").arg("my_set").arg(num).ignore();
    }

    // since we don't care about the return value of the pipeline we can
    // just cast it into the unit type.
    let _ : () = try!(pipe.query(con));

    // since rust currently does not track temporaries for us, we need to
    // store it in a local variable.
    let mut cmd = redis::cmd("SSCAN");
    cmd.arg("my_set").cursor_arg(0);

    // as a simple exercise we just sum up the iterator.  Since the fold
    // method carries an initial value we do not need to define the
    // type of the iterator, rust will figure "int" out for us.
    let sum = try!(cmd.iter::<i32>(con)).fold(0, |a, b| a + b);

    println!("The sum of all numbers in the set 0-1000: {}", sum);

    Ok(())
}

/// Demonstrates how to do an atomic increment in a very low level way.
fn do_atomic_increment_lowlevel(con: &redis::Connection) -> redis::RedisResult<()> {
    let key = "the_key";
    println!("Run low-level atomic increment:");

    // set the initial value so we have something to test with.
    let _ : () = try!(redis::cmd("SET").arg(key).arg(42).query(con));

    loop {
        // we need to start watching the key we care about, so that our
        // exec fails if the key changes.
        let _ : () = try!(redis::cmd("WATCH").arg(key).query(con));

        // load the old value, so we know what to increment.
        let val : isize = try!(redis::cmd("GET").arg(key).query(con));

        // at this point we can go into an atomic pipe (a multi block)
        // and set up the keys.
        let response : Option<(isize,)> = try!(redis::pipe()
            .atomic()
            .cmd("SET").arg(key).arg(val + 1).ignore()
            .cmd("GET").arg(key)
            .query(con));

        match response {
            None => { continue; }
            Some(response) => {
                let (new_val,) = response;
                println!("  New value: {}", new_val);
                break;
            }
        }
    }

    Ok(())
}

/// Demonstrates how to do an atomic increment with transaction support.
fn do_atomic_increment(con: &redis::Connection) -> redis::RedisResult<()> {
    let key = "the_key";
    println!("Run high-level atomic increment:");

    // set the initial value so we have something to test with.
    let _ : () = try!(con.set(key, 42));

    // run the transaction block.
    let (new_val,) : (isize,) = try!(transaction(con, &[key], |pipe| {
        // load the old value, so we know what to increment.
        let val : isize = try!(con.get(key));
        // increment
        pipe
            .set(key, val + 1).ignore()
            .get(key).query(con)
    }));

    // and print the result
    println!("New value: {}", new_val);

    Ok(())
}

/// Runs all the examples and propagates errors up.
fn do_redis_code() -> redis::RedisResult<()>
{
    // general connection handling
    let client = try!(redis::Client::open("redis://127.0.0.1/"));
    let con = try!(client.get_connection());

    // read some config and print it.
    try!(do_print_max_entry_limits(&con));

    // demonstrate how scanning works.
    try!(do_show_scanning(&con));

    // shows an atomic increment.
    try!(do_atomic_increment_lowlevel(&con));
    try!(do_atomic_increment(&con));

    Ok(())
}

fn main()
{
    // at this point the errors are fatal, let's just fail hard.
    match do_redis_code() {
        Err(err) => {
            println!("Could not execute example:");
            println!("  {}: {}", err.category(), err.description());
        },
        Ok(()) => {},
    }
}
<|endoftext|>


<commit_before>//! Routes are used for ratelimiting. These are to differentiate between the
//! different _types_ of routes - such as getting the current user's channels -
//! for the most part, with the exception being major parameters.
//!
//! [Taken from] the Discord docs, major parameters are:
//!
//! > Additionally, rate limits take into account major parameters in the URL.
//! > For example, `/channels/:channel_id` and
//! > `/channels/:channel_id/messages/:message_id` both take `channel_id` into
//! > account when generating rate limits since it's the major parameter. The
//! only current major parameters are `channel_id` and `guild_id`.
//!
//! This results in the two URIs of `GET /channels/4/messages/7` and
//! `GET /channels/5/messages/8` being rate limited _separately_. However, the
//! two URIs of `GET /channels/10/messages/11` and
//! `GET /channels/10/messages/12` will count towards the "same ratelimit", as
//! the major parameter - `10` is equivalent in both URIs' format.
//!
//! # Examples
//!
//! First: taking the first two URIs - `GET /channels/4/messages/7` and
//! `GET /channels/5/messages/8` - and assuming both buckets have a `limit` of
//! `10`, requesting the first URI will result in the response containing a
//! `remaining` of `9`. Immediately after - prior to buckets resetting -
//! performing a request to the _second_ URI will also contain a `remaining` of
//! `9` in the response, as the major parameter - `channel_id` - is different
//! in the two requests (`4` and `5`).
//!
//! Second: take for example the last two URIs. Assuming the bucket's `limit` is
//! `10`, requesting the first URI will return a `remaining` of `9` in the
//! response. Immediately after - prior to buckets resetting - performing a
//! request to the _second_ URI will return a `remaining` of `8` in the
//! response, as the major parameter - `channel_id` - is equivalent for the two
//! requests (`10`).
//!
//!
//! With the examples out of the way: major parameters are why some variants
//! (i.e. all of the channel/guild variants) have an associated u64 as data.
//! This is the Id of the parameter, differentiating between different
//! ratelimits.

use hyper::client::{RequestBuilder, Response};
use hyper::header::Headers;
use hyper::status::StatusCode;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::{str, thread};
use time;
use ::internal::prelude::*;

lazy_static! {
    static ref GLOBAL: Arc<Mutex<()>> = Arc::new(Mutex::new(()));
    static ref ROUTES: Arc<Mutex<HashMap<Route, RateLimit>>> = Arc::new(Mutex::new(HashMap::default()));
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Route {
    ChannelsId(u64),
    ChannelsIdInvites(u64),
    ChannelsIdMessages(u64),
    ChannelsIdMessagesBulkDelete(u64),
    ChannelsIdMessagesId(u64),
    ChannelsIdMessagesIdAck(u64),
    ChannelsIdMessagesIdReactions(u64),
    ChannelsIdMessagesIdReactionsUserIdType(u64),
    ChannelsIdMessagesSearch(u64),
    ChannelsIdPermissionsOverwriteId(u64),
    ChannelsIdPins(u64),
    ChannelsIdPinsMessageId(u64),
    ChannelsIdTyping(u64),
    ChannelsIdWebhooks(u64),
    Gateway,
    GatewayBot,
    Guilds,
    GuildsId(u64),
    GuildsIdBans(u64),
    GuildsIdBansUserId(u64),
    GuildsIdChannels(u64),
    GuildsIdEmbed(u64),
    GuildsIdEmojis(u64),
    GuildsIdEmojisId(u64),
    GuildsIdIntegrations(u64),
    GuildsIdIntegrationsId(u64),
    GuildsIdIntegrationsIdSync(u64),
    GuildsIdInvites(u64),
    GuildsIdMembers(u64),
    GuildsIdMembersId(u64),
    GuildsIdMembersIdRolesId(u64),
    GuildsIdMembersMeNick(u64),
    GuildsIdMessagesSearch(u64),
    GuildsIdPrune(u64),
    GuildsIdRegions(u64),
    GuildsIdRoles(u64),
    GuildsIdRolesId(u64),
    GuildsIdWebhooks(u64),
    InvitesCode,
    UsersId,
    UsersMe,
    UsersMeChannels,
    UsersMeConnections,
    UsersMeGuilds,
    UsersMeGuildsId,
    VoiceRegions,
    WebhooksId,
    None,
}

pub fn perform<'a, F>(route: Route, f: F) -> Result<Response>
    where F: Fn() -> RequestBuilder<'a> {

    loop {
        {
            // This will block if another thread already has the global
            // unlocked already (due to receiving an x-ratelimit-global).
            let mut _global = GLOBAL.lock().expect("global route lock poisoned");
        }

        // Perform pre-checking here:
        //
        // - get the route's relevant rate
        // - sleep if that route's already rate-limited until the end of the
        //   'reset' time;
        // - get the global rate;
        // - sleep if there is 0 remaining
        // - then, perform the request
        if route != Route::None {
            if let Some(route) = ROUTES.lock().expect("routes poisoned").get_mut(&route) {
                route.pre_hook();
            }
        }

        let response = super::retry(&f)?;

        // Check if the request got ratelimited by checking for status 429,
        // and if so, sleep for the value of the header 'retry-after' -
        // which is in milliseconds - and then `continue` to try again
        //
        // If it didn't ratelimit, subtract one from the RateLimit's
        // 'remaining'
        //
        // Update the 'reset' with the value of the 'x-ratelimit-reset'
        // header
        //
        // It _may_ be possible for the limit to be raised at any time,
        // so check if it did from the value of the 'x-ratelimit-limit'
        // header. If the limit was 5 and is now 7, add 2 to the 'remaining'
        if route != Route::None {
            let redo = if response.headers.get_raw("x-ratelimit-global").is_some() {
                let _ = GLOBAL.lock().expect("global route lock poisoned");

                Ok(if let Some(retry_after) = get_header(&response.headers, "retry-after")? {
                    debug!("Ratelimited: {:?}ms", retry_after);
                    thread::sleep(Duration::from_millis(retry_after as u64));

                    true
                } else {
                    false
                })
            } else {
                ROUTES.lock()
                    .expect("routes poisoned")
                    .entry(route)
                    .or_insert_with(RateLimit::default)
                    .post_hook(&response)
            };

            if redo.unwrap_or(false) {
                continue;
            }
        }

        return Ok(response);
    }
}

#[derive(Clone, Debug, Default)]
pub struct RateLimit {
    limit: i64,
    remaining: i64,
    reset: i64,
}

impl RateLimit {
    pub fn pre_hook(&mut self) {
        if self.limit == 0 {
            return;
        }

        let current_time = time::get_time().sec;

        // The reset was in the past, so we're probably good.
        if current_time > self.reset {
            self.remaining = self.limit;

            return;
        }

        let diff = (self.reset - current_time) as u64;

        if self.remaining == 0 {
            let delay = (diff * 1000) + 500;

            debug!("Pre-emptive ratelimit for {:?}ms", delay);
            thread::sleep(Duration::from_millis(delay));

            return;
        }

        self.remaining -= 1;
    }

    pub fn post_hook(&mut self, response: &Response) -> Result<bool> {
        if let Some(limit) = get_header(&response.headers, "x-ratelimit-limit")? {
            self.limit = limit;
        }

        if let Some(remaining) = get_header(&response.headers, "x-ratelimit-remaining")? {
            self.remaining = remaining;
        }

        if let Some(reset) = get_header(&response.headers, "x-ratelimit-reset")? {
            self.reset = reset;
        }

        Ok(if response.status != StatusCode::TooManyRequests {
            false
        } else if let Some(retry_after) = get_header(&response.headers, "retry-after")? {
            debug!("Ratelimited: {:?}ms", retry_after);
            thread::sleep(Duration::from_millis(retry_after as u64));

            true
        } else {
            false
        })
    }
}

fn get_header(headers: &Headers, header: &str) -> Result<Option<i64>> {
    match headers.get_raw(header) {
        Some(header) => match str::from_utf8(&header[0]) {
            Ok(v) => match v.parse::<i64>() {
                Ok(v) => Ok(Some(v)),
                Err(_) => Err(Error::Client(ClientError::RateLimitI64)),
            },
            Err(_) => Err(Error::Client(ClientError::RateLimitUtf8)),
        },
        None => Ok(None),
    }
}
<commit_msg>Expose and document ratelimiting<commit_after>//! Routes are used for ratelimiting. These are to differentiate between the
//! different _types_ of routes - such as getting the current user's channels -
//! for the most part, with the exception being major parameters.
//!
//! [Taken from] the Discord docs, major parameters are:
//!
//! > Additionally, rate limits take into account major parameters in the URL.
//! > For example, `/channels/:channel_id` and
//! > `/channels/:channel_id/messages/:message_id` both take `channel_id` into
//! > account when generating rate limits since it's the major parameter. The
//! only current major parameters are `channel_id` and `guild_id`.
//!
//! This results in the two URIs of `GET /channels/4/messages/7` and
//! `GET /channels/5/messages/8` being rate limited _separately_. However, the
//! two URIs of `GET /channels/10/messages/11` and
//! `GET /channels/10/messages/12` will count towards the "same ratelimit", as
//! the major parameter - `10` is equivalent in both URIs' format.
//!
//! # Examples
//!
//! First: taking the first two URIs - `GET /channels/4/messages/7` and
//! `GET /channels/5/messages/8` - and assuming both buckets have a `limit` of
//! `10`, requesting the first URI will result in the response containing a
//! `remaining` of `9`. Immediately after - prior to buckets resetting -
//! performing a request to the _second_ URI will also contain a `remaining` of
//! `9` in the response, as the major parameter - `channel_id` - is different
//! in the two requests (`4` and `5`).
//!
//! Second: take for example the last two URIs. Assuming the bucket's `limit` is
//! `10`, requesting the first URI will return a `remaining` of `9` in the
//! response. Immediately after - prior to buckets resetting - performing a
//! request to the _second_ URI will return a `remaining` of `8` in the
//! response, as the major parameter - `channel_id` - is equivalent for the two
//! requests (`10`).
//!
//! Major parameters are why some variants (i.e. all of the channel/guild
//! variants) have an associated u64 as data. This is the Id of the parameter,
//! differentiating between different ratelimits.
//!
//! [Taken from]: https://discordapp.com/developers/docs/topics/rate-limits#rate-limits

use hyper::client::{RequestBuilder, Response};
use hyper::header::Headers;
use hyper::status::StatusCode;
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use std::time::Duration;
use std::{str, thread};
use time;
use ::internal::prelude::*;

lazy_static! {
    /// The global mutex is a mutex unlocked and then immediately re-locked
    /// prior to every request, to abide by Discord's global ratelimit.
    ///
    /// The global ratelimit is the total number of requests that may be made
    /// across the entirity of the API within an amount of time. If this is
    /// reached, then the global mutex is unlocked for the amount of time
    /// present in the "Retry-After" header.
    ///
    /// While locked, all requests are blocked until each request can acquire
    /// the lock.
    ///
    /// The only reason that you would need to use the global mutex is to
    /// block requests yourself. This has the side-effect of potentially
    /// blocking many of your event handlers or framework commands.
    pub static ref GLOBAL: Arc<Mutex<()>> = Arc::new(Mutex::new(()));
    /// The routes mutex is a HashMap of each [`Route`] and their respective
    /// ratelimit information.
    ///
    /// See the documentation for [`RateLimit`] for more infomation on how the
    /// library handles ratelimiting.
    ///
    /// # Examples
    ///
    /// View the `reset` time of the route for `ChannelsId(7)`:
    ///
    /// ```rust,no_run
    /// use serenity::client::rest::ratelimiting::{ROUTES, Route};
    ///
    /// let routes = ROUTES.lock().unwrap();
    ///
    /// if let Some(route) = routes.get(&Route::ChannelsId(7)) {
    ///     println!("Reset time at: {}", route.reset);
    /// }
    /// ```
    ///
    /// [`RateLimit`]: struct.RateLimit.html
    /// [`Route`]: enum.Route.html
    pub static ref ROUTES: Arc<Mutex<HashMap<Route, RateLimit>>> = Arc::new(Mutex::new(HashMap::default()));
}

/// A representation of all routes registered within the library. These are safe
/// and memory-efficient representations of each path that functions exist for
/// in the [`rest`] module.
///
/// [`rest`]: ../index.html
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Route {
    ChannelsId(u64),
    ChannelsIdInvites(u64),
    ChannelsIdMessages(u64),
    ChannelsIdMessagesBulkDelete(u64),
    ChannelsIdMessagesId(u64),
    ChannelsIdMessagesIdAck(u64),
    ChannelsIdMessagesIdReactions(u64),
    ChannelsIdMessagesIdReactionsUserIdType(u64),
    ChannelsIdMessagesSearch(u64),
    ChannelsIdPermissionsOverwriteId(u64),
    ChannelsIdPins(u64),
    ChannelsIdPinsMessageId(u64),
    ChannelsIdTyping(u64),
    ChannelsIdWebhooks(u64),
    Gateway,
    GatewayBot,
    Guilds,
    GuildsId(u64),
    GuildsIdBans(u64),
    GuildsIdBansUserId(u64),
    GuildsIdChannels(u64),
    GuildsIdEmbed(u64),
    GuildsIdEmojis(u64),
    GuildsIdEmojisId(u64),
    GuildsIdIntegrations(u64),
    GuildsIdIntegrationsId(u64),
    GuildsIdIntegrationsIdSync(u64),
    GuildsIdInvites(u64),
    GuildsIdMembers(u64),
    GuildsIdMembersId(u64),
    GuildsIdMembersIdRolesId(u64),
    GuildsIdMembersMeNick(u64),
    GuildsIdMessagesSearch(u64),
    GuildsIdPrune(u64),
    GuildsIdRegions(u64),
    GuildsIdRoles(u64),
    GuildsIdRolesId(u64),
    GuildsIdWebhooks(u64),
    InvitesCode,
    UsersId,
    UsersMe,
    UsersMeChannels,
    UsersMeConnections,
    UsersMeGuilds,
    UsersMeGuildsId,
    VoiceRegions,
    WebhooksId,
    None,
}

#[doc(hidden)]
pub fn perform<'a, F>(route: Route, f: F) -> Result<Response>
    where F: Fn() -> RequestBuilder<'a> {

    loop {
        {
            // This will block if another thread already has the global
            // unlocked already (due to receiving an x-ratelimit-global).
            let mut _global = GLOBAL.lock().expect("global route lock poisoned");
        }

        // Perform pre-checking here:
        //
        // - get the route's relevant rate
        // - sleep if that route's already rate-limited until the end of the
        //   'reset' time;
        // - get the global rate;
        // - sleep if there is 0 remaining
        // - then, perform the request
        if route != Route::None {
            if let Some(route) = ROUTES.lock().expect("routes poisoned").get_mut(&route) {
                route.pre_hook();
            }
        }

        let response = super::retry(&f)?;

        // Check if the request got ratelimited by checking for status 429,
        // and if so, sleep for the value of the header 'retry-after' -
        // which is in milliseconds - and then `continue` to try again
        //
        // If it didn't ratelimit, subtract one from the RateLimit's
        // 'remaining'
        //
        // Update the 'reset' with the value of the 'x-ratelimit-reset'
        // header
        //
        // It _may_ be possible for the limit to be raised at any time,
        // so check if it did from the value of the 'x-ratelimit-limit'
        // header. If the limit was 5 and is now 7, add 2 to the 'remaining'
        if route != Route::None {
            let redo = if response.headers.get_raw("x-ratelimit-global").is_some() {
                let _ = GLOBAL.lock().expect("global route lock poisoned");

                Ok(if let Some(retry_after) = get_header(&response.headers, "retry-after")? {
                    debug!("Ratelimited: {:?}ms", retry_after);
                    thread::sleep(Duration::from_millis(retry_after as u64));

                    true
                } else {
                    false
                })
            } else {
                ROUTES.lock()
                    .expect("routes poisoned")
                    .entry(route)
                    .or_insert_with(RateLimit::default)
                    .post_hook(&response)
            };

            if redo.unwrap_or(false) {
                continue;
            }
        }

        return Ok(response);
    }
}

/// A set of data containing information about the ratelimits for a particular
/// [`Route`], which is stored in the [`ROUTES`] mutex.
///
/// See the [Discord docs] on ratelimits for more information.
///
/// **Note**: You should _not_ mutate any of the fields, as this can help cause
/// 429s.
///
/// [`ROUTES`]: struct.ROUTES.html
/// [`Route`]: enum.Route.html
/// [Discord docs]: https://discordapp.com/developers/docs/topics/rate-limits
#[derive(Clone, Debug, Default)]
pub struct RateLimit {
    /// The total number of requests that can be made in a period of time.
    pub limit: i64,
    /// The number of requests remaining in the period of time.
    pub remaining: i64,
    /// When the interval resets and the the [`limit`] resets to the value of
    /// [`remaining`].
    ///
    /// [`limit`]: #structfield.limit
    /// [`remaining`]: #structfield.remaining
    pub reset: i64,
}

impl RateLimit {
    #[doc(hidden)]
    pub fn pre_hook(&mut self) {
        if self.limit == 0 {
            return;
        }

        let current_time = time::get_time().sec;

        // The reset was in the past, so we're probably good.
        if current_time > self.reset {
            self.remaining = self.limit;

            return;
        }

        let diff = (self.reset - current_time) as u64;

        if self.remaining == 0 {
            let delay = (diff * 1000) + 500;

            debug!("Pre-emptive ratelimit for {:?}ms", delay);
            thread::sleep(Duration::from_millis(delay));

            return;
        }

        self.remaining -= 1;
    }

    #[doc(hidden)]
    pub fn post_hook(&mut self, response: &Response) -> Result<bool> {
        if let Some(limit) = get_header(&response.headers, "x-ratelimit-limit")? {
            self.limit = limit;
        }

        if let Some(remaining) = get_header(&response.headers, "x-ratelimit-remaining")? {
            self.remaining = remaining;
        }

        if let Some(reset) = get_header(&response.headers, "x-ratelimit-reset")? {
            self.reset = reset;
        }

        Ok(if response.status != StatusCode::TooManyRequests {
            false
        } else if let Some(retry_after) = get_header(&response.headers, "retry-after")? {
            debug!("Ratelimited: {:?}ms", retry_after);
            thread::sleep(Duration::from_millis(retry_after as u64));

            true
        } else {
            false
        })
    }
}

fn get_header(headers: &Headers, header: &str) -> Result<Option<i64>> {
    match headers.get_raw(header) {
        Some(header) => match str::from_utf8(&header[0]) {
            Ok(v) => match v.parse::<i64>() {
                Ok(v) => Ok(Some(v)),
                Err(_) => Err(Error::Client(ClientError::RateLimitI64)),
            },
            Err(_) => Err(Error::Client(ClientError::RateLimitUtf8)),
        },
        None => Ok(None),
    }
}
<|endoftext|>


<commit_before>extern crate risp;

use risp::*;
use risp::types::RispType::*;
use risp::core::create_core_environment;

#[test]
fn test_sum() {
    assert_eq!(eval_risp(r"
        (+ 1
            (* 2 3)
        )
    "), Ok(Int(7)));
}

#[test]
fn test_def() {
    let mut env = create_core_environment();

    assert_eq!(eval_risp_for_env(r"
        (def variable
            (* 2 3)
        )
    ", &mut env), Ok(Int(6)));

    assert_eq!(env.get("variable"), Some(Int(6)));

}

#[test]
fn test_parsing_errors() {
    assert!(eval_risp("(").is_err());
    assert!(eval_risp(")").is_err());
    assert!(eval_risp("").is_err());
}

#[test]
fn test_eval_errors() {
    assert!(eval_risp("()").is_err());
    assert!(eval_risp("(1 2)").is_err());
    assert!(eval_risp("(a 2)").is_err());
    assert!(eval_risp("(def)").is_err());
    assert!(eval_risp("(def a)").is_err());
    assert!(eval_risp("(def 1 2)").is_err());
}

#[test]
fn test_eval_error_expected_function() {
    let mut env = create_core_environment();
    env.set("var", Int(1));
    assert!(eval_risp("(var 1 2 3)").is_err());
}<commit_msg>fixed test_eval_error_expected_function<commit_after>extern crate risp;

use risp::*;
use risp::types::RispType::*;
use risp::types::error_result;
use risp::core::create_core_environment;

#[test]
fn test_sum() {
    assert_eq!(eval_risp(r"
        (+ 1
            (* 2 3)
        )
    "), Ok(Int(7)));
}

#[test]
fn test_def() {
    let mut env = create_core_environment();

    assert_eq!(eval_risp_for_env(r"
        (def variable
            (* 2 3)
        )
    ", &mut env), Ok(Int(6)));

    assert_eq!(env.get("variable"), Some(Int(6)));

}

#[test]
fn test_parsing_errors() {
    assert!(eval_risp("(").is_err());
    assert!(eval_risp(")").is_err());
    assert!(eval_risp("").is_err());
}

#[test]
fn test_eval_errors() {
    assert!(eval_risp("()").is_err());
    assert!(eval_risp("(1 2)").is_err());
    assert!(eval_risp("(a 2)").is_err());
    assert!(eval_risp("(def)").is_err());
    assert!(eval_risp("(def a)").is_err());
    assert!(eval_risp("(def 1 2)").is_err());
}

#[test]
fn test_eval_error_expected_function() {
    let mut env = create_core_environment();
    env.set("var", Int(1));
    let result = eval_risp_for_env("(var 1 2 3)", &mut env);
    assert_eq!(result, error_result("Expected function but got Int(1)"));
}<|endoftext|>


<commit_before>//! Unwinding for *hermit* target.
//!
//! Right now we don't support this, so this is just stubs.

use alloc::boxed::Box;
use core::any::Any;
use core::ptr;

pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
    extern "C" {
        pub fn __rust_abort() -> !;
    }
    __rust_abort();
}

pub unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
    extern "C" {
        pub fn __rust_abort() -> !;
    }
    __rust_abort();
}
<commit_msg>Rollup merge of #70133 - hermitcore:libpanic_unwind, r=nikomatsakis<commit_after>//! Unwinding for *hermit* target.
//!
//! Right now we don't support this, so this is just stubs.

use alloc::boxed::Box;
use core::any::Any;

pub unsafe fn cleanup(_ptr: *mut u8) -> Box<dyn Any + Send> {
    extern "C" {
        pub fn __rust_abort() -> !;
    }
    __rust_abort();
}

pub unsafe fn panic(_data: Box<dyn Any + Send>) -> u32 {
    extern "C" {
        pub fn __rust_abort() -> !;
    }
    __rust_abort();
}
<|endoftext|>


<commit_before>extern crate rustty;

use rustty::{
    Terminal,
    Event,
    HasSize,
    CellAccessor
};

use rustty::ui::{
    Painter,
    Dialog,
    Widget,
    Alignable,
    HorizontalAlign,
    VerticalAlign
};

const BLOCK: char = '\u{25AA}';

fn create_optiondlg() -> Dialog {
    let mut optiondlg = Dialog::new(50, 6);
    let inc_label = "+ -> Increase Radius";
    let dec_label = "+ -> Decrease Radius";
    let q_label = "q -> Quit";
    let inc_pos = optiondlg.window().halign_line(inc_label, HorizontalAlign::Left, 1);
    let dec_pos = optiondlg.window().halign_line(dec_label, HorizontalAlign::Left, 1);
    let q_pos = optiondlg.window().halign_line(q_label, HorizontalAlign::Left, 1);
    optiondlg.window_mut().printline(inc_pos, 1, inc_label);
    optiondlg.window_mut().printline(dec_pos, 2, dec_label);
    optiondlg.window_mut().printline(q_pos, 3, q_label);
    optiondlg.window_mut().draw_box();
    optiondlg
}

fn main() {
    // Create our terminal, dialog window and main canvas
    let mut term = Terminal::new().unwrap();
    let mut optiondlg = create_optiondlg();
    let mut canvas = Widget::new(term.size().0, term.size().1 - 4);

    // Align canvas to top left, and dialog to bottom right
    optiondlg.window_mut().align(&term, HorizontalAlign::Right, VerticalAlign::Bottom, 0);
    canvas.align(&term, HorizontalAlign::Left, VerticalAlign::Top, 0);

    let mut radius = 10u32;
    'main: loop {
        while let Some(Event::Key(ch)) = term.get_event(0).unwrap() {
            match ch {
                'q' => break 'main,
                '+' => radius = radius.saturating_add(1),
                '-' => radius = radius.saturating_sub(1),
                _ => {},
            }
        }
        // Grab the size of the canvas
        let (cols, rows) = canvas.size();
        let (cols, rows) = (cols as isize, rows as isize);

        let (a, b) = (cols / 2, rows / 2);

        // Main render loop, draws the circle to canvas
        for i in 0..cols*rows {
            let y = i as isize / cols;
            let x = i as isize % cols;

            let mut cell = canvas.get_mut(x as usize, y as usize).unwrap();

            if ((x - a).pow(2)/4 + (y - b).pow(2)) <= radius.pow(2) as isize {
                cell.set_ch(BLOCK);
            } else {
                cell.set_ch(' ');
            }
        }

        // draw the canvas, dialog window and swap buffers
        canvas.draw_into(&mut term);
        optiondlg.window().draw_into(&mut term);
        term.swap_buffers().unwrap();
    }
}
<commit_msg>Refactor circle.rs to use new API<commit_after>extern crate rustty;

use rustty::{
    Terminal,
    Event,
    HasSize,
    CellAccessor
};

use rustty::ui::core::{
    Painter,
    Widget,
    Base,
    Alignable,
    HorizontalAlign,
    VerticalAlign,
    ButtonResult
};

use rustty::ui::{
    Dialog,
    StdButton
};

const BLOCK: char = '\u{25AA}';

fn create_optiondlg() -> Dialog {
    let mut optiondlg = Dialog::new(50, 6);
    let mut inc_b = StdButton::new(" + :Increase Radius", '+', ButtonResult::Custom(1));
    inc_b.pack(&optiondlg, HorizontalAlign::Left, VerticalAlign::Top, 1);
    let mut dec_b = StdButton::new(" - :Decrease Radius", '-', ButtonResult::Custom(2));
    dec_b.pack(&optiondlg, HorizontalAlign::Left, VerticalAlign::Middle, 1);
    let mut quit_b = StdButton::new("Quit", 'q', ButtonResult::Ok);
    quit_b.pack(&optiondlg, HorizontalAlign::Left, VerticalAlign::Bottom, 1);

    optiondlg.add_button(inc_b);
    optiondlg.add_button(dec_b);
    optiondlg.add_button(quit_b);

    optiondlg.window_mut().draw_box();
    optiondlg
}

fn main() {
    // Create our terminal, dialog window and main canvas
    let mut term = Terminal::new().unwrap();
    let mut optiondlg = create_optiondlg();
    let mut canvas = Base::new(term.size().0, term.size().1 - 4);

    // Align canvas to top left, and dialog to bottom right
    optiondlg.window_mut().align(&term, HorizontalAlign::Right, VerticalAlign::Bottom, 0);
    canvas.align(&term, HorizontalAlign::Left, VerticalAlign::Top, 0);

    let mut radius = 10u32;
    'main: loop {
        while let Some(Event::Key(ch)) = term.get_event(0).unwrap() {
            match optiondlg.result_for_key(ch) {
                Some(ButtonResult::Ok)          => break 'main,
                Some(ButtonResult::Custom(i))   => {
                    radius =
                        if i == 1 {
                            radius.saturating_add(1)
                        } else {
                            radius.saturating_sub(1)
                        };
                },
                _ => {},
            }
        }
        // Grab the size of the canvas
        let (cols, rows) = canvas.size();
        let (cols, rows) = (cols as isize, rows as isize);

        let (a, b) = (cols / 2, rows / 2);

        // Main render loop, draws the circle to canvas
        for i in 0..cols*rows {
            let y = i as isize / cols;
            let x = i as isize % cols;

            let mut cell = canvas.get_mut(x as usize, y as usize).unwrap();

            if ((x - a).pow(2)/4 + (y - b).pow(2)) <= radius.pow(2) as isize {
                cell.set_ch(BLOCK);
            } else {
                cell.set_ch(' ');
            }
        }

        // draw the canvas, dialog window and swap buffers
        canvas.draw_into(&mut term);
        optiondlg.window().draw_into(&mut term);
        term.swap_buffers().unwrap();
    }
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;
extern crate rocket_contrib;
#[macro_use] extern crate serde_derive;

/// Contains all the routes for Satellite.
mod routes;

use rocket_contrib::Template;

/// Creates a new Rocket instance ready to launch the cms.
///
/// You can add more routes, fairings and managed state afert calling
/// this function.
///
/// # Examples
///
/// Launch the instance without additional configuration.
///
/// ```rust,ignore
/// use satellite_core::rocket;
///
/// fn main() {
///     rocket().launch();
/// }
/// ```
pub fn rocket() -> rocket::Rocket {
    rocket::ignite()
        .mount("/", routes.routes())
        .attach(Template::fairing())
}
<commit_msg>Corrected typo<commit_after>#![feature(plugin)]
#![plugin(rocket_codegen)]

extern crate rocket;
extern crate rocket_contrib;
#[macro_use] extern crate serde_derive;

/// Contains all the routes for Satellite.
mod routes;

use rocket_contrib::Template;

/// Creates a new Rocket instance ready to launch the cms.
///
/// You can add more routes, fairings and managed state afert calling
/// this function.
///
/// # Examples
///
/// Launch the instance without additional configuration.
///
/// ```rust,ignore
/// use satellite_core::rocket;
///
/// fn main() {
///     rocket().launch();
/// }
/// ```
pub fn rocket() -> rocket::Rocket {
    rocket::ignite()
        .mount("/", routes::routes())
        .attach(Template::fairing())
}
<|endoftext|>


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

use metadata::cstore::LOCAL_CRATE;
use middle::ty;
use syntax::ast::CrateNum;
use std::fmt;
use std::u32;

/// A DefIndex is an index into the hir-map for a crate, identifying a
/// particular definition. It should really be considered an interned
/// shorthand for a particular DefPath.
#[derive(Clone, Debug, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
           RustcDecodable, Hash, Copy)]
pub struct DefIndex(u32);

impl DefIndex {
    pub fn new(x: usize) -> DefIndex {
        assert!(x < (u32::MAX as usize));
        DefIndex(x as u32)
    }

    pub fn from_u32(x: u32) -> DefIndex {
        DefIndex(x)
    }

    pub fn as_usize(&self) -> usize {
        self.0 as usize
    }

    pub fn as_u32(&self) -> u32 {
        self.0
    }
}

/// The crate root is always assigned index 0 by the AST Map code,
/// thanks to `NodeCollector::new`.
pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);

/// A DefId identifies a particular *definition*, by combining a crate
/// index and a def index.
#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
           RustcDecodable, Hash, Copy)]
pub struct DefId {
    pub krate: CrateNum,
    pub index: DefIndex,
}

impl fmt::Debug for DefId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "DefId {{ krate: {:?}, node: {:?}",
                    self.krate, self.index));

        // Unfortunately, there seems to be no way to attempt to print
        // a path for a def-id, so I'll just make a best effort for now
        // and otherwise fallback to just printing the crate/node pair
        try!(ty::tls::with_opt(|opt_tcx| {
            if let Some(tcx) = opt_tcx {
                try!(write!(f, " => {}", tcx.item_path_str(*self)));
            }
            Ok(())
        }));

        write!(f, " }}")
    }
}

impl DefId {
    pub fn local(index: DefIndex) -> DefId {
        DefId { krate: LOCAL_CRATE, index: index }
    }

    pub fn is_local(&self) -> bool {
        self.krate == LOCAL_CRATE
    }
}
<commit_msg>do not dump extern def-ids with path for now<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use metadata::cstore::LOCAL_CRATE;
use middle::ty;
use syntax::ast::CrateNum;
use std::fmt;
use std::u32;

/// A DefIndex is an index into the hir-map for a crate, identifying a
/// particular definition. It should really be considered an interned
/// shorthand for a particular DefPath.
#[derive(Clone, Debug, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
           RustcDecodable, Hash, Copy)]
pub struct DefIndex(u32);

impl DefIndex {
    pub fn new(x: usize) -> DefIndex {
        assert!(x < (u32::MAX as usize));
        DefIndex(x as u32)
    }

    pub fn from_u32(x: u32) -> DefIndex {
        DefIndex(x)
    }

    pub fn as_usize(&self) -> usize {
        self.0 as usize
    }

    pub fn as_u32(&self) -> u32 {
        self.0
    }
}

/// The crate root is always assigned index 0 by the AST Map code,
/// thanks to `NodeCollector::new`.
pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);

/// A DefId identifies a particular *definition*, by combining a crate
/// index and a def index.
#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
           RustcDecodable, Hash, Copy)]
pub struct DefId {
    pub krate: CrateNum,
    pub index: DefIndex,
}

impl fmt::Debug for DefId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "DefId {{ krate: {:?}, node: {:?}",
                    self.krate, self.index));

        // Unfortunately, there seems to be no way to attempt to print
        // a path for a def-id, so I'll just make a best effort for now
        // and otherwise fallback to just printing the crate/node pair
        if self.is_local() { // (1)
            // (1) side-step fact that not all external things have paths at
            // the moment, such as type parameters
            try!(ty::tls::with_opt(|opt_tcx| {
                if let Some(tcx) = opt_tcx {
                    try!(write!(f, " => {}", tcx.item_path_str(*self)));
                }
                Ok(())
            }));
        }

        write!(f, " }}")
    }
}

impl DefId {
    pub fn local(index: DefIndex) -> DefId {
        DefId { krate: LOCAL_CRATE, index: index }
    }

    pub fn is_local(&self) -> bool {
        self.krate == LOCAL_CRATE
    }
}
<|endoftext|>


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

use hair::cx::Cx;
use rustc::middle::region::CodeExtent;
use rustc::middle::ty::{FnOutput, Ty};
use rustc::mir::repr::*;
use rustc_data_structures::fnv::FnvHashMap;
use rustc_front::hir;

use syntax::ast;
use syntax::codemap::Span;

pub struct Builder<'a, 'tcx: 'a> {
    hir: Cx<'a, 'tcx>,
    cfg: CFG<'tcx>,
    scopes: Vec<scope::Scope<'tcx>>,
    loop_scopes: Vec<scope::LoopScope>,
    unit_temp: Lvalue<'tcx>,
    var_decls: Vec<VarDecl<'tcx>>,
    var_indices: FnvHashMap<ast::NodeId, u32>,
    temp_decls: Vec<TempDecl<'tcx>>,
}

struct CFG<'tcx> {
    basic_blocks: Vec<BasicBlockData<'tcx>>,
}

///////////////////////////////////////////////////////////////////////////
// The `BlockAnd` "monad" packages up the new basic block along with a
// produced value (sometimes just unit, of course). The `unpack!`
// macro (and methods below) makes working with `BlockAnd` much more
// convenient.

#[must_use] // if you don't use one of these results, you're leaving a dangling edge
pub struct BlockAnd<T>(BasicBlock, T);

trait BlockAndExtension {
    fn and<T>(self, v: T) -> BlockAnd<T>;
    fn unit(self) -> BlockAnd<()>;
}

impl BlockAndExtension for BasicBlock {
    fn and<T>(self, v: T) -> BlockAnd<T> {
        BlockAnd(self, v)
    }

    fn unit(self) -> BlockAnd<()> {
        BlockAnd(self, ())
    }
}

/// Update a block pointer and return the value.
/// Use it like `let x = unpack!(block = self.foo(block, foo))`.
macro_rules! unpack {
    ($x:ident = $c:expr) => {
        {
            let BlockAnd(b, v) = $c;
            $x = b;
            v
        }
    };

    ($c:expr) => {
        {
            let BlockAnd(b, ()) = $c;
            b
        }
    };
}

///////////////////////////////////////////////////////////////////////////
// construct() -- the main entry point for building MIR for a function

pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
                          _span: Span,
                          implicit_arguments: Vec<Ty<'tcx>>,
                          explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
                          argument_extent: CodeExtent,
                          return_ty: FnOutput<'tcx>,
                          ast_block: &'tcx hir::Block)
                          -> Mir<'tcx> {
    let cfg = CFG { basic_blocks: vec![] };

    // it's handy to have a temporary of type `()` sometimes, so make
    // one from the start and keep it available
    let temp_decls = vec![TempDecl::<'tcx> { ty: hir.unit_ty() }];
    let unit_temp = Lvalue::Temp(0);

    let mut builder = Builder {
        hir: hir,
        cfg: cfg,
        scopes: vec![],
        loop_scopes: vec![],
        temp_decls: temp_decls,
        var_decls: vec![],
        var_indices: FnvHashMap(),
        unit_temp: unit_temp,
    };

    assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
    assert_eq!(builder.cfg.start_new_block(), END_BLOCK);
    assert_eq!(builder.cfg.start_new_block(), DIVERGE_BLOCK);

    let mut block = START_BLOCK;
    let arg_decls = unpack!(block = builder.args_and_body(block,
                                                          implicit_arguments,
                                                          explicit_arguments,
                                                          argument_extent,
                                                          ast_block));

    builder.cfg.terminate(block, Terminator::Goto { target: END_BLOCK });
    builder.cfg.terminate(END_BLOCK, Terminator::Return);

    Mir {
        basic_blocks: builder.cfg.basic_blocks,
        var_decls: builder.var_decls,
        arg_decls: arg_decls,
        temp_decls: builder.temp_decls,
        return_ty: return_ty,
    }
}

impl<'a,'tcx> Builder<'a,'tcx> {
    fn args_and_body(&mut self,
                     mut block: BasicBlock,
                     implicit_arguments: Vec<Ty<'tcx>>,
                     explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
                     argument_extent: CodeExtent,
                     ast_block: &'tcx hir::Block)
                     -> BlockAnd<Vec<ArgDecl<'tcx>>>
    {
        self.in_scope(argument_extent, block, |this| {
            let arg_decls = {
                let num_implicit_args = implicit_arguments.len();
                let implicit_arg_decls = implicit_arguments.into_iter()
                                                           .map(|ty| ArgDecl { ty: ty });

                // to start, translate the argument patterns and collect the
                // argument types.
                let explicit_arg_decls =
                    explicit_arguments
                    .into_iter()
                    .enumerate()
                    .map(|(index, (ty, pattern))| {
                        let lvalue = Lvalue::Arg((num_implicit_args + index) as u32);
                        let pattern = this.hir.irrefutable_pat(pattern);
                        unpack!(block = this.lvalue_into_pattern(block,
                                                                 argument_extent,
                                                                 pattern,
                                                                 &lvalue));
                        ArgDecl { ty: ty }
                    });

                implicit_arg_decls.chain(explicit_arg_decls).collect()
            };

            // start the first basic block and translate the body
            unpack!(block = this.ast_block(&Lvalue::ReturnPointer, block, ast_block));

            block.and(arg_decls)
        })
    }
}

///////////////////////////////////////////////////////////////////////////
// Builder methods are broken up into modules, depending on what kind
// of thing is being translated. Note that they use the `unpack` macro
// above extensively.

mod block;
mod cfg;
mod expr;
mod into;
mod matches;
mod misc;
mod scope;
mod stmt;
<commit_msg>Refactor MIR building for arguments.<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hair::cx::Cx;
use rustc::middle::region::CodeExtent;
use rustc::middle::ty::{FnOutput, Ty};
use rustc::mir::repr::*;
use rustc_data_structures::fnv::FnvHashMap;
use rustc_front::hir;

use syntax::ast;
use syntax::codemap::Span;

pub struct Builder<'a, 'tcx: 'a> {
    hir: Cx<'a, 'tcx>,
    cfg: CFG<'tcx>,
    scopes: Vec<scope::Scope<'tcx>>,
    loop_scopes: Vec<scope::LoopScope>,
    unit_temp: Lvalue<'tcx>,
    var_decls: Vec<VarDecl<'tcx>>,
    var_indices: FnvHashMap<ast::NodeId, u32>,
    temp_decls: Vec<TempDecl<'tcx>>,
}

struct CFG<'tcx> {
    basic_blocks: Vec<BasicBlockData<'tcx>>,
}

///////////////////////////////////////////////////////////////////////////
// The `BlockAnd` "monad" packages up the new basic block along with a
// produced value (sometimes just unit, of course). The `unpack!`
// macro (and methods below) makes working with `BlockAnd` much more
// convenient.

#[must_use] // if you don't use one of these results, you're leaving a dangling edge
pub struct BlockAnd<T>(BasicBlock, T);

trait BlockAndExtension {
    fn and<T>(self, v: T) -> BlockAnd<T>;
    fn unit(self) -> BlockAnd<()>;
}

impl BlockAndExtension for BasicBlock {
    fn and<T>(self, v: T) -> BlockAnd<T> {
        BlockAnd(self, v)
    }

    fn unit(self) -> BlockAnd<()> {
        BlockAnd(self, ())
    }
}

/// Update a block pointer and return the value.
/// Use it like `let x = unpack!(block = self.foo(block, foo))`.
macro_rules! unpack {
    ($x:ident = $c:expr) => {
        {
            let BlockAnd(b, v) = $c;
            $x = b;
            v
        }
    };

    ($c:expr) => {
        {
            let BlockAnd(b, ()) = $c;
            b
        }
    };
}

///////////////////////////////////////////////////////////////////////////
// construct() -- the main entry point for building MIR for a function

pub fn construct<'a,'tcx>(mut hir: Cx<'a,'tcx>,
                          _span: Span,
                          implicit_arguments: Vec<Ty<'tcx>>,
                          explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
                          argument_extent: CodeExtent,
                          return_ty: FnOutput<'tcx>,
                          ast_block: &'tcx hir::Block)
                          -> Mir<'tcx> {
    let cfg = CFG { basic_blocks: vec![] };

    // it's handy to have a temporary of type `()` sometimes, so make
    // one from the start and keep it available
    let temp_decls = vec![TempDecl::<'tcx> { ty: hir.unit_ty() }];
    let unit_temp = Lvalue::Temp(0);

    let mut builder = Builder {
        hir: hir,
        cfg: cfg,
        scopes: vec![],
        loop_scopes: vec![],
        temp_decls: temp_decls,
        var_decls: vec![],
        var_indices: FnvHashMap(),
        unit_temp: unit_temp,
    };

    assert_eq!(builder.cfg.start_new_block(), START_BLOCK);
    assert_eq!(builder.cfg.start_new_block(), END_BLOCK);
    assert_eq!(builder.cfg.start_new_block(), DIVERGE_BLOCK);

    let mut block = START_BLOCK;
    let arg_decls = unpack!(block = builder.args_and_body(block,
                                                          implicit_arguments,
                                                          explicit_arguments,
                                                          argument_extent,
                                                          ast_block));

    builder.cfg.terminate(block, Terminator::Goto { target: END_BLOCK });
    builder.cfg.terminate(END_BLOCK, Terminator::Return);

    Mir {
        basic_blocks: builder.cfg.basic_blocks,
        var_decls: builder.var_decls,
        arg_decls: arg_decls,
        temp_decls: builder.temp_decls,
        return_ty: return_ty,
    }
}

impl<'a,'tcx> Builder<'a,'tcx> {
    fn args_and_body(&mut self,
                     mut block: BasicBlock,
                     implicit_arguments: Vec<Ty<'tcx>>,
                     explicit_arguments: Vec<(Ty<'tcx>, &'tcx hir::Pat)>,
                     argument_extent: CodeExtent,
                     ast_block: &'tcx hir::Block)
                     -> BlockAnd<Vec<ArgDecl<'tcx>>>
    {
        self.in_scope(argument_extent, block, |this| {
            // to start, translate the argument patterns and collect the argument types.
            let implicits = implicit_arguments.into_iter().map(|ty| (ty, None));
            let explicits = explicit_arguments.into_iter().map(|(ty, pat)| (ty, Some(pat)));
            let arg_decls =
                implicits
                .chain(explicits)
                .enumerate()
                .map(|(index, (ty, pattern))| {
                    if let Some(pattern) = pattern {
                        let lvalue = Lvalue::Arg(index as u32);
                        let pattern = this.hir.irrefutable_pat(pattern);
                        unpack!(block = this.lvalue_into_pattern(block,
                                                                 argument_extent,
                                                                 pattern,
                                                                 &lvalue));
                    }
                    ArgDecl { ty: ty }
                })
                .collect();

            // start the first basic block and translate the body
            unpack!(block = this.ast_block(&Lvalue::ReturnPointer, block, ast_block));

            block.and(arg_decls)
        })
    }
}

///////////////////////////////////////////////////////////////////////////
// Builder methods are broken up into modules, depending on what kind
// of thing is being translated. Note that they use the `unpack` macro
// above extensively.

mod block;
mod cfg;
mod expr;
mod into;
mod matches;
mod misc;
mod scope;
mod stmt;
<|endoftext|>


<commit_before>use std::path::PathBuf;

use rustc_data_structures::fx::FxHashMap;

use crate::externalfiles::ExternalHtml;
use crate::html::escape::Escape;
use crate::html::format::{Buffer, Print};
use crate::html::render::{ensure_trailing_slash, StylePath};

#[derive(Clone)]
crate struct Layout {
    crate logo: String,
    crate favicon: String,
    crate external_html: ExternalHtml,
    crate default_settings: FxHashMap<String, String>,
    crate krate: String,
    /// The given user css file which allow to customize the generated
    /// documentation theme.
    crate css_file_extension: Option<PathBuf>,
    /// If false, the `select` element to have search filtering by crates on rendered docs
    /// won't be generated.
    crate generate_search_filter: bool,
}

crate struct Page<'a> {
    crate title: &'a str,
    crate css_class: &'a str,
    crate root_path: &'a str,
    crate static_root_path: Option<&'a str>,
    crate description: &'a str,
    crate keywords: &'a str,
    crate resource_suffix: &'a str,
    crate extra_scripts: &'a [&'a str],
    crate static_extra_scripts: &'a [&'a str],
}

crate fn render<T: Print, S: Print>(
    layout: &Layout,
    page: &Page<'_>,
    sidebar: S,
    t: T,
    style_files: &[StylePath],
) -> String {
    let static_root_path = page.static_root_path.unwrap_or(page.root_path);
    format!(
        "<!DOCTYPE html>\
\
\
    <meta charset=\"utf-8\">\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
    <meta name=\"generator\" content=\"rustdoc\">\
    <meta name=\"description\" content=\"{description}\">\
    <meta name=\"keywords\" content=\"{keywords}\">\
    <title>{title}</title>\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
          id=\"mainThemeStyle\">\
    {style_files}\
    \
    \
    \
    <link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\">\
    {css_extension}\
    {favicon}\
    {in_header}\
    \
\
\
    \
    {before_content}\
    \

☰
\
        {logo}\
        {sidebar}\
    \

\
        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\">\
            \
        </button>\

\

\
    \
        <form class=\"search-form\">\

\

{filter_crates}\
                    <input class=\"search-input\" name=\"search\" \
                           disabled \
                           autocomplete=\"off\" \
                           spellcheck=\"false\" \
                           placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
                           type=\"search\">\

\
                <button type=\"button\" class=\"help-button\">?</button>
                \
                    \
                \

\
        </form>\
    \

{content}
\

\

\
    {after_content}\

    \
    {extra_scripts}\
\
",
        css_extension = if layout.css_file_extension.is_some() {
            format!(
                "<link rel=\"stylesheet\" \
                       type=\"text/css\" \
                       href=\"{static_root_path}theme{suffix}.css\">",
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            String::new()
        },
        content = Buffer::html().to_display(t),
        static_root_path = static_root_path,
        root_path = page.root_path,
        css_class = page.css_class,
        logo = {
            if layout.logo.is_empty() {
                format!(
                    "\

\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    static_root_path = static_root_path,
                    suffix = page.resource_suffix
                )
            } else {
                format!(
                    "\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    logo = layout.logo
                )
            }
        },
        title = page.title,
        description = page.description,
        keywords = page.keywords,
        favicon = if layout.favicon.is_empty() {
            format!(
                r##"<link rel="icon" type="image/svg+xml" href="{static_root_path}favicon{suffix}.svg">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-16x16{suffix}.png">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-32x32{suffix}.png">"##,
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
        },
        in_header = layout.external_html.in_header,
        before_content = layout.external_html.before_content,
        after_content = layout.external_html.after_content,
        sidebar = Buffer::html().to_display(sidebar),
        krate = layout.krate,
        default_settings = layout
            .default_settings
            .iter()
            .map(|(k, v)| format!(r#" data-{}="{}""#, k.replace('-', "_"), Escape(v)))
            .collect::<String>(),
        style_files = style_files
            .iter()
            .filter_map(|t| {
                if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
            })
            .filter_map(|t| {
                if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }
            })
            .map(|t| format!(
                r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
                Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
                if t.1 { "disabled" } else { "" },
                if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
            ))
            .collect::<String>(),
        suffix = page.resource_suffix,
        extra_scripts = page
            .static_extra_scripts
            .iter()
            .map(|e| {
                format!(
                    "",
                    static_root_path = static_root_path,
                    extra_script = e
                )
            })
            .chain(page.extra_scripts.iter().map(|e| {
                format!(
                    "",
                    root_path = page.root_path,
                    extra_script = e
                )
            }))
            .collect::<String>(),
        filter_crates = if layout.generate_search_filter {
            "<select id=\"crate-search\">\
                 <option value=\"All crates\">All crates</option>\
             </select>"
        } else {
            ""
        },
    )
}

crate fn redirect(url: &str) -> String {
    //

"##,
        url = url,
    )
}
<commit_msg>Remove unused footer section<commit_after>use std::path::PathBuf;

use rustc_data_structures::fx::FxHashMap;

use crate::externalfiles::ExternalHtml;
use crate::html::escape::Escape;
use crate::html::format::{Buffer, Print};
use crate::html::render::{ensure_trailing_slash, StylePath};

#[derive(Clone)]
crate struct Layout {
    crate logo: String,
    crate favicon: String,
    crate external_html: ExternalHtml,
    crate default_settings: FxHashMap<String, String>,
    crate krate: String,
    /// The given user css file which allow to customize the generated
    /// documentation theme.
    crate css_file_extension: Option<PathBuf>,
    /// If false, the `select` element to have search filtering by crates on rendered docs
    /// won't be generated.
    crate generate_search_filter: bool,
}

crate struct Page<'a> {
    crate title: &'a str,
    crate css_class: &'a str,
    crate root_path: &'a str,
    crate static_root_path: Option<&'a str>,
    crate description: &'a str,
    crate keywords: &'a str,
    crate resource_suffix: &'a str,
    crate extra_scripts: &'a [&'a str],
    crate static_extra_scripts: &'a [&'a str],
}

crate fn render<T: Print, S: Print>(
    layout: &Layout,
    page: &Page<'_>,
    sidebar: S,
    t: T,
    style_files: &[StylePath],
) -> String {
    let static_root_path = page.static_root_path.unwrap_or(page.root_path);
    format!(
        "<!DOCTYPE html>\
\
\
    <meta charset=\"utf-8\">\
    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
    <meta name=\"generator\" content=\"rustdoc\">\
    <meta name=\"description\" content=\"{description}\">\
    <meta name=\"keywords\" content=\"{keywords}\">\
    <title>{title}</title>\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}normalize{suffix}.css\">\
    <link rel=\"stylesheet\" type=\"text/css\" href=\"{static_root_path}rustdoc{suffix}.css\" \
          id=\"mainThemeStyle\">\
    {style_files}\
    \
    \
    \
    <link rel=\"stylesheet\" href=\"{static_root_path}noscript{suffix}.css\">\
    {css_extension}\
    {favicon}\
    {in_header}\
    \
\
\
    \
    {before_content}\
    \

☰
\
        {logo}\
        {sidebar}\
    \

\
        <button id=\"theme-picker\" aria-label=\"Pick another theme!\" aria-haspopup=\"menu\">\
            \
        </button>\

\

\
    \
        <form class=\"search-form\">\

\

{filter_crates}\
                    <input class=\"search-input\" name=\"search\" \
                           disabled \
                           autocomplete=\"off\" \
                           spellcheck=\"false\" \
                           placeholder=\"Click or press ‘S’ to search, ‘?’ for more options…\" \
                           type=\"search\">\

\
                <button type=\"button\" class=\"help-button\">?</button>
                \
                    \
                \

\
        </form>\
    \

{content}
\

\
    {after_content}\

    \
    {extra_scripts}\
\
",
        css_extension = if layout.css_file_extension.is_some() {
            format!(
                "<link rel=\"stylesheet\" \
                       type=\"text/css\" \
                       href=\"{static_root_path}theme{suffix}.css\">",
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            String::new()
        },
        content = Buffer::html().to_display(t),
        static_root_path = static_root_path,
        root_path = page.root_path,
        css_class = page.css_class,
        logo = {
            if layout.logo.is_empty() {
                format!(
                    "\

\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    static_root_path = static_root_path,
                    suffix = page.resource_suffix
                )
            } else {
                format!(
                    "\

",
                    root = page.root_path,
                    path = ensure_trailing_slash(&layout.krate),
                    logo = layout.logo
                )
            }
        },
        title = page.title,
        description = page.description,
        keywords = page.keywords,
        favicon = if layout.favicon.is_empty() {
            format!(
                r##"<link rel="icon" type="image/svg+xml" href="{static_root_path}favicon{suffix}.svg">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-16x16{suffix}.png">
<link rel="alternate icon" type="image/png" href="{static_root_path}favicon-32x32{suffix}.png">"##,
                static_root_path = static_root_path,
                suffix = page.resource_suffix
            )
        } else {
            format!(r#"<link rel="shortcut icon" href="{}">"#, layout.favicon)
        },
        in_header = layout.external_html.in_header,
        before_content = layout.external_html.before_content,
        after_content = layout.external_html.after_content,
        sidebar = Buffer::html().to_display(sidebar),
        krate = layout.krate,
        default_settings = layout
            .default_settings
            .iter()
            .map(|(k, v)| format!(r#" data-{}="{}""#, k.replace('-', "_"), Escape(v)))
            .collect::<String>(),
        style_files = style_files
            .iter()
            .filter_map(|t| {
                if let Some(stem) = t.path.file_stem() { Some((stem, t.disabled)) } else { None }
            })
            .filter_map(|t| {
                if let Some(path) = t.0.to_str() { Some((path, t.1)) } else { None }
            })
            .map(|t| format!(
                r#"<link rel="stylesheet" type="text/css" href="{}.css" {} {}>"#,
                Escape(&format!("{}{}{}", static_root_path, t.0, page.resource_suffix)),
                if t.1 { "disabled" } else { "" },
                if t.0 == "light" { "id=\"themeStyle\"" } else { "" }
            ))
            .collect::<String>(),
        suffix = page.resource_suffix,
        extra_scripts = page
            .static_extra_scripts
            .iter()
            .map(|e| {
                format!(
                    "",
                    static_root_path = static_root_path,
                    extra_script = e
                )
            })
            .chain(page.extra_scripts.iter().map(|e| {
                format!(
                    "",
                    root_path = page.root_path,
                    extra_script = e
                )
            }))
            .collect::<String>(),
        filter_crates = if layout.generate_search_filter {
            "<select id=\"crate-search\">\
                 <option value=\"All crates\">All crates</option>\
             </select>"
        } else {
            ""
        },
    )
}

crate fn redirect(url: &str) -> String {
    //

"##,
        url = url,
    )
}
<|endoftext|>


<commit_before>use super::GbaMemory;
use arm::{AccessType, Waitstates};

impl GbaMemory {
    pub(super) fn load32_sram(&mut self, _address: u32, _access: AccessType) -> (u32, Waitstates) {
        todo!("load32_sram")
    }

    pub(super) fn load16_sram(&mut self, _address: u32, _access: AccessType) -> (u16, Waitstates) {
        todo!("load16_sram")
    }

    pub(super) fn load8_sram(&mut self, _address: u32, _access: AccessType) -> (u8, Waitstates) {
        todo!("load8_sram")
    }

    pub(super) fn store32_sram(
        &mut self,
        _address: u32,
        _value: u32,
        _access: AccessType,
    ) -> Waitstates {
        todo!("store32_sram")
    }

    pub(super) fn store16_sram(
        &mut self,
        _address: u32,
        _value: u16,
        _access: AccessType,
    ) -> Waitstates {
        todo!("store16_sram")
    }

    pub(super) fn store8_sram(
        &mut self,
        _address: u32,
        _value: u8,
        _access: AccessType,
    ) -> Waitstates {
        todo!("store8_sram")
    }
}
<commit_msg>Implement stub for flash memory device/manufacturer.<commit_after>use super::GbaMemory;
use arm::{AccessType, Waitstates};

impl GbaMemory {
    pub(super) fn load32_sram(&mut self, address: u32, access: AccessType) -> (u32, Waitstates) {
        let (value, waitstates) = self.load8_sram(address, access);
        (value as u32 * 0x01010101, waitstates) // return repeated byte
    }

    pub(super) fn load16_sram(&mut self, address: u32, access: AccessType) -> (u16, Waitstates) {
        let (value, waitstates) = self.load8_sram(address, access);
        (value as u16 * 0x0101, waitstates) // return repeated byte
    }

    pub(super) fn load8_sram(&mut self, address: u32, _access: AccessType) -> (u8, Waitstates) {
        // FIXME implement real Flash IDs

        // These are some default values that Pokemon works with
        const MANUFACTURER: u8 = 0xC2;
        const DEVICE: u8 = 0x09;

        let value = match address {
            0xE000000 => MANUFACTURER,
            0xE000001 => DEVICE,
            _ => 0,
        };
        log::warn!("attempted to load from  unimplemented SRAM; address=0x{address:08X}; value=0x{value:02X}");
        (value, self.sram_waitstates)
    }

    pub(super) fn store32_sram(
        &mut self,
        address: u32,
        value: u32,
        _access: AccessType,
    ) -> Waitstates {
        log::warn!("attempted to store to unimplemented SRAM; address=0x{address:08X}; value=0x{value:08X}",);
        self.sram_waitstates
    }

    pub(super) fn store16_sram(
        &mut self,
        address: u32,
        value: u16,
        _access: AccessType,
    ) -> Waitstates {
        log::warn!("attempted to store to unimplemented SRAM; address=0x{address:08X}; value=0x{value:04X}",);
        self.sram_waitstates
    }

    pub(super) fn store8_sram(
        &mut self,
        address: u32,
        value: u8,
        _access: AccessType,
    ) -> Waitstates {
        log::warn!("attempted to store to unimplemented SRAM; address=0x{address:08X}; value=0x{value:02X}",);
        self.sram_waitstates
    }
}
<|endoftext|>


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

//! Unix-specific extensions to general I/O primitives

#![stable(feature = "rust1", since = "1.0.0")]

use fs;
use net;
use os::raw;
use sys;
use sys_common::{self, AsInner, FromInner, IntoInner};

/// Raw file descriptors.
#[stable(feature = "rust1", since = "1.0.0")]
pub type RawFd = raw::c_int;

/// A trait to extract the raw unix file descriptor from an underlying
/// object.
///
/// This is only available on unix platforms and must be imported in order
/// to call the method. Windows platforms have a corresponding `AsRawHandle`
/// and `AsRawSocket` set of traits.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRawFd {
    /// Extracts the raw file descriptor.
    ///
    /// This method does **not** pass ownership of the raw file descriptor
    /// to the caller. The descriptor is only guaranteed to be valid while
    /// the original object has not yet been destroyed.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_raw_fd(&self) -> RawFd;
}

/// A trait to express the ability to construct an object from a raw file
/// descriptor.
#[stable(feature = "from_raw_os", since = "1.1.0")]
pub trait FromRawFd {
    /// Constructs a new instance of `Self` from the given raw file
    /// descriptor.
    ///
    /// This function **consumes ownership** of the specified file
    /// descriptor. The returned object will take responsibility for closing
    /// it when the object goes out of scope.
    ///
    /// This function is also unsafe as the primitives currently returned
    /// have the contract that they are the sole owner of the file
    /// descriptor they are wrapping. Usage of this function could
    /// accidentally allow violating this contract which can cause memory
    /// unsafety in code that relies on it being true.
    #[stable(feature = "from_raw_os", since = "1.1.0")]
    unsafe fn from_raw_fd(fd: RawFd) -> Self;
}

/// A trait to express the ability to consume an object and acquire ownership of
/// its raw file descriptor.
#[stable(feature = "into_raw_os", since = "1.4.0")]
pub trait IntoRawFd {
    /// Consumes this object, returning the raw underlying file descriptor.
    ///
    /// This function **transfers ownership** of the underlying file descriptor
    /// to the caller. Callers are then the unique owners of the file descriptor
    /// and must close the descriptor once it's no longer needed.
    #[stable(feature = "into_raw_os", since = "1.4.0")]
    fn into_raw_fd(self) -> RawFd;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for fs::File {
    fn as_raw_fd(&self) -> RawFd {
        self.as_inner().fd().raw()
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for fs::File {
    unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
        fs::File::from_inner(sys::fs::File::from_inner(fd))
    }
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for fs::File {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_fd().into_raw()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::TcpStream {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::TcpListener {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::UdpSocket {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}

#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::TcpStream {
    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
        let socket = sys::net::Socket::from_inner(fd);
        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket))
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::TcpListener {
    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
        let socket = sys::net::Socket::from_inner(fd);
        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket))
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::UdpSocket {
    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
        let socket = sys::net::Socket::from_inner(fd);
        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::TcpStream {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::TcpListener {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::UdpSocket {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
<commit_msg>Rollup merge of #40842 - Mic92:RawFd, r=aturon<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Unix-specific extensions to general I/O primitives

#![stable(feature = "rust1", since = "1.0.0")]

use fs;
use net;
use os::raw;
use sys;
use sys_common::{self, AsInner, FromInner, IntoInner};

/// Raw file descriptors.
#[stable(feature = "rust1", since = "1.0.0")]
pub type RawFd = raw::c_int;

/// A trait to extract the raw unix file descriptor from an underlying
/// object.
///
/// This is only available on unix platforms and must be imported in order
/// to call the method. Windows platforms have a corresponding `AsRawHandle`
/// and `AsRawSocket` set of traits.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsRawFd {
    /// Extracts the raw file descriptor.
    ///
    /// This method does **not** pass ownership of the raw file descriptor
    /// to the caller. The descriptor is only guaranteed to be valid while
    /// the original object has not yet been destroyed.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn as_raw_fd(&self) -> RawFd;
}

/// A trait to express the ability to construct an object from a raw file
/// descriptor.
#[stable(feature = "from_raw_os", since = "1.1.0")]
pub trait FromRawFd {
    /// Constructs a new instance of `Self` from the given raw file
    /// descriptor.
    ///
    /// This function **consumes ownership** of the specified file
    /// descriptor. The returned object will take responsibility for closing
    /// it when the object goes out of scope.
    ///
    /// This function is also unsafe as the primitives currently returned
    /// have the contract that they are the sole owner of the file
    /// descriptor they are wrapping. Usage of this function could
    /// accidentally allow violating this contract which can cause memory
    /// unsafety in code that relies on it being true.
    #[stable(feature = "from_raw_os", since = "1.1.0")]
    unsafe fn from_raw_fd(fd: RawFd) -> Self;
}

/// A trait to express the ability to consume an object and acquire ownership of
/// its raw file descriptor.
#[stable(feature = "into_raw_os", since = "1.4.0")]
pub trait IntoRawFd {
    /// Consumes this object, returning the raw underlying file descriptor.
    ///
    /// This function **transfers ownership** of the underlying file descriptor
    /// to the caller. Callers are then the unique owners of the file descriptor
    /// and must close the descriptor once it's no longer needed.
    #[stable(feature = "into_raw_os", since = "1.4.0")]
    fn into_raw_fd(self) -> RawFd;
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for RawFd {
    fn as_raw_fd(&self) -> RawFd {
        *self
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for fs::File {
    fn as_raw_fd(&self) -> RawFd {
        self.as_inner().fd().raw()
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for fs::File {
    unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
        fs::File::from_inner(sys::fs::File::from_inner(fd))
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for RawFd {
    fn into_raw_fd(self) -> RawFd {
        self
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for fs::File {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_fd().into_raw()
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::TcpStream {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::TcpListener {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRawFd for net::UdpSocket {
    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
}

#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::TcpStream {
    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
        let socket = sys::net::Socket::from_inner(fd);
        net::TcpStream::from_inner(sys_common::net::TcpStream::from_inner(socket))
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::TcpListener {
    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
        let socket = sys::net::Socket::from_inner(fd);
        net::TcpListener::from_inner(sys_common::net::TcpListener::from_inner(socket))
    }
}
#[stable(feature = "from_raw_os", since = "1.1.0")]
impl FromRawFd for net::UdpSocket {
    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
        let socket = sys::net::Socket::from_inner(fd);
        net::UdpSocket::from_inner(sys_common::net::UdpSocket::from_inner(socket))
    }
}

#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::TcpStream {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::TcpListener {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
#[stable(feature = "into_raw_os", since = "1.4.0")]
impl IntoRawFd for net::UdpSocket {
    fn into_raw_fd(self) -> RawFd {
        self.into_inner().into_socket().into_inner()
    }
}
<|endoftext|>