<commit_before>//! Provides polyphonic voice arrays.

use std::collections::{VecDeque, HashMap};
use std::slice::{Iter, IterMut};
use std::vec::Vec;

/// A manager for a polyphonic set of voices.
pub struct VoiceArray<T> {
    /// All the voices are contained in the voices vector
    voices: Vec<T>,
    /// Maps MIDI note numbers to currently triggered voice indices
    note_to_voice: HashMap<u8, usize>,
    /// Maps voice indices to MIDI note numbers
    voice_to_note: HashMap<usize, u8>,
    /// Places the most recently mapped voices at the end
    voice_queue: VecDeque<usize>
}

impl<T> VoiceArray<T> {
    /// Creates a new VoiceArray from the provifed vector of voices.
    pub fn new(voices: Vec<T>) -> VoiceArray<T> {
        let num_voices = voices.len();
        let mut voice_queue = VecDeque::new();
        for i in (0 .. num_voices) {
            voice_queue.push_back(i);
        }

        VoiceArray {
            voices: voices,
            note_to_voice: HashMap::new(),
            voice_to_note: HashMap::new(),
            voice_queue: voice_queue
        }
    }

    /// Get an iterator over the voice objects
    pub fn iter(&self) -> Iter<T> {
        self.voices.iter()
    }

    /// Get a mutable iterator over the voice objects
    pub fn iter_mut(&mut self) -> IterMut<T> {
        self.voices.iter_mut()
    }

    /// Selects a new voice, marks it as used, and loans it out
    pub fn note_on(&mut self, note: u8) -> &mut T {
        let i = match self.note_to_voice.remove(&note) {
            Some(i) => {
                // This note is already being played, so retrigger it and move
                // it to the back of the queue
                self.remove_from_queue(i);
                i
            },
            None => {
                // This note is not being played, so get the next voice
                let i = self.voice_queue.pop_front().unwrap();

                // Remove the mapping between the voice and its old note
                match self.voice_to_note.remove(&i) {
                    Some(n) => { self.note_to_voice.remove(&n); },
                    None => ()
                }

                // Map this voice to its new note
                self.note_to_voice.insert(note, i);
                self.voice_to_note.insert(i, note);
                i
            }
        };
        // Finally, push the voice to the back of the queue and handle the event
        self.voice_queue.push_back(i);
        &mut self.voices[i]
    }

    /// Find the voice playing this note and mark it as done
    pub fn note_off(&mut self, note: u8) -> Option<&mut T> {
        match self.note_to_voice.remove(&note) {
            Some(i) => {
                self.remove_from_queue(i);
                self.voice_to_note.remove(&i);
                self.voice_queue.push_front(i);
                Some(&mut self.voices[i])
            },
            None => None
        }
    }

    // Finds a voice in the queue and removes it
    fn remove_from_queue(&mut self, voice: usize) {
        for i in (0 .. self.voice_queue.len()) {
            if *self.voice_queue.get(i).unwrap() == voice {
                self.voice_queue.remove(i);
                break;
            }
        }
    }
}
<commit_msg>Bug fixes and tests for voice selection<commit_after>//! Provides polyphonic voice arrays.

use std::collections::{VecDeque, HashMap};
use std::slice::{Iter, IterMut};
use std::vec::Vec;

/// A manager for a polyphonic set of voices.
pub struct VoiceArray<T> {
    /// All the voices are contained in the voices vector
    voices: Vec<T>,
    /// Maps MIDI note numbers to currently triggered voice indices
    note_to_voice: HashMap<u8, usize>,
    /// Places the most recently mapped voices at the end, and track the note
    /// they are currently playing
    held_voices: VecDeque<(usize, u8)>,
    /// Tracks free voices
    free_voices: VecDeque<usize>,
}

impl<T> VoiceArray<T> {
    /// Creates a new VoiceArray from the provifed vector of voices.
    pub fn new(voices: Vec<T>) -> VoiceArray<T> {
        let num_voices = voices.len();
        let mut free_voices = VecDeque::new();
        for i in (0 .. num_voices) {
            free_voices.push_back(i);
        }

        VoiceArray {
            voices: voices,
            note_to_voice: HashMap::new(),
            held_voices: VecDeque::new(),
            free_voices: free_voices,
        }
    }

    /// Get an iterator over the voice objects
    pub fn iter(&self) -> Iter<T> {
        self.voices.iter()
    }

    /// Get a mutable iterator over the voice objects
    pub fn iter_mut(&mut self) -> IterMut<T> {
        self.voices.iter_mut()
    }

    /// Selects a new voice, marks it as used, and loans it out
    pub fn note_on(&mut self, note: u8) -> &mut T {
        let i = match self.note_to_voice.get(&note) {
            Some(&i) => {
                // This note is already being played, so retrigger it and move
                // it to the back of the queue
                self.remove_from_queue(i);
                i
            },
            None => {
                let i = match self.free_voices.pop_front() {
                    // If there is a free voice, use the oldest one
                    Some(i) => i,
                    // Otherwise, use the oldest playing voice
                    None => {
                        let (i, n) = self.held_voices.pop_front().unwrap();
                        self.note_to_voice.remove(&n);
                        i
                    }
                };
                self.note_to_voice.insert(note, i);
                i
            }
        };
        // Finally, push the voice to the back of the queue and handle the event
        self.held_voices.push_back((i,note));
        &mut self.voices[i]
    }

    /// Find the voice playing this note and mark it as done
    pub fn note_off(&mut self, note: u8) -> Option<&mut T> {
        match self.note_to_voice.remove(&note) {
            Some(i) => {
                self.remove_from_queue(i);
                self.free_voices.push_back(i);
                Some(&mut self.voices[i])
            },
            None => None
        }
    }

    // Finds a voice in the queue and removes it
    fn remove_from_queue(&mut self, voice: usize) {
        for i in (0 .. self.held_voices.len()) {
            let (j, _) = self.held_voices[i];
            if j == voice {
                self.held_voices.remove(i);
                break;
            }
        }
    }
}

#[cfg(test)]
mod test {
    /// Verify that asking for a new note selects free voices first
    #[test]
    fn test_free_voice() {
        use super::VoiceArray;
        let mut voices1 = VoiceArray::new(vec![1,2]);
        let v1 = voices1.note_on(1).clone();
        let _ = voices1.note_on(2).clone();
        voices1.note_off(1);
        let v3 = voices1.note_on(3).clone();
        assert_eq!(v1, v3);

        let mut voices2 = VoiceArray::new(vec![1,2]);
        let _ = voices2.note_on(1).clone();
        let v2 = voices2.note_on(2).clone();
        voices2.note_off(2);
        let v3 = voices2.note_on(3).clone();
        assert_eq!(v2, v3);
    }

    /// Verify that asking for a held note always returns that held note
    #[test]
    fn test_key_repeat() {
        use super::VoiceArray;
        let mut voices = VoiceArray::new(vec![1,2]);
        let v1 = voices.note_on(1).clone();
        let v2 = voices.note_on(2).clone();
        let v3 = voices.note_on(1).clone();
        let v4 = voices.note_on(1).clone();
        let v5 = voices.note_on(2).clone();
        let v6 = voices.note_on(2).clone();
        assert!(v1 != v2);
        assert_eq!(v1, v3);
        assert_eq!(v1, v4);
        assert_eq!(v2, v5);
        assert_eq!(v2, v6);
    }

    /// Verify that the oldest free voice is always selected
    #[test]
    fn test_oldest_free() {
        use super::VoiceArray;
        let mut voices = VoiceArray::new(vec![1,2]);
        let v1 = voices.note_on(1).clone();
        let v2 = voices.note_on(2).clone();

        voices.note_off(1);
        voices.note_off(2);
        let v3 = voices.note_on(3).clone();
        assert_eq!(v3, v1);

        voices.note_off(3);
        let v4 = voices.note_on(4).clone();
        assert_eq!(v4, v2);
    }

    /// Verify that note pruning always selects the oldest held voice
    #[test]
    fn test_oldest_held() {
        use super::VoiceArray;
        let mut voices = VoiceArray::new(vec![1,2,3]);
        let v1 = voices.note_on(1).clone();
        let v2 = voices.note_on(2).clone();
        let v3 = voices.note_on(3).clone();
        let v4 = voices.note_on(4).clone();
        let v5 = voices.note_on(5).clone();
        let v6 = voices.note_on(6).clone();
        assert_eq!(v1, v4);
        assert_eq!(v2, v5);
        assert_eq!(v3, v6);
    }
}
<|endoftext|>


<commit_before>//! rustdoc handler

use super::pool::Pool;
use super::file::File;
use super::{latest_version, redirect_base};
use super::crate_details::CrateDetails;
use iron::prelude::*;
use iron::{status, Url};
use iron::modifiers::Redirect;
use router::Router;
use super::{match_version, MatchVersion};
use super::error::Nope;
use super::page::Page;
use rustc_serialize::json::{Json, ToJson};
use std::collections::BTreeMap;
use iron::headers::{Expires, HttpDate, CacheControl, CacheDirective};
use time;
use iron::Handler;
use utils;

#[derive(Debug)]
struct RustdocPage {
    pub head: String,
    pub body: String,
    pub body_class: String,
    pub name: String,
    pub full: String,
    pub version: String,
    pub description: Option<String>,
    pub crate_details: Option<CrateDetails>,
}

impl Default for RustdocPage {
    fn default() -> RustdocPage {
        RustdocPage {
            head: String::new(),
            body: String::new(),
            body_class: String::new(),
            name: String::new(),
            full: String::new(),
            version: String::new(),
            description: None,
            crate_details: None,
        }
    }
}

impl ToJson for RustdocPage {
    fn to_json(&self) -> Json {
        let mut m: BTreeMap<String, Json> = BTreeMap::new();
        m.insert("rustdoc_head".to_string(), self.head.to_json());
        m.insert("rustdoc_body".to_string(), self.body.to_json());
        m.insert("rustdoc_body_class".to_string(), self.body_class.to_json());
        m.insert("rustdoc_full".to_string(), self.full.to_json());
        m.insert("rustdoc_status".to_string(), true.to_json());
        m.insert("name".to_string(), self.name.to_json());
        m.insert("version".to_string(), self.version.to_json());
        m.insert("description".to_string(), self.description.to_json());
        m.insert("crate_details".to_string(), self.crate_details.to_json());
        m.to_json()
    }
}

pub struct RustLangRedirector {
    url: Url,
}

impl RustLangRedirector {
    pub fn new(target: &'static str) -> Self {
        let url = url::Url::parse("https://doc.rust-lang.org/stable/")
            .expect("failed to parse rust-lang.org base URL")
            .join(target)
            .expect("failed to append crate name to rust-lang.org base URL");
        let url = Url::from_generic_url(url)
            .expect("failed to convert url::Url to iron::Url");
        Self { url }
    }
}

impl iron::Handler for RustLangRedirector {
    fn handle(&self, _req: &mut Request) -> IronResult<Response> {
        Ok(Response::with((status::Found, Redirect(self.url.clone()))))
    }
}

/// Handler called for `/:crate` and `/:crate/:version` URLs. Automatically redirects to the docs
/// or crate details page based on whether the given crate version was successfully built.
pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {

    fn redirect_to_doc(req: &Request,
                       name: &str,
                       vers: &str,
                       target_name: &str)
                       -> IronResult<Response> {
        let url = ctry!(Url::parse(&format!("{}/{}/{}/{}/",
                                            redirect_base(req),
                                            name,
                                            vers,
                                            target_name)[..]));
        let mut resp = Response::with((status::Found, Redirect(url)));
        resp.headers.set(Expires(HttpDate(time::now())));

        Ok(resp)
    }

    fn redirect_to_crate(req: &Request,
                         name: &str,
                         vers: &str)
                         -> IronResult<Response> {
        let url = ctry!(Url::parse(&format!("{}/crate/{}/{}",
                                            redirect_base(req),
                                            name,
                                            vers)[..]));

        let mut resp = Response::with((status::Found, Redirect(url)));
        resp.headers.set(Expires(HttpDate(time::now())));

        Ok(resp)
    }

    // this unwrap is safe because iron urls are always able to use `path_segments`
    // i'm using this instead of `req.url.path()` to avoid allocating the Vec, and also to avoid
    // keeping the borrow alive into the return statement
    if req.url.as_ref().path_segments().unwrap().last().map_or(false, |s| s.ends_with(".js")) {
        // javascript files should be handled by the file server instead of erroneously
        // redirecting to the crate root page
        if req.url.as_ref().path_segments().unwrap().count() > 2 {
            // this URL is actually from a crate-internal path, serve it there instead
            return rustdoc_html_server_handler(req);
        } else {
            let path = req.url.path();
            let path = path.join("/");
            let conn = extension!(req, Pool);
            match File::from_path(&conn, &path) {
                Some(f) => return Ok(f.serve()),
                None => return Err(IronError::new(Nope::ResourceNotFound, status::NotFound)),
            }
        }
    } else if req.url.as_ref().path_segments().unwrap().last().map_or(false, |s| s.ends_with(".ico")) {
        // route .ico files into their dedicated handler so that docs.rs's favicon is always
        // displayed
        return super::ico_handler(req);
    }

    let router = extension!(req, Router);
    // this handler should never called without crate pattern
    let crate_name = cexpect!(router.find("crate"));
    let req_version = router.find("version");

    let conn = extension!(req, Pool);

    // it doesn't matter if the version that was given was exact or not, since we're redirecting
    // anyway
    let version = match match_version(&conn, &crate_name, req_version).into_option() {
        Some(v) => v,
        None => return Err(IronError::new(Nope::CrateNotFound, status::NotFound)),
    };

    // get target name and whether it has docs
    // FIXME: This is a bit inefficient but allowing us to use less code in general
    let (target_name, has_docs): (String, bool) = {
        let rows = ctry!(conn.query("SELECT target_name, rustdoc_status
                                     FROM releases
                                     INNER JOIN crates ON crates.id = releases.crate_id
                                     WHERE crates.name = $1 AND releases.version = $2",
                                    &[&crate_name, &version]));

        (rows.get(0).get(0), rows.get(0).get(1))
    };

    if has_docs {
        redirect_to_doc(req, &crate_name, &version, &target_name)
    } else {
        redirect_to_crate(req, &crate_name, &version)
    }
}

/// Serves documentation generated by rustdoc.
///
/// This includes all HTML files for an individual crate, as well as the `search-index.js`, which is
/// also crate-specific.
pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult<Response> {

    let router = extension!(req, Router);
    let name = router.find("crate").unwrap_or("").to_string();
    let url_version = router.find("version");
    let version; // pre-declaring it to enforce drop order relative to `req_path`
    let conn = extension!(req, Pool);

    let mut req_path = req.url.path();

    // remove name and version from path
    for _ in 0..2 {
        req_path.remove(0);
    }

    version = match match_version(&conn, &name, url_version) {
        MatchVersion::Exact(v) => v,
        MatchVersion::Semver(v) => {
            // to prevent cloudfront caching the wrong artifacts on URLs with loose semver
            // versions, redirect the browser to the returned version instead of loading it
            // immediately
            let url = ctry!(Url::parse(&format!("{}/{}/{}/{}",
                                                redirect_base(req),
                                                name,
                                                v,
                                                req_path.join("/"))[..]));
            return Ok(super::redirect(url));
        }
        MatchVersion::None => return Err(IronError::new(Nope::ResourceNotFound, status::NotFound)),
    };

    // docs have "rustdoc" prefix in database
    req_path.insert(0, "rustdoc");

    // add crate name and version
    req_path.insert(1, &name);
    req_path.insert(2, &version);

    let path = {
        let mut path = req_path.join("/");
        if path.ends_with('/') {
            req_path.pop(); // get rid of empty string
            path.push_str("index.html");
            req_path.push("index.html");
        }
        path
    };

    let file = match File::from_path(&conn, &path) {
        Some(f) => f,
        None => return Err(IronError::new(Nope::ResourceNotFound, status::NotFound)),
    };

    // serve file directly if it's not html
    if !path.ends_with(".html") {
        return Ok(file.serve());
    }

    let mut content = RustdocPage::default();

    let file_content = ctry!(String::from_utf8(file.0.content));

    let (head, body, mut body_class) = ctry!(utils::extract_head_and_body(&file_content));
    content.head = head;
    content.body = body;

    if body_class.is_empty() {
        body_class = "rustdoc container-rustdoc".to_string();
    } else {
        // rustdoc adds its own "rustdoc" class to the body
        body_class.push_str(" container-rustdoc");
    }
    content.body_class = body_class;

    content.full = file_content;
    let crate_details = cexpect!(CrateDetails::new(&conn, &name, &version));
    let latest_version = latest_version(&crate_details.versions, &version);

    content.crate_details = Some(crate_details);

    let (path, version) = if let Some(version) = latest_version {
        req_path[2] = &version;
        let path = if File::from_path(&conn, &req_path.join("/")).is_some() {
            req_path[3..].join("/") // NOTE: this adds 'index.html' if it wasn't there before
        } else { // this page doesn't exist in the latest version
            let search_item = if *req_path.last().unwrap() == "index.html" { // this is a module
                req_path[&req_path.len() - 2]
            } else { // this is an item
                req_path.last().unwrap().split('.').nth(1)
                    .expect("paths should be of the form <class>.<name>.html")
            };
            // TODO: check if req_path[3] is the platform choice or the name of the crate
            format!("{}/?search={}", req_path[3], search_item)
        };
        (path, version)
    } else {
        (String::new(), String::new())
    };

    Page::new(content)
        .set_true("show_package_navigation")
        .set_true("package_navigation_documentation_tab")
        .set_true("package_navigation_show_platforms_tab")
        .set_bool("is_latest_version", path.is_empty())
        .set("path_in_latest", &path)
        .set("latest_version", &version)
        .to_resp("rustdoc")
}

pub fn badge_handler(req: &mut Request) -> IronResult<Response> {
    use iron::headers::ContentType;
    use params::{Params, Value};
    use badge::{Badge, BadgeOptions};

    let version = {
        let params = ctry!(req.get_ref::<Params>());
        match params.find(&["version"]) {
            Some(&Value::String(ref version)) => version.clone(),
            _ => "*".to_owned(),
        }
    };

    let name = cexpect!(extension!(req, Router).find("crate"));
    let conn = extension!(req, Pool);

    let options = match match_version(&conn, &name, Some(&version)) {
        MatchVersion::Exact(version) => {
            let rows = ctry!(conn.query("SELECT rustdoc_status
                                         FROM releases
                                         INNER JOIN crates ON crates.id = releases.crate_id
                                         WHERE crates.name = $1 AND releases.version = $2",
                                        &[&name, &version]));
            if rows.len() > 0 && rows.get(0).get(0) {
                BadgeOptions {
                    subject: "docs".to_owned(),
                    status: version,
                    color: "#4d76ae".to_owned(),
                }
            } else {
                BadgeOptions {
                    subject: "docs".to_owned(),
                    status: version,
                    color: "#e05d44".to_owned(),
                }
            }
        }
        MatchVersion::Semver(version) => {
            let url = ctry!(Url::parse(&format!("{}/{}/badge.svg?version={}",
                                                redirect_base(req),
                                                name,
                                                version)[..]));

            return Ok(super::redirect(url));
        }
        MatchVersion::None => {
            BadgeOptions {
                subject: "docs".to_owned(),
                status: "no builds".to_owned(),
                color: "#e05d44".to_owned(),
            }
        }
    };

    let mut resp = Response::with((status::Ok, ctry!(Badge::new(options)).to_svg()));
    resp.headers.set(ContentType("image/svg+xml".parse().unwrap()));
    resp.headers.set(Expires(HttpDate(time::now())));
    resp.headers.set(CacheControl(vec![CacheDirective::NoCache,
                                       CacheDirective::NoStore,
                                       CacheDirective::MustRevalidate]));
    Ok(resp)
}

/// Serves shared web resources used by rustdoc-generated documentation.
///
/// This includes common `css` and `js` files that only change when the compiler is updated, but are
/// otherwise the same for all crates documented with that compiler. Those have a custom handler to
/// deduplicate them and save space.
pub struct SharedResourceHandler;

impl Handler for SharedResourceHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let path = req.url.path();
        let filename = path.last().unwrap();  // unwrap is fine: vector is non-empty
        let suffix = filename.split('.').last().unwrap();  // unwrap is fine: split always works
        if ["js", "css", "woff", "svg"].contains(&suffix) {
            let conn = extension!(req, Pool);

            if let Some(file) = File::from_path(conn, filename) {
                return Ok(file.serve());
            }
        }

        // Just always return a 404 here - the main handler will then try the other handlers
        Err(IronError::new(Nope::ResourceNotFound, status::NotFound))
    }
}
<commit_msg>fix broken link in the wrong circumstances<commit_after>//! rustdoc handler

use super::pool::Pool;
use super::file::File;
use super::{latest_version, redirect_base};
use super::crate_details::CrateDetails;
use iron::prelude::*;
use iron::{status, Url};
use iron::modifiers::Redirect;
use router::Router;
use super::{match_version, MatchVersion};
use super::error::Nope;
use super::page::Page;
use rustc_serialize::json::{Json, ToJson};
use std::collections::BTreeMap;
use iron::headers::{Expires, HttpDate, CacheControl, CacheDirective};
use time;
use iron::Handler;
use utils;

#[derive(Debug)]
struct RustdocPage {
    pub head: String,
    pub body: String,
    pub body_class: String,
    pub name: String,
    pub full: String,
    pub version: String,
    pub description: Option<String>,
    pub crate_details: Option<CrateDetails>,
}

impl Default for RustdocPage {
    fn default() -> RustdocPage {
        RustdocPage {
            head: String::new(),
            body: String::new(),
            body_class: String::new(),
            name: String::new(),
            full: String::new(),
            version: String::new(),
            description: None,
            crate_details: None,
        }
    }
}

impl ToJson for RustdocPage {
    fn to_json(&self) -> Json {
        let mut m: BTreeMap<String, Json> = BTreeMap::new();
        m.insert("rustdoc_head".to_string(), self.head.to_json());
        m.insert("rustdoc_body".to_string(), self.body.to_json());
        m.insert("rustdoc_body_class".to_string(), self.body_class.to_json());
        m.insert("rustdoc_full".to_string(), self.full.to_json());
        m.insert("rustdoc_status".to_string(), true.to_json());
        m.insert("name".to_string(), self.name.to_json());
        m.insert("version".to_string(), self.version.to_json());
        m.insert("description".to_string(), self.description.to_json());
        m.insert("crate_details".to_string(), self.crate_details.to_json());
        m.to_json()
    }
}

pub struct RustLangRedirector {
    url: Url,
}

impl RustLangRedirector {
    pub fn new(target: &'static str) -> Self {
        let url = url::Url::parse("https://doc.rust-lang.org/stable/")
            .expect("failed to parse rust-lang.org base URL")
            .join(target)
            .expect("failed to append crate name to rust-lang.org base URL");
        let url = Url::from_generic_url(url)
            .expect("failed to convert url::Url to iron::Url");
        Self { url }
    }
}

impl iron::Handler for RustLangRedirector {
    fn handle(&self, _req: &mut Request) -> IronResult<Response> {
        Ok(Response::with((status::Found, Redirect(self.url.clone()))))
    }
}

/// Handler called for `/:crate` and `/:crate/:version` URLs. Automatically redirects to the docs
/// or crate details page based on whether the given crate version was successfully built.
pub fn rustdoc_redirector_handler(req: &mut Request) -> IronResult<Response> {

    fn redirect_to_doc(req: &Request,
                       name: &str,
                       vers: &str,
                       target_name: &str)
                       -> IronResult<Response> {
        let url = ctry!(Url::parse(&format!("{}/{}/{}/{}/",
                                            redirect_base(req),
                                            name,
                                            vers,
                                            target_name)[..]));
        let mut resp = Response::with((status::Found, Redirect(url)));
        resp.headers.set(Expires(HttpDate(time::now())));

        Ok(resp)
    }

    fn redirect_to_crate(req: &Request,
                         name: &str,
                         vers: &str)
                         -> IronResult<Response> {
        let url = ctry!(Url::parse(&format!("{}/crate/{}/{}",
                                            redirect_base(req),
                                            name,
                                            vers)[..]));

        let mut resp = Response::with((status::Found, Redirect(url)));
        resp.headers.set(Expires(HttpDate(time::now())));

        Ok(resp)
    }

    // this unwrap is safe because iron urls are always able to use `path_segments`
    // i'm using this instead of `req.url.path()` to avoid allocating the Vec, and also to avoid
    // keeping the borrow alive into the return statement
    if req.url.as_ref().path_segments().unwrap().last().map_or(false, |s| s.ends_with(".js")) {
        // javascript files should be handled by the file server instead of erroneously
        // redirecting to the crate root page
        if req.url.as_ref().path_segments().unwrap().count() > 2 {
            // this URL is actually from a crate-internal path, serve it there instead
            return rustdoc_html_server_handler(req);
        } else {
            let path = req.url.path();
            let path = path.join("/");
            let conn = extension!(req, Pool);
            match File::from_path(&conn, &path) {
                Some(f) => return Ok(f.serve()),
                None => return Err(IronError::new(Nope::ResourceNotFound, status::NotFound)),
            }
        }
    } else if req.url.as_ref().path_segments().unwrap().last().map_or(false, |s| s.ends_with(".ico")) {
        // route .ico files into their dedicated handler so that docs.rs's favicon is always
        // displayed
        return super::ico_handler(req);
    }

    let router = extension!(req, Router);
    // this handler should never called without crate pattern
    let crate_name = cexpect!(router.find("crate"));
    let req_version = router.find("version");

    let conn = extension!(req, Pool);

    // it doesn't matter if the version that was given was exact or not, since we're redirecting
    // anyway
    let version = match match_version(&conn, &crate_name, req_version).into_option() {
        Some(v) => v,
        None => return Err(IronError::new(Nope::CrateNotFound, status::NotFound)),
    };

    // get target name and whether it has docs
    // FIXME: This is a bit inefficient but allowing us to use less code in general
    let (target_name, has_docs): (String, bool) = {
        let rows = ctry!(conn.query("SELECT target_name, rustdoc_status
                                     FROM releases
                                     INNER JOIN crates ON crates.id = releases.crate_id
                                     WHERE crates.name = $1 AND releases.version = $2",
                                    &[&crate_name, &version]));

        (rows.get(0).get(0), rows.get(0).get(1))
    };

    if has_docs {
        redirect_to_doc(req, &crate_name, &version, &target_name)
    } else {
        redirect_to_crate(req, &crate_name, &version)
    }
}

/// Serves documentation generated by rustdoc.
///
/// This includes all HTML files for an individual crate, as well as the `search-index.js`, which is
/// also crate-specific.
pub fn rustdoc_html_server_handler(req: &mut Request) -> IronResult<Response> {

    let router = extension!(req, Router);
    let name = router.find("crate").unwrap_or("").to_string();
    let url_version = router.find("version");
    let version; // pre-declaring it to enforce drop order relative to `req_path`
    let conn = extension!(req, Pool);

    let mut req_path = req.url.path();

    // remove name and version from path
    for _ in 0..2 {
        req_path.remove(0);
    }

    version = match match_version(&conn, &name, url_version) {
        MatchVersion::Exact(v) => v,
        MatchVersion::Semver(v) => {
            // to prevent cloudfront caching the wrong artifacts on URLs with loose semver
            // versions, redirect the browser to the returned version instead of loading it
            // immediately
            let url = ctry!(Url::parse(&format!("{}/{}/{}/{}",
                                                redirect_base(req),
                                                name,
                                                v,
                                                req_path.join("/"))[..]));
            return Ok(super::redirect(url));
        }
        MatchVersion::None => return Err(IronError::new(Nope::ResourceNotFound, status::NotFound)),
    };

    // docs have "rustdoc" prefix in database
    req_path.insert(0, "rustdoc");

    // add crate name and version
    req_path.insert(1, &name);
    req_path.insert(2, &version);

    let path = {
        let mut path = req_path.join("/");
        if path.ends_with('/') {
            req_path.pop(); // get rid of empty string
            path.push_str("index.html");
            req_path.push("index.html");
        }
        path
    };

    let file = match File::from_path(&conn, &path) {
        Some(f) => f,
        None => return Err(IronError::new(Nope::ResourceNotFound, status::NotFound)),
    };

    // serve file directly if it's not html
    if !path.ends_with(".html") {
        return Ok(file.serve());
    }

    let mut content = RustdocPage::default();

    let file_content = ctry!(String::from_utf8(file.0.content));

    let (head, body, mut body_class) = ctry!(utils::extract_head_and_body(&file_content));
    content.head = head;
    content.body = body;

    if body_class.is_empty() {
        body_class = "rustdoc container-rustdoc".to_string();
    } else {
        // rustdoc adds its own "rustdoc" class to the body
        body_class.push_str(" container-rustdoc");
    }
    content.body_class = body_class;

    content.full = file_content;
    let crate_details = cexpect!(CrateDetails::new(&conn, &name, &version));
    let latest_version = latest_version(&crate_details.versions, &version);

    let (path, version) = if let Some(version) = latest_version {
        req_path[2] = &version;
        let path = if File::from_path(&conn, &req_path.join("/")).is_some() {
            req_path[3..].join("/") // NOTE: this adds 'index.html' if it wasn't there before
        } else { // this page doesn't exist in the latest version
            let search_item = if *req_path.last().unwrap() == "index.html" { // this is a module
                req_path[&req_path.len() - 2]
            } else { // this is an item
                req_path.last().unwrap().split('.').nth(1)
                    .expect("paths should be of the form <class>.<name>.html")
            };
            // check if req_path[3] is the platform choice or the name of the crate
            let concat_path;
            let crate_root = if req_path[3] != crate_details.target_name {
                concat_path = format!("{}/{}", req_path[3], req_path[4]);
                &concat_path
            } else {
                req_path[3]
            };
            format!("{}/?search={}", crate_root, search_item)
        };
        (path, version)
    } else {
        (String::new(), String::new())
    };

    content.crate_details = Some(crate_details);

    Page::new(content)
        .set_true("show_package_navigation")
        .set_true("package_navigation_documentation_tab")
        .set_true("package_navigation_show_platforms_tab")
        .set_bool("is_latest_version", path.is_empty())
        .set("path_in_latest", &path)
        .set("latest_version", &version)
        .to_resp("rustdoc")
}

pub fn badge_handler(req: &mut Request) -> IronResult<Response> {
    use iron::headers::ContentType;
    use params::{Params, Value};
    use badge::{Badge, BadgeOptions};

    let version = {
        let params = ctry!(req.get_ref::<Params>());
        match params.find(&["version"]) {
            Some(&Value::String(ref version)) => version.clone(),
            _ => "*".to_owned(),
        }
    };

    let name = cexpect!(extension!(req, Router).find("crate"));
    let conn = extension!(req, Pool);

    let options = match match_version(&conn, &name, Some(&version)) {
        MatchVersion::Exact(version) => {
            let rows = ctry!(conn.query("SELECT rustdoc_status
                                         FROM releases
                                         INNER JOIN crates ON crates.id = releases.crate_id
                                         WHERE crates.name = $1 AND releases.version = $2",
                                        &[&name, &version]));
            if rows.len() > 0 && rows.get(0).get(0) {
                BadgeOptions {
                    subject: "docs".to_owned(),
                    status: version,
                    color: "#4d76ae".to_owned(),
                }
            } else {
                BadgeOptions {
                    subject: "docs".to_owned(),
                    status: version,
                    color: "#e05d44".to_owned(),
                }
            }
        }
        MatchVersion::Semver(version) => {
            let url = ctry!(Url::parse(&format!("{}/{}/badge.svg?version={}",
                                                redirect_base(req),
                                                name,
                                                version)[..]));

            return Ok(super::redirect(url));
        }
        MatchVersion::None => {
            BadgeOptions {
                subject: "docs".to_owned(),
                status: "no builds".to_owned(),
                color: "#e05d44".to_owned(),
            }
        }
    };

    let mut resp = Response::with((status::Ok, ctry!(Badge::new(options)).to_svg()));
    resp.headers.set(ContentType("image/svg+xml".parse().unwrap()));
    resp.headers.set(Expires(HttpDate(time::now())));
    resp.headers.set(CacheControl(vec![CacheDirective::NoCache,
                                       CacheDirective::NoStore,
                                       CacheDirective::MustRevalidate]));
    Ok(resp)
}

/// Serves shared web resources used by rustdoc-generated documentation.
///
/// This includes common `css` and `js` files that only change when the compiler is updated, but are
/// otherwise the same for all crates documented with that compiler. Those have a custom handler to
/// deduplicate them and save space.
pub struct SharedResourceHandler;

impl Handler for SharedResourceHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let path = req.url.path();
        let filename = path.last().unwrap();  // unwrap is fine: vector is non-empty
        let suffix = filename.split('.').last().unwrap();  // unwrap is fine: split always works
        if ["js", "css", "woff", "svg"].contains(&suffix) {
            let conn = extension!(req, Pool);

            if let Some(file) = File::from_path(conn, filename) {
                return Ok(file.serve());
            }
        }

        // Just always return a 404 here - the main handler will then try the other handlers
        Err(IronError::new(Nope::ResourceNotFound, status::NotFound))
    }
}
<|endoftext|>


<commit_before>use crate::config::CONF;
use crossbeam::{channel::bounded, Sender};
use libp2p::{
    core,
    dns::DnsConfig,
    identify, identity, kad, mplex,
    multiaddr::Protocol,
    noise,
    swarm::{NetworkBehaviourEventProcess, SwarmEvent},
    tcp::TcpConfig,
    yamux, Multiaddr, NetworkBehaviour, PeerId, Swarm, Transport,
};
use std::{collections::HashSet, io::Write, net::IpAddr};

/// A prepared network connection not yet running.
/// This can be either the preparation of a network bootstrap node or a new peer
/// connecting to an existing network.
pub struct Network {
    id: PeerId,
    sent_queries: HashSet<kad::QueryId>,
    swarm: Swarm<Behaviour>,
}

impl Network {
    /// Bootstrap the network with a listener which will act as the initial provider. This initial peer
    /// will be listening at the provided port and assigned IP. If those are not free it will error.
    ///
    /// ## Arguments
    /// - ip: IP associated to this node.
    /// - port: listening port.
    /// - peer: Optional connection to an already existing listener.
    /// - key: Optional identity key of this node; if it's not provided it will be either obtained
    ///        from the configuration or generated
    pub fn bootstrap<T: Into<IpAddr>>(
        ip: T,
        port: u16,
        peer: Option<Provider>,
        key: Option<identity::ed25519::Keypair>,
    ) -> std::io::Result<NetworkHandle> {
        let builder = network_builder::NetworkBuilder::new(peer, key);
        let local_key = builder.local_ed25519_key.clone();
        let mut network = builder.configure_network()?;

        let mut bootstrap_addr = Multiaddr::with_capacity(2);
        bootstrap_addr.push(Protocol::from(ip.into()));
        bootstrap_addr.push(Protocol::Tcp(port));
        let _listener_id = Swarm::listen_on(&mut network.swarm, bootstrap_addr).unwrap();

        let sender = network.run_event_loop();
        Ok(NetworkHandle { sender, local_key })
    }

    /// Join an existing network as a new or old node (if the identity was already registered).
    pub fn join_network(bootstrap_info: Provider) -> std::io::Result<NetworkHandle> {
        let builder = network_builder::NetworkBuilder::new(Some(bootstrap_info), None);
        let local_key = builder.local_ed25519_key.clone();
        let mut network = builder.configure_network()?;

        // let mut listening_addr = Multiaddr::with_capacity(2);
        // listening_addr.push(Protocol::from(Ipv4Addr::LOCALHOST));
        // listening_addr.push(Protocol::Tcp(get_free_port().unwrap()));
        // let _listener_id = Swarm::listen_on(&mut swarm, listening_addr).unwrap();

        let bootstrap_query = network.swarm.bootstrap();
        network.sent_queries.insert(bootstrap_query);

        let sender = network.run_event_loop();
        Ok(NetworkHandle { sender, local_key })
    }

    fn run_event_loop(mut self) -> Sender<String> {
        let (sender, receiver) = bounded::<String>(100);
        std::thread::spawn(|| {
            smol::run(async move {
                eprintln!("Setting #{} event loop", &self.id);
                loop {
                    if let Ok(msg) = receiver.try_recv() {
                        eprintln!("Received: {}", msg);
                    }
                    match self.swarm.next_event().await {
                        SwarmEvent::Behaviour(event) => {
                            // let Behaviour { kad, identify } = event;
                            // self.process_event(event);
                            todo!()
                        }
                        SwarmEvent::IncomingConnection {
                            local_addr,
                            send_back_addr,
                        } => {
                            eprintln!("Connected at {}, callback {}", local_addr, send_back_addr);
                        }
                        SwarmEvent::UnreachableAddr {
                            peer_id,
                            address,
                            attempts_remaining,
                            ..
                        } => {
                            eprintln!(
                                "Connected by #{} from address {}; attempts remaining: {}",
                                peer_id, address, attempts_remaining
                            );
                        }
                        SwarmEvent::Dialing(id) => {
                            eprintln!("Connected by #{}", id);
                        }
                        _ => {}
                    }
                }
            })
        });
        sender
    }

    fn process_event(&mut self, event: kad::KademliaEvent) {
        eprintln!("\nPeer #{} received event:\n {:?}", self.id, event);
        match event {
            kad::KademliaEvent::QueryResult { result, id, .. } => {
                if self.sent_queries.remove(&id) {
                    eprintln!("Got result from query id: {:?}", id);
                }
            }
            kad::KademliaEvent::RoutablePeer { .. } => {}
            kad::KademliaEvent::RoutingUpdated { .. } => {}
            kad::KademliaEvent::UnroutablePeer { .. } => {}
            kad::KademliaEvent::PendingRoutablePeer { .. } => {}
        }
    }
}

#[derive(NetworkBehaviour)]
struct Behaviour {
    kad: kad::Kademlia<kad::store::MemoryStore>,
    identify: identify::Identify,
}

impl Behaviour {
    fn bootstrap(&mut self) -> kad::QueryId {
        self.kad
            .bootstrap()
            .expect("At least one peer is required when bootstrapping.")
    }
}

impl NetworkBehaviourEventProcess<identify::IdentifyEvent> for Behaviour {
    fn inject_event(&mut self, event: identify::IdentifyEvent) {
        todo!()
    }
}

impl NetworkBehaviourEventProcess<kad::KademliaEvent> for Behaviour {
    fn inject_event(&mut self, message: kad::KademliaEvent) {
        todo!()
    }
}

/// A handle to a running network connection.
pub struct NetworkHandle {
    sender: Sender<String>,
    local_key: identity::ed25519::Keypair,
}

impl NetworkHandle {
    /// Get this peer id encoded as a Base58 string.
    pub fn get_peer_id(&self) -> String {
        peer_id_from_ed25519(self.local_key.public()).to_base58()
    }

    /// Saves this peer secret key to a file in bytes. This file should be kept in a secure location.
    pub fn save_secret_key<T: AsRef<std::path::Path>>(&self, path: T) -> std::io::Result<()> {
        let enconded_key = self.local_key.encode().to_vec();
        use std::fs::File;
        let mut file = File::create(path.as_ref())?;
        file.write_all(enconded_key.as_slice())
    }

    /// Returns Ok while the connection to the network still is running or Err if
    /// it shutdowns.
    pub fn is_running(&self) -> Result<(), ()> {
        Ok(())
    }
}

/// Initial listening provider peer to bootstrap the network.
#[derive(Clone)]
pub struct Provider {
    addr: Option<Multiaddr>,
    identifier: Option<PeerId>,
}

impl Provider {
    pub fn new() -> Provider {
        Provider {
            addr: None,
            identifier: None,
        }
    }

    /// IP which will be assigned to this node.
    pub fn listening_ip<T: Into<IpAddr>>(mut self, ip: T) -> Self {
        if let Some(addr) = &mut self.addr {
            addr.push(Protocol::from(ip.into()));
        } else {
            self.addr = Some(Multiaddr::from(ip.into()));
        }
        self
    }

    /// TCP listening port (only required in case of using TCP as transport).
    /// If not specified port 7800 will be used as default.
    pub fn listening_port(mut self, port: u16) -> Self {
        if let Some(addr) = &mut self.addr {
            addr.push(Protocol::Tcp(port));
        } else {
            self.addr = Some(Multiaddr::from(Protocol::Tcp(port)));
        }
        self
    }

    pub fn with_identifier(mut self, id: PeerId) -> Self {
        self.identifier = Some(id);
        self
    }
}

impl From<(Multiaddr, PeerId)> for Provider {
    fn from(info: (Multiaddr, PeerId)) -> Self {
        let (addr, identifier) = info;
        Provider {
            addr: Some(addr),
            identifier: Some(identifier),
        }
    }
}

impl std::default::Default for Provider {
    fn default() -> Self {
        let conf = &CONF;
        let mut multi_addr = Multiaddr::with_capacity(2);
        multi_addr.push(Protocol::from(conf.bootstrap_ip));
        multi_addr.push(Protocol::Tcp(conf.bootstrap_port));
        let identifier = conf.bootstrap_id.clone()
            .expect("At least one public identifier is required to bootstrap the connection to the network.");
        Provider {
            addr: Some(multi_addr),
            identifier: Some(identifier),
        }
    }
}

fn peer_id_from_ed25519(key: identity::ed25519::PublicKey) -> PeerId {
    PeerId::from_public_key(identity::PublicKey::Ed25519(key))
}

mod network_builder {
    use super::*;

    pub(super) struct NetworkBuilder {
        /// ED25519 local peer private key.
        pub local_ed25519_key: identity::ed25519::Keypair,
        /// ED25519 local peer private key in generic format.
        local_key: identity::Keypair,
        /// The peer ID of this machine.
        local_peer_id: PeerId,
        /// At least an other running listener node is required for joining the network.
        /// Not necessary if this is an initial provider.
        remote_provider: Option<Provider>,
    }

    impl NetworkBuilder {
        const CURRENT_AGENT_VERSION: &'static str = "simag/0.1.0";

        pub fn new(
            remote_provider: Option<Provider>,
            key: Option<identity::ed25519::Keypair>,
        ) -> NetworkBuilder {
            let ed25519_key = {
                if let Some(key) = key {
                    key
                } else if let Some(key) = &CONF.local_peer_keypair {
                    key.clone()
                } else {
                    identity::ed25519::Keypair::generate()
                }
            };
            let local_key = identity::Keypair::Ed25519(ed25519_key.clone());
            let local_peer_id = PeerId::from(local_key.public());
            NetworkBuilder {
                local_ed25519_key: ed25519_key,
                local_key,
                local_peer_id,
                remote_provider,
            }
        }

        pub fn configure_network(self) -> std::io::Result<Network> {
            let transport = self.set_transport()?;
            let behav = Behaviour {
                kad: self.set_kademlia_dht(),
                identify: identify::Identify::new(
                    "ipfs/0.1.0".to_owned(),
                    Self::CURRENT_AGENT_VERSION.to_owned(),
                    self.local_key.public(),
                ),
            };
            let swarm = Swarm::new(transport, behav, self.local_peer_id.clone());

            Ok(Network {
                swarm,
                sent_queries: HashSet::new(),
                id: self.local_peer_id,
            })
        }

        fn set_transport(
            &self,
        ) -> std::io::Result<
            impl Transport<
                    Output = (
                        PeerId,
                        impl libp2p::core::muxing::StreamMuxer<
                                OutboundSubstream = impl Send,
                                Substream = impl Send,
                                Error = impl Into<std::io::Error>,
                            > + Send
                            + Sync,
                    ),
                    Listener = impl Send,
                    ListenerUpgrade = impl Send,
                    Dial = impl Send,
                    Error = impl std::error::Error + Send,
                > + Clone,
        > {
            let noise_keys = noise::Keypair::<noise::X25519Spec>::new()
                .into_authentic(&self.local_key)
                .expect("Signing libp2p-noise static DH keypair failed.");

            let tcp = TcpConfig::new().nodelay(true);
            Ok(DnsConfig::new(tcp)?
                .upgrade(core::upgrade::Version::V1)
                .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated())
                .multiplex(core::upgrade::SelectUpgrade::new(
                    yamux::Config::default(),
                    mplex::MplexConfig::new(),
                ))
                .map(|(peer, muxer), _| (peer, core::muxing::StreamMuxerBox::new(muxer)))
                .timeout(std::time::Duration::from_secs(20)))
        }

        fn set_kademlia_dht(&self) -> kad::Kademlia<kad::store::MemoryStore> {
            let store = kad::store::MemoryStore::new(self.local_peer_id.clone());
            let mut kdm = kad::Kademlia::new(self.local_peer_id.clone(), store);

            if let Some(remote_bootstrap) = &self.remote_provider {
                // There is already at least one existing node in the network. Add it to the table and query for bootstrapping.
                kdm.add_address(
                    remote_bootstrap.identifier.as_ref().unwrap(),
                    remote_bootstrap.addr.clone().unwrap(),
                );
            }
            kdm
        }
    }
}
<commit_msg>Add custom net event<commit_after>use crate::config::CONF;
use crossbeam::{channel::bounded, Sender};
use libp2p::{
    core,
    dns::DnsConfig,
    identify, identity, kad, mplex,
    multiaddr::Protocol,
    noise,
    swarm::{NetworkBehaviourEventProcess, SwarmEvent},
    tcp::TcpConfig,
    yamux, Multiaddr, NetworkBehaviour, PeerId, Swarm, Transport,
};
use std::{collections::HashSet, io::Write, net::IpAddr};

/// A prepared network connection not yet running.
/// This can be either the preparation of a network bootstrap node or a new peer
/// connecting to an existing network.
pub struct Network {
    id: PeerId,
    sent_queries: HashSet<kad::QueryId>,
    swarm: Swarm<NetBehaviour>,
}

impl Network {
    /// Bootstrap the network with a listener which will act as the initial provider. This initial peer
    /// will be listening at the provided port and assigned IP. If those are not free it will error.
    ///
    /// ## Arguments
    /// - ip: IP associated to this node.
    /// - port: listening port.
    /// - peer: Optional connection to an already existing listener.
    /// - key: Optional identity key of this node; if it's not provided it will be either obtained
    ///        from the configuration or generated
    pub fn bootstrap<T: Into<IpAddr>>(
        ip: T,
        port: u16,
        peer: Option<Provider>,
        key: Option<identity::ed25519::Keypair>,
    ) -> std::io::Result<NetworkHandle> {
        let builder = network_builder::NetworkBuilder::new(peer, key);
        let local_key = builder.local_ed25519_key.clone();
        let mut network = builder.configure_network()?;

        let mut bootstrap_addr = Multiaddr::with_capacity(2);
        bootstrap_addr.push(Protocol::from(ip.into()));
        bootstrap_addr.push(Protocol::Tcp(port));
        let _listener_id = Swarm::listen_on(&mut network.swarm, bootstrap_addr).unwrap();

        let sender = network.run_event_loop();
        Ok(NetworkHandle { sender, local_key })
    }

    /// Join an existing network as a new or old node (if the identity was already registered).
    pub fn join_network(bootstrap_info: Provider) -> std::io::Result<NetworkHandle> {
        let builder = network_builder::NetworkBuilder::new(Some(bootstrap_info), None);
        let local_key = builder.local_ed25519_key.clone();
        let mut network = builder.configure_network()?;

        // let mut listening_addr = Multiaddr::with_capacity(2);
        // listening_addr.push(Protocol::from(Ipv4Addr::LOCALHOST));
        // listening_addr.push(Protocol::Tcp(get_free_port().unwrap()));
        // let _listener_id = Swarm::listen_on(&mut swarm, listening_addr).unwrap();

        let bootstrap_query = network.swarm.bootstrap();
        network.sent_queries.insert(bootstrap_query);

        let sender = network.run_event_loop();
        Ok(NetworkHandle { sender, local_key })
    }

    fn run_event_loop(mut self) -> Sender<String> {
        let (sender, receiver) = bounded::<String>(100);
        std::thread::spawn(|| {
            smol::run(async move {
                eprintln!("Setting #{} event loop", &self.id);
                loop {
                    if let Ok(msg) = receiver.try_recv() {
                        eprintln!("Received: {}", msg);
                    }
                    match self.swarm.next_event().await {
                        SwarmEvent::Behaviour(event) => match event {
                            NetEvent::Identify(_event) => {}
                            NetEvent::KademliaEvent(event) => self.process_event(event),
                        },
                        SwarmEvent::IncomingConnection {
                            local_addr,
                            send_back_addr,
                        } => {
                            eprintln!("Connected at {}, callback {}", local_addr, send_back_addr);
                        }
                        SwarmEvent::UnreachableAddr {
                            peer_id,
                            address,
                            attempts_remaining,
                            ..
                        } => {
                            eprintln!(
                                "Connected by #{} from address {}; attempts remaining: {}",
                                peer_id, address, attempts_remaining
                            );
                        }
                        SwarmEvent::Dialing(id) => {
                            eprintln!("Connected by #{}", id);
                        }
                        _ => {}
                    }
                }
            })
        });
        sender
    }

    fn process_event(&mut self, event: kad::KademliaEvent) {
        eprintln!("\nPeer #{} received event:\n {:?}", self.id, event);
        match event {
            kad::KademliaEvent::QueryResult { result, id, .. } => {
                if self.sent_queries.remove(&id) {
                    eprintln!("Got result from query id: {:?}", id);
                }
            }
            kad::KademliaEvent::RoutablePeer { .. } => {}
            kad::KademliaEvent::RoutingUpdated { .. } => {}
            kad::KademliaEvent::UnroutablePeer { .. } => {}
            kad::KademliaEvent::PendingRoutablePeer { .. } => {}
        }
    }
}

#[derive(NetworkBehaviour)]
#[behaviour(event_process = false)]
#[behaviour(out_event = "NetEvent")]
struct NetBehaviour {
    kad: kad::Kademlia<kad::store::MemoryStore>,
    identify: identify::Identify,
}

enum NetEvent {
    KademliaEvent(kad::KademliaEvent),
    Identify(identify::IdentifyEvent),
}

impl From<kad::KademliaEvent> for NetEvent {
    fn from(event: kad::KademliaEvent) -> NetEvent {
        Self::KademliaEvent(event)
    }
}

impl From<identify::IdentifyEvent> for NetEvent {
    fn from(event: identify::IdentifyEvent) -> NetEvent {
        Self::Identify(event)
    }
}

impl NetBehaviour {
    fn bootstrap(&mut self) -> kad::QueryId {
        self.kad
            .bootstrap()
            .expect("At least one peer is required when bootstrapping.")
    }
}

impl NetworkBehaviourEventProcess<identify::IdentifyEvent> for NetBehaviour {
    fn inject_event(&mut self, event: identify::IdentifyEvent) {
        todo!()
    }
}

impl NetworkBehaviourEventProcess<kad::KademliaEvent> for NetBehaviour {
    fn inject_event(&mut self, message: kad::KademliaEvent) {
        todo!()
    }
}

/// A handle to a running network connection.
pub struct NetworkHandle {
    sender: Sender<String>,
    local_key: identity::ed25519::Keypair,
}

impl NetworkHandle {
    /// Get this peer id encoded as a Base58 string.
    pub fn get_peer_id(&self) -> String {
        peer_id_from_ed25519(self.local_key.public()).to_base58()
    }

    /// Saves this peer secret key to a file in bytes. This file should be kept in a secure location.
    pub fn save_secret_key<T: AsRef<std::path::Path>>(&self, path: T) -> std::io::Result<()> {
        let enconded_key = self.local_key.encode().to_vec();
        use std::fs::File;
        let mut file = File::create(path.as_ref())?;
        file.write_all(enconded_key.as_slice())
    }

    /// Returns Ok while the connection to the network still is running or Err if
    /// it shutdowns.
    pub fn is_running(&self) -> Result<(), ()> {
        Ok(())
    }
}

/// Initial listening provider peer to bootstrap the network.
#[derive(Clone)]
pub struct Provider {
    addr: Option<Multiaddr>,
    identifier: Option<PeerId>,
}

impl Provider {
    pub fn new() -> Provider {
        Provider {
            addr: None,
            identifier: None,
        }
    }

    /// IP which will be assigned to this node.
    pub fn listening_ip<T: Into<IpAddr>>(mut self, ip: T) -> Self {
        if let Some(addr) = &mut self.addr {
            addr.push(Protocol::from(ip.into()));
        } else {
            self.addr = Some(Multiaddr::from(ip.into()));
        }
        self
    }

    /// TCP listening port (only required in case of using TCP as transport).
    /// If not specified port 7800 will be used as default.
    pub fn listening_port(mut self, port: u16) -> Self {
        if let Some(addr) = &mut self.addr {
            addr.push(Protocol::Tcp(port));
        } else {
            self.addr = Some(Multiaddr::from(Protocol::Tcp(port)));
        }
        self
    }

    pub fn with_identifier(mut self, id: PeerId) -> Self {
        self.identifier = Some(id);
        self
    }
}

impl From<(Multiaddr, PeerId)> for Provider {
    fn from(info: (Multiaddr, PeerId)) -> Self {
        let (addr, identifier) = info;
        Provider {
            addr: Some(addr),
            identifier: Some(identifier),
        }
    }
}

impl std::default::Default for Provider {
    fn default() -> Self {
        let conf = &CONF;
        let mut multi_addr = Multiaddr::with_capacity(2);
        multi_addr.push(Protocol::from(conf.bootstrap_ip));
        multi_addr.push(Protocol::Tcp(conf.bootstrap_port));
        let identifier = conf.bootstrap_id.clone()
            .expect("At least one public identifier is required to bootstrap the connection to the network.");
        Provider {
            addr: Some(multi_addr),
            identifier: Some(identifier),
        }
    }
}

fn peer_id_from_ed25519(key: identity::ed25519::PublicKey) -> PeerId {
    PeerId::from_public_key(identity::PublicKey::Ed25519(key))
}

mod network_builder {
    use super::*;

    pub(super) struct NetworkBuilder {
        /// ED25519 local peer private key.
        pub local_ed25519_key: identity::ed25519::Keypair,
        /// ED25519 local peer private key in generic format.
        local_key: identity::Keypair,
        /// The peer ID of this machine.
        local_peer_id: PeerId,
        /// At least an other running listener node is required for joining the network.
        /// Not necessary if this is an initial provider.
        remote_provider: Option<Provider>,
    }

    impl NetworkBuilder {
        const CURRENT_AGENT_VERSION: &'static str = "simag/0.1.0";

        pub fn new(
            remote_provider: Option<Provider>,
            key: Option<identity::ed25519::Keypair>,
        ) -> NetworkBuilder {
            let ed25519_key = {
                if let Some(key) = key {
                    key
                } else if let Some(key) = &CONF.local_peer_keypair {
                    key.clone()
                } else {
                    identity::ed25519::Keypair::generate()
                }
            };
            let local_key = identity::Keypair::Ed25519(ed25519_key.clone());
            let local_peer_id = PeerId::from(local_key.public());
            NetworkBuilder {
                local_ed25519_key: ed25519_key,
                local_key,
                local_peer_id,
                remote_provider,
            }
        }

        pub fn configure_network(self) -> std::io::Result<Network> {
            let transport = self.set_transport()?;
            let behav = NetBehaviour {
                kad: self.set_kademlia_dht(),
                identify: identify::Identify::new(
                    "ipfs/0.1.0".to_owned(),
                    Self::CURRENT_AGENT_VERSION.to_owned(),
                    self.local_key.public(),
                ),
            };
            let swarm = Swarm::new(transport, behav, self.local_peer_id.clone());

            Ok(Network {
                swarm,
                sent_queries: HashSet::new(),
                id: self.local_peer_id,
            })
        }

        fn set_transport(
            &self,
        ) -> std::io::Result<
            impl Transport<
                    Output = (
                        PeerId,
                        impl libp2p::core::muxing::StreamMuxer<
                                OutboundSubstream = impl Send,
                                Substream = impl Send,
                                Error = impl Into<std::io::Error>,
                            > + Send
                            + Sync,
                    ),
                    Listener = impl Send,
                    ListenerUpgrade = impl Send,
                    Dial = impl Send,
                    Error = impl std::error::Error + Send,
                > + Clone,
        > {
            let noise_keys = noise::Keypair::<noise::X25519Spec>::new()
                .into_authentic(&self.local_key)
                .expect("Signing libp2p-noise static DH keypair failed.");

            let tcp = TcpConfig::new().nodelay(true);
            Ok(DnsConfig::new(tcp)?
                .upgrade(core::upgrade::Version::V1)
                .authenticate(noise::NoiseConfig::xx(noise_keys).into_authenticated())
                .multiplex(core::upgrade::SelectUpgrade::new(
                    yamux::Config::default(),
                    mplex::MplexConfig::new(),
                ))
                .map(|(peer, muxer), _| (peer, core::muxing::StreamMuxerBox::new(muxer)))
                .timeout(std::time::Duration::from_secs(20)))
        }

        fn set_kademlia_dht(&self) -> kad::Kademlia<kad::store::MemoryStore> {
            let store = kad::store::MemoryStore::new(self.local_peer_id.clone());
            let mut kdm = kad::Kademlia::new(self.local_peer_id.clone(), store);

            if let Some(remote_bootstrap) = &self.remote_provider {
                // There is already at least one existing node in the network. Add it to the table and query for bootstrapping.
                kdm.add_address(
                    remote_bootstrap.identifier.as_ref().unwrap(),
                    remote_bootstrap.addr.clone().unwrap(),
                );
            }
            kdm
        }
    }
}
<|endoftext|>


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

pub fn part1(_input: &mut dyn Read) -> String {
    todo!()
}

pub fn part2(_input: &mut dyn Read) -> String {
    todo!()
}
<commit_msg>Implement fast day 21 part 1<commit_after>use std::io::Read;

use crate::common::LineIter;

fn read_input(input: &mut dyn Read) -> (i32, i32) {
    let mut reader = LineIter::new(input);

    let a = reader
        .next()
        .unwrap()
        .split(' ')
        .last()
        .unwrap()
        .parse()
        .unwrap();

    let b = reader
        .next()
        .unwrap()
        .split(' ')
        .last()
        .unwrap()
        .parse()
        .unwrap();

    (a, b)
}

#[inline]
fn simulate(die: i32, pos: i32) -> i32 {
    (pos + 3 * die + 3 - 1) % 10 + 1
}

fn find_repetition(mut pos: i32, mut die: i32) -> i32 {
    let mut advance = 0;

    for _ in 0..10 {
        pos = simulate(die, pos);
        advance += pos;
        die = (die + 6) % 10;
    }

    advance
}

pub fn part1(input: &mut dyn Read) -> String {
    const TARGET_SCORE: i32 = 1000;

    let (a, b) = read_input(input);

    let a10 = find_repetition(a, 1);
    let b10 = find_repetition(b, 4);

    let a_win = TARGET_SCORE / a10;
    let b_win = TARGET_SCORE / b10;

    let mut rolls = 3 * 20 * a_win.min(b_win);
    let mut a_score = rolls / 3 / 20 * a10;
    let mut b_score = rolls / 3 / 20 * b10;
    let mut a_pos = a;
    let mut b_pos = b;
    let mut die = 1;

    let (loser_score, rolls) = if a_win < b_win {
        while a_score < TARGET_SCORE {
            a_pos = simulate(die, a_pos);
            a_score += a_pos;
            rolls += 3;

            if a_score < TARGET_SCORE {
                b_pos = simulate(die + 3, b_pos);
                b_score += b_pos;
                rolls += 3;
            }

            die = (die + 6) % 10;
        }

        (b_score, rolls)
    } else {
        while b_score < TARGET_SCORE {
            a_pos = simulate(die, a_pos);
            a_score += a_pos;

            b_pos = simulate(die + 3, b_pos);
            b_score += b_pos;

            rolls += 6;

            die = (die + 6) % 10;
        }

        (a_score, rolls)
    };

    (loser_score * rolls).to_string()
}

pub fn part2(_input: &mut dyn Read) -> String {
    todo!()
}

#[cfg(test)]
mod tests {
    use crate::test_implementation;

    use super::*;

    const SAMPLE: &[u8] = include_bytes!("samples/21.txt");

    #[test]
    fn sample_part1() {
        test_implementation(part1, SAMPLE, 739785);
    }
}
<|endoftext|>


<commit_before>// library
extern crate my_extern_lib;

// modules
mod simple_functions {
    pub fn print_hello_world() {
        println!("Hello, World! (from the simple_functions module)");
     }

    // nested modules
    pub mod simple_math {
        pub fn multiple_two_integers(a: i32, b: i32) -> i32 {
            a * b
        }
    }
}

use simple_functions::simple_math::multiple_two_integers;

fn print_some_msg() {
    println!("Modules: printing from the outer function");
}

mod sample_module {

    pub fn call_sample_module() {
        use second_module::print_some_msg as print_second;
        use self::second_module::print_some_msg as print_second_sample;
        use super::print_some_msg as print_outside;
        print_outside();
        print_second();
        print_some_msg();
        print_second_sample();
    }

    mod second_module {

        pub fn print_some_msg() {
            println!("Modules: printing from the second module inside the sample module");
        }

    }

    fn print_some_msg() {
        println!("Modules: printing from the inside of the sample module");
    }

}

mod second_module {
    pub fn print_some_msg() {
        println!("Modules: printing from the second module");
    }
}

mod modules;

fn main() {

    // formatted output
    println!("Hello, Rust!");
    println!("Integer number = {}", 23);
    println!("Float number = {}", 1.012);
    println!("Repeat printing: {0}, {1}, {1}, {3}, {2}", 2, 1, 44, 9);
    println!("Named arguments: {name}, {age}, {occupation}", age="24", name="Ann", occupation="Designer");
    println!("{:08b} XOR {:08b} = {:08b}", 3i8, 32i8, 3i8 ^ 34i8);
    println!("Floating point number {:?}", 2.910210);
    println!("Hex: {:08X}, {:08x}", 131342112, 131342112);
    // TODO find out why this doesn't work:
    //println!("{0:08X}, {0:08x}", 7661);

    // variables
    let integer = 3i32;
    let floating_point = 2.1137;

    let mut u_integer = 3u32;
    //integer += 1; error: an immutable variable
    u_integer += 1;

    println!("{}, {}, {}", integer, floating_point, u_integer);
    // TODO find out why snake case instead of camel case

    // shadowing
    let first_var = 4;
    {
        let first_var = 51;
        println!("first_var = {}", first_var);
    }
    println!("first_var = {}", first_var);

    // unitialized variables
    let uninit_var;
    //println!("uninit_var = {}", uninit_var); error: use of an init variable
    uninit_var = 231.2;
    println!("already initialized uninit_var = {}", uninit_var);

    // type casting
    let a_integer = 0x40_u8;
    let a_char = a_integer as char;
    println!("char cast from integer {}: {}", a_integer, a_char);

    let a_float = 8.45511;
    println!("integer cast from float {}: {}", a_float, a_float as i32);

    println!("Binary represntation of {}: {:08b}", -1_i8, -1_i8);
    println!("Binary represntation of {}: {:08b}", -2_i8, -2_i8);

    // aliases
    type FloatingPoint32 = f32;
    let a_float_2 : FloatingPoint32 = 3 as f32;
    println!("Type alias: {}, size of var {}", a_float_2, std::mem::size_of_val(&a_float_2));

    // expressions
    let expr = {
        let x = 4.09;
        let y = 1.28;
        println!("x = {}, y = {}", x, y);
        x / y
    };
    println!("expr = {}", expr);

    // if-statement (every if-statement is an expression too, which is really a cool thing)
    let speed = 10;
    let mass = 890;
    let consumption =
        if speed < 0 {
            -1.0
        }
        else if speed == 0 {
            0.8
        }
        else if speed > 0 && speed < 10 {
            18.52
        }
        else if speed >= 10 && speed < 30 {
            let x = mass / speed;
            (x as f32) * 0.05
        }
        else {
            11.71
        };
        println!("Speed = {}, consumption = {}", speed, consumption);

        // loop
        let mut count = 0u32;
        loop {
            println!("loop iteration #{}", count);
            count += 1;
            if count > 9 {
            break;
            }
        }

        count = 0;
        while count < 10 {
            println!("while loop iteration #{}", count);
            count += 1;
        }

        for n in 0u32..10 {
            println!("for loop iteration #{}", n);
        }

        // matching
        let age = 19;
        match age {
            1  => println!("Seems like 1"),
            5  => println!("It's 5"),
            18 => println!("Exactly 18!"),
            _  => println!("I couldn't guess :("),
        }

        match age {
            a if a > 1 && a <= 9  => println!("The age is in range [1,9]"),
            a if a > 9 && a <= 19 => println!("The age is in range [10, 19]"),
            _                     => println!("Nothing, I don't know what range the age is in :("),
        }

        // the previous match is equivalent to the following:
        match age {
            a @ 1...9   => println!("The age is {} and in range [1,9]", a),
            a @ 10...19 => println!("The age is {} and in range [10, 19]", a),
            a           => println!("Nothing, I don't know what range the age {} is in :(", a),
        }

        // if let
        let a_some = Some(0.0008);
        if let Some(i) = a_some {
            println!("a_some is not None, {}", i);
            println!("result {}",  9.0 / i);
        }
        else {
            println!("None");
        }

        // while let
        let mut a_optional = Some(10);

        while let Some(i) = a_optional {
            if i == 20 {
                println!("while let: i equals 20, leave");
                a_optional = None;
            }
            else {
                a_optional = Some(i + 1);
            }
        }

        // functions, finally!
        let first_integer: i32 = -20;
        let second_integer: i32 = 8;
        let result_of_addition = add_two_integers(first_integer, second_integer);
        println!("{} + {} = {}", first_integer, second_integer, result_of_addition);

        simple_functions::print_hello_world();
        let mul_result = simple_functions::simple_math::multiple_two_integers(3, 15);
        println!("Modules: multiplication result = {}", mul_result);

        // this doesn't work.. why?
        println!("Modules: multiplication result 2 = {}", multiple_two_integers(-1, 8));

        // "super" and "self"
        sample_module::call_sample_module();

        // file hierarchy
        {
            let a : i32 = 4;
            let b : i32 = 15;
            println!("modules::math {} + {} = {}", a, b, modules::math::add_two_int(a, b));
        }

        // call external library
        my_extern_lib::run(5);

}

fn add_two_integers(a: i32, b: i32) -> i32 {
    a + b
}
<commit_msg>Progress: tuples and structs<commit_after>// library
extern crate my_extern_lib;

// modules
mod simple_functions {
    pub fn print_hello_world() {
        println!("Hello, World! (from the simple_functions module)");
     }

    // nested modules
    pub mod simple_math {
        pub fn multiple_two_integers(a: i32, b: i32) -> i32 {
            a * b
        }
    }
}

use simple_functions::simple_math::multiple_two_integers;

fn print_some_msg() {
    println!("Modules: printing from the outer function");
}

mod sample_module {

    pub fn call_sample_module() {
        use second_module::print_some_msg as print_second;
        use self::second_module::print_some_msg as print_second_sample;
        use super::print_some_msg as print_outside;
        print_outside();
        print_second();
        print_some_msg();
        print_second_sample();
    }

    mod second_module {

        pub fn print_some_msg() {
            println!("Modules: printing from the second module inside the sample module");
        }

    }

    fn print_some_msg() {
        println!("Modules: printing from the inside of the sample module");
    }

}

mod second_module {
    pub fn print_some_msg() {
        println!("Modules: printing from the second module");
    }
}

mod modules;

fn main() {

    // formatted output
    println!("Hello, Rust!");
    println!("Integer number = {}", 23);
    println!("Float number = {}", 1.012);
    println!("Repeat printing: {0}, {1}, {1}, {3}, {2}", 2, 1, 44, 9);
    println!("Named arguments: {name}, {age}, {occupation}", age="24", name="Ann", occupation="Designer");
    println!("{:08b} XOR {:08b} = {:08b}", 3i8, 32i8, 3i8 ^ 34i8);
    println!("Floating point number {:?}", 2.910210);
    println!("Hex: {:08X}, {:08x}", 131342112, 131342112);
    // TODO find out why this doesn't work:
    //println!("{0:08X}, {0:08x}", 7661);

    // variables
    let integer = 3i32;
    let floating_point = 2.1137;

    let mut u_integer = 3u32;
    //integer += 1; error: an immutable variable
    u_integer += 1;

    println!("{}, {}, {}", integer, floating_point, u_integer);
    // TODO find out why snake case instead of camel case

    // shadowing
    let first_var = 4;
    {
        let first_var = 51;
        println!("first_var = {}", first_var);
    }
    println!("first_var = {}", first_var);

    // unitialized variables
    let uninit_var;
    //println!("uninit_var = {}", uninit_var); error: use of an init variable
    uninit_var = 231.2;
    println!("already initialized uninit_var = {}", uninit_var);

    // type casting
    let a_integer = 0x40_u8;
    let a_char = a_integer as char;
    println!("char cast from integer {}: {}", a_integer, a_char);

    let a_float = 8.45511;
    println!("integer cast from float {}: {}", a_float, a_float as i32);

    println!("Binary represntation of {}: {:08b}", -1_i8, -1_i8);
    println!("Binary represntation of {}: {:08b}", -2_i8, -2_i8);

    // aliases
    type FloatingPoint32 = f32;
    let a_float_2 : FloatingPoint32 = 3 as f32;
    println!("Type alias: {}, size of var {}", a_float_2, std::mem::size_of_val(&a_float_2));

    // expressions
    let expr = {
        let x = 4.09;
        let y = 1.28;
        println!("x = {}, y = {}", x, y);
        x / y
    };
    println!("expr = {}", expr);

    // if-statement (every if-statement is an expression too, which is really a cool thing)
    let speed = 10;
    let mass = 890;
    let consumption =
        if speed < 0 {
            -1.0
        }
        else if speed == 0 {
            0.8
        }
        else if speed > 0 && speed < 10 {
            18.52
        }
        else if speed >= 10 && speed < 30 {
            let x = mass / speed;
            (x as f32) * 0.05
        }
        else {
            11.71
        };
        println!("Speed = {}, consumption = {}", speed, consumption);

        // loop
        let mut count = 0u32;
        loop {
            println!("loop iteration #{}", count);
            count += 1;
            if count > 9 {
            break;
            }
        }

        count = 0;
        while count < 10 {
            println!("while loop iteration #{}", count);
            count += 1;
        }

        for n in 0u32..10 {
            println!("for loop iteration #{}", n);
        }

        // matching
        let age = 19;
        match age {
            1  => println!("Seems like 1"),
            5  => println!("It's 5"),
            18 => println!("Exactly 18!"),
            _  => println!("I couldn't guess :("),
        }

        match age {
            a if a > 1 && a <= 9  => println!("The age is in range [1,9]"),
            a if a > 9 && a <= 19 => println!("The age is in range [10, 19]"),
            _                     => println!("Nothing, I don't know what range the age is in :("),
        }

        // the previous match is equivalent to the following:
        match age {
            a @ 1...9   => println!("The age is {} and in range [1,9]", a),
            a @ 10...19 => println!("The age is {} and in range [10, 19]", a),
            a           => println!("Nothing, I don't know what range the age {} is in :(", a),
        }

        // if let
        let a_some = Some(0.0008);
        if let Some(i) = a_some {
            println!("a_some is not None, {}", i);
            println!("result {}",  9.0 / i);
        }
        else {
            println!("None");
        }

        // while let
        let mut a_optional = Some(10);

        while let Some(i) = a_optional {
            if i == 20 {
                println!("while let: i equals 20, leave");
                a_optional = None;
            }
            else {
                a_optional = Some(i + 1);
            }
        }

        // functions, finally!
        let first_integer: i32 = -20;
        let second_integer: i32 = 8;
        let result_of_addition = add_two_integers(first_integer, second_integer);
        println!("{} + {} = {}", first_integer, second_integer, result_of_addition);

        simple_functions::print_hello_world();
        let mul_result = simple_functions::simple_math::multiple_two_integers(3, 15);
        println!("Modules: multiplication result = {}", mul_result);

        // this doesn't work.. why?
        println!("Modules: multiplication result 2 = {}", multiple_two_integers(-1, 8));

        // "super" and "self"
        sample_module::call_sample_module();

        // file hierarchy
        {
            let a : i32 = 4;
            let b : i32 = 15;
            println!("modules::math {} + {} = {}", a, b, modules::math::add_two_int(a, b));
        }

        // call external library
        my_extern_lib::run(5);

        // tuples
        let pair = ("key", 4);
        println!("tuple value: ({}, {})", pair.0, pair.1);
        println!("tuple value: {:?}", pair);

        // structs
        let bmw: Car = Car {color: "Blue".to_string(), weight: 940};
        println!("BMW: {} - {}", bmw.color, bmw.weight);

        // tuple structs
        let color_1: RgbColor = RgbColor(123, 33, 81);
        println!("RGB color: {}, {}, {}", color_1.0, color_1.1, color_1.2);

        // unit structs
        let _nil = Nil;

}

// a C-like struct
struct Car {
    color: String,
    weight: u32,
}

// a tuple struct s
struct RgbColor(i8, i8, i8);

// a unit struct
struct Nil;

fn add_two_integers(a: i32, b: i32) -> i32 {
    a + b
}
<|endoftext|>


<commit_before>#![no_std]
#![allow(ctypes)]

enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

fn range(lo: uint, hi: uint, it: |uint| -> ()) {
    let mut iter = lo;
    while iter < hi {
        it(iter);
        iter += 1;
    }
}

unsafe fn clear_screen(background: Color) {
    range(0, 80*25, |i| {
        *((0xb8000 + i * 2) as *mut u16) = (background as u16) << 12;
    });
}

#[no_mangle]
#[no_split_stack]
pub unsafe fn main() {
    clear_screen(LightRed);
}
<commit_msg>localize the unsafety, like a good rust citizen<commit_after>#![no_std]
#![allow(ctypes)]

enum Color {
    Black      = 0,
    Blue       = 1,
    Green      = 2,
    Cyan       = 3,
    Red        = 4,
    Pink       = 5,
    Brown      = 6,
    LightGray  = 7,
    DarkGray   = 8,
    LightBlue  = 9,
    LightGreen = 10,
    LightCyan  = 11,
    LightRed   = 12,
    LightPink  = 13,
    Yellow     = 14,
    White      = 15,
}

fn range(lo: uint, hi: uint, it: |uint| -> ()) {
    let mut iter = lo;
    while iter < hi {
        it(iter);
        iter += 1;
    }
}

fn clear_screen(background: Color) {
    range(0, 80*25, |i| {
        unsafe {
            *((0xb8000 + i * 2) as *mut u16) = (background as u16) << 12;
        }
    });
}

#[no_mangle]
#[no_split_stack]
pub fn main() {
    clear_screen(LightRed);
}
<|endoftext|>


<commit_before>use bson::{self, Bson};
use mongodb::{Client, ThreadedClient};
use mongodb::db::ThreadedDatabase;
use mongodb::db::options::CreateUserOptions;
use mongodb::db::roles::{AllDatabaseRole, SingleDatabaseRole, Role};

#[test]
fn create_collection() {
    let client = Client::connect("localhost", 27017).unwrap();
    let db = client.db("create_collection");
    db.drop_database().unwrap();

    // Build collections
    db.create_collection("test1", None).unwrap();
    db.create_collection("test2", None).unwrap();

    // Check for namespaces
    let mut cursor = db.list_collections_with_batch_size(None, 1)
        .expect("Failed to execute list_collections command.");

    let results = cursor.next_n(5).unwrap();

    let v3_0 = cfg!(feature = "mongodb_3_0");
    let result_size = if v3_0 { 3 } else { 2 };
    assert_eq!(result_size, results.len());

    if v3_0 {
        match results[0].get("name") {
            Some(&Bson::String(ref name)) => assert_eq!("system.indexes", name),
            _ => panic!("Expected BSON string!"),
        }
    }

    match results[result_size - 2].get("name") {
        Some(&Bson::String(ref name)) => assert_eq!("test1", name),
        _ => panic!("Expected BSON string!"),
    }
    match results[result_size - 1].get("name") {
        Some(&Bson::String(ref name)) => assert_eq!("test2", name),
        _ => panic!("Expected BSON string!"),
    }
}

#[test]
fn list_collections() {
    let client = Client::connect("localhost", 27017).unwrap();
    let db = client.db("list_collections");

    db.drop_database().expect("Failed to drop database");

    // Build collections
    db.collection("test")
        .insert_one(bson::Document::new(), None)
        .expect("Failed to insert placeholder document into collection");
    db.collection("test2")
        .insert_one(bson::Document::new(), None)
        .expect("Failed to insert placeholder document into collection");

    // Check for namespaces
    let mut cursor = db.list_collections_with_batch_size(None, 1)
        .expect("Failed to execute list_collections command.");

    let results = cursor.next_n(5).unwrap();

    let v3_0 = cfg!(feature = "mongodb_3_0");
    let result_size = if v3_0 { 3 } else { 2 };
    assert_eq!(result_size, results.len());

    if v3_0 {
        match results[0].get("name") {
            Some(&Bson::String(ref name)) => assert_eq!("system.indexes", name),
            _ => panic!("Expected BSON string!"),
        };
    }

    match results[result_size - 2].get("name") {
        Some(&Bson::String(ref name)) => assert_eq!("test", name),
        _ => panic!("Expected BSON string!"),
    };

    match results[result_size - 1].get("name") {
        Some(&Bson::String(ref name)) => assert_eq!("test2", name),
        _ => panic!("Expected BSON string!"),
    }
}

#[test]
fn create_and_get_users() {
    let client = Client::connect("localhost", 27017).unwrap();
    let db = client.db("create_and_get_users");
    db.drop_database().unwrap();
    db.drop_all_users(None).unwrap();

    let saghm_options = CreateUserOptions {
        custom_data: Some(doc! { "foo" => "bar" }),
        roles: vec![Role::Single {
                        role: SingleDatabaseRole::DbAdmin,
                        db: String::from("test"),
                    },
                    Role::All(AllDatabaseRole::ReadWrite)],
        write_concern: None,
    };

    db.create_user("saghm", "ilikepuns!", Some(saghm_options)).unwrap();

    let kevin_options = CreateUserOptions {
        custom_data: None,
        roles: vec![Role::All(AllDatabaseRole::Read)],
        write_concern: None,
    };

    db.create_user("kevin",
                     "ihavenosenseofhumorandthereforeihatepuns!",
                     Some(kevin_options))
        .unwrap();
    db.create_user("val", "ilikeangularjs!", None).unwrap();

    let user = db.get_user("saghm", None).unwrap();

    match user.get("db") {
        Some(&Bson::String(ref s)) => assert_eq!("create_and_get_users", s),
        _ => {
            panic!("Invalid `db` specified for user 'saghm': {:?}",
                   user.get("db"))
        }
    };

    let data = match user.get("customData") {
        Some(&Bson::Document(ref d)) => d.clone(),
        _ => panic!("Invalid `customData` specified for user 'saghm'"),
    };

    match data.get("foo") {
        Some(&Bson::String(ref s)) => assert_eq!("bar", s),
        _ => panic!("Invalid custom data for user 'saghm': {}", data),
    };

    let users = db.get_users(vec!["kevin", "val"], None).unwrap();
    assert_eq!(users.len(), 2 as usize);

    match users[0].get("user") {
        Some(&Bson::String(ref s)) => assert_eq!("kevin", s),
        _ => panic!("User isn't named 'kevin' but should be"),
    };

    match users[1].get("user") {
        Some(&Bson::String(ref s)) => assert_eq!("val", s),
        _ => panic!("User isn't named 'val' but should be"),
    };

    let users = db.get_all_users(false).unwrap();

    assert_eq!(users.len(), 3);

    match users[0].get("user") {
        Some(&Bson::String(ref s)) => assert_eq!("saghm", s),
        _ => panic!("User isn't named 'saghm' but should be"),
    };

    match users[1].get("user") {
        Some(&Bson::String(ref s)) => assert_eq!("kevin", s),
        _ => panic!("User isn't named 'kevin' but should be"),
    };

    match users[2].get("user") {
        Some(&Bson::String(ref s)) => assert_eq!("val", s),
        _ => panic!("User isn't named 'val' but should be"),
    };
}
<commit_msg>add simple versioning test<commit_after>use bson::{self, Bson};
use mongodb::{Client, ThreadedClient};
use mongodb::db::ThreadedDatabase;
use mongodb::db::options::CreateUserOptions;
use mongodb::db::roles::{AllDatabaseRole, SingleDatabaseRole, Role};

#[test]
fn create_collection() {
    let client = Client::connect("localhost", 27017).unwrap();
    let db = client.db("create_collection");
    db.drop_database().unwrap();

    // Build collections
    db.create_collection("test1", None).unwrap();
    db.create_collection("test2", None).unwrap();

    // Check for namespaces
    let mut cursor = db.list_collections_with_batch_size(None, 1)
        .expect("Failed to execute list_collections command.");

    let results = cursor.next_n(5).unwrap();

    let v3_0 = cfg!(feature = "mongodb_3_0");
    let result_size = if v3_0 { 3 } else { 2 };
    assert_eq!(result_size, results.len());

    if v3_0 {
        match results[0].get("name") {
            Some(&Bson::String(ref name)) => assert_eq!("system.indexes", name),
            _ => panic!("Expected BSON string!"),
        }
    }

    match results[result_size - 2].get("name") {
        Some(&Bson::String(ref name)) => assert_eq!("test1", name),
        _ => panic!("Expected BSON string!"),
    }
    match results[result_size - 1].get("name") {
        Some(&Bson::String(ref name)) => assert_eq!("test2", name),
        _ => panic!("Expected BSON string!"),
    }
}

#[test]
fn list_collections() {
    let client = Client::connect("localhost", 27017).unwrap();
    let db = client.db("list_collections");

    db.drop_database().expect("Failed to drop database");

    // Build collections
    db.collection("test")
        .insert_one(bson::Document::new(), None)
        .expect("Failed to insert placeholder document into collection");
    db.collection("test2")
        .insert_one(bson::Document::new(), None)
        .expect("Failed to insert placeholder document into collection");

    // Check for namespaces
    let mut cursor = db.list_collections_with_batch_size(None, 1)
        .expect("Failed to execute list_collections command.");

    let results = cursor.next_n(5).unwrap();

    let v3_0 = cfg!(feature = "mongodb_3_0");
    let result_size = if v3_0 { 3 } else { 2 };
    assert_eq!(result_size, results.len());

    if v3_0 {
        match results[0].get("name") {
            Some(&Bson::String(ref name)) => assert_eq!("system.indexes", name),
            _ => panic!("Expected BSON string!"),
        };
    }

    match results[result_size - 2].get("name") {
        Some(&Bson::String(ref name)) => assert_eq!("test", name),
        _ => panic!("Expected BSON string!"),
    };

    match results[result_size - 1].get("name") {
        Some(&Bson::String(ref name)) => assert_eq!("test2", name),
        _ => panic!("Expected BSON string!"),
    }
}

#[test]
fn create_and_get_users() {
    let client = Client::connect("localhost", 27017).unwrap();
    let db = client.db("create_and_get_users");
    db.drop_database().unwrap();
    db.drop_all_users(None).unwrap();

    let saghm_options = CreateUserOptions {
        custom_data: Some(doc! { "foo" => "bar" }),
        roles: vec![Role::Single {
                        role: SingleDatabaseRole::DbAdmin,
                        db: String::from("test"),
                    },
                    Role::All(AllDatabaseRole::ReadWrite)],
        write_concern: None,
    };

    db.create_user("saghm", "ilikepuns!", Some(saghm_options)).unwrap();

    let kevin_options = CreateUserOptions {
        custom_data: None,
        roles: vec![Role::All(AllDatabaseRole::Read)],
        write_concern: None,
    };

    db.create_user("kevin",
                     "ihavenosenseofhumorandthereforeihatepuns!",
                     Some(kevin_options))
        .unwrap();
    db.create_user("val", "ilikeangularjs!", None).unwrap();

    let user = db.get_user("saghm", None).unwrap();

    match user.get("db") {
        Some(&Bson::String(ref s)) => assert_eq!("create_and_get_users", s),
        _ => {
            panic!("Invalid `db` specified for user 'saghm': {:?}",
                   user.get("db"))
        }
    };

    let data = match user.get("customData") {
        Some(&Bson::Document(ref d)) => d.clone(),
        _ => panic!("Invalid `customData` specified for user 'saghm'"),
    };

    match data.get("foo") {
        Some(&Bson::String(ref s)) => assert_eq!("bar", s),
        _ => panic!("Invalid custom data for user 'saghm': {}", data),
    };

    let users = db.get_users(vec!["kevin", "val"], None).unwrap();
    assert_eq!(users.len(), 2 as usize);

    match users[0].get("user") {
        Some(&Bson::String(ref s)) => assert_eq!("kevin", s),
        _ => panic!("User isn't named 'kevin' but should be"),
    };

    match users[1].get("user") {
        Some(&Bson::String(ref s)) => assert_eq!("val", s),
        _ => panic!("User isn't named 'val' but should be"),
    };

    let users = db.get_all_users(false).unwrap();

    assert_eq!(users.len(), 3);

    match users[0].get("user") {
        Some(&Bson::String(ref s)) => assert_eq!("saghm", s),
        _ => panic!("User isn't named 'saghm' but should be"),
    };

    match users[1].get("user") {
        Some(&Bson::String(ref s)) => assert_eq!("kevin", s),
        _ => panic!("User isn't named 'kevin' but should be"),
    };

    match users[2].get("user") {
        Some(&Bson::String(ref s)) => assert_eq!("val", s),
        _ => panic!("User isn't named 'val' but should be"),
    };
}

#[test]
fn get_version() {
    let client = Client::connect("localhost", 27017).unwrap();
    let db = client.db("create_and_get_users");
    let version = db.version().unwrap();
}
<|endoftext|>


<commit_before>//! Diagnostic reporting support for the codespan crate.

#[cfg(feature = "serialization")]
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use termcolor::ColorChoice;

mod diagnostic;
mod emitter;

pub use termcolor;

pub use self::diagnostic::{Diagnostic, Label, Severity};
pub use self::emitter::{emit, Config};

/// A command line argument that configures the coloring of the output.
///
/// This can be used with command line argument parsers like `clap` or `structopt`.
///
/// # Example
///
/// ```rust
/// use structopt::StructOpt;
/// use codespan_reporting::termcolor::StandardStream;
/// use codespan_reporting::ColorArg;
///
/// #[derive(Debug, StructOpt)]
/// #[structopt(name = "groovey-app")]
/// pub struct Opts {
///     /// Configure coloring of output
///     #[structopt(
///         long = "color",
///         parse(try_from_str),
///         default_value = "auto",
///         raw(possible_values = "ColorArg::VARIANTS", case_insensitive = "true")
///     )]
///     pub color: ColorArg,
/// }
///
/// fn main() {
///     let opts = Opts::from_args();
///     let writer = StandardStream::stderr(opts.color.into());
/// }
/// ```
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ColorArg(pub ColorChoice);

impl ColorArg {
    /// Allowed values the argument.
    ///
    /// This is useful for generating documentation via `clap` or `structopt`'s
    /// `possible_values` configuration.
    pub const VARIANTS: &'static [&'static str] = &["auto", "always", "ansi", "never"];
}

impl FromStr for ColorArg {
    type Err = &'static str;

    fn from_str(src: &str) -> Result<ColorArg, &'static str> {
        match src {
            _ if src.eq_ignore_ascii_case("auto") => Ok(ColorArg(ColorChoice::Auto)),
            _ if src.eq_ignore_ascii_case("always") => Ok(ColorArg(ColorChoice::Always)),
            _ if src.eq_ignore_ascii_case("ansi") => Ok(ColorArg(ColorChoice::AlwaysAnsi)),
            _ if src.eq_ignore_ascii_case("never") => Ok(ColorArg(ColorChoice::Never)),
            _ => Err("valid values: auto, always, ansi, never"),
        }
    }
}

impl Into<ColorChoice> for ColorArg {
    fn into(self) -> ColorChoice {
        self.0
    }
}
<commit_msg>Remove unused import<commit_after>//! Diagnostic reporting support for the codespan crate.

use std::str::FromStr;
use termcolor::ColorChoice;

mod diagnostic;
mod emitter;

pub use termcolor;

pub use self::diagnostic::{Diagnostic, Label, Severity};
pub use self::emitter::{emit, Config};

/// A command line argument that configures the coloring of the output.
///
/// This can be used with command line argument parsers like `clap` or `structopt`.
///
/// # Example
///
/// ```rust
/// use structopt::StructOpt;
/// use codespan_reporting::termcolor::StandardStream;
/// use codespan_reporting::ColorArg;
///
/// #[derive(Debug, StructOpt)]
/// #[structopt(name = "groovey-app")]
/// pub struct Opts {
///     /// Configure coloring of output
///     #[structopt(
///         long = "color",
///         parse(try_from_str),
///         default_value = "auto",
///         raw(possible_values = "ColorArg::VARIANTS", case_insensitive = "true")
///     )]
///     pub color: ColorArg,
/// }
///
/// fn main() {
///     let opts = Opts::from_args();
///     let writer = StandardStream::stderr(opts.color.into());
/// }
/// ```
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ColorArg(pub ColorChoice);

impl ColorArg {
    /// Allowed values the argument.
    ///
    /// This is useful for generating documentation via `clap` or `structopt`'s
    /// `possible_values` configuration.
    pub const VARIANTS: &'static [&'static str] = &["auto", "always", "ansi", "never"];
}

impl FromStr for ColorArg {
    type Err = &'static str;

    fn from_str(src: &str) -> Result<ColorArg, &'static str> {
        match src {
            _ if src.eq_ignore_ascii_case("auto") => Ok(ColorArg(ColorChoice::Auto)),
            _ if src.eq_ignore_ascii_case("always") => Ok(ColorArg(ColorChoice::Always)),
            _ if src.eq_ignore_ascii_case("ansi") => Ok(ColorArg(ColorChoice::AlwaysAnsi)),
            _ if src.eq_ignore_ascii_case("never") => Ok(ColorArg(ColorChoice::Never)),
            _ => Err("valid values: auto, always, ansi, never"),
        }
    }
}

impl Into<ColorChoice> for ColorArg {
    fn into(self) -> ColorChoice {
        self.0
    }
}
<|endoftext|>