<commit_before>use crate::builders::{CrateBuilder, PublishBuilder};
use crate::util::{RequestHelper, TestApp};
use crate::OkBool;
use http::StatusCode;

impl crate::util::MockTokenUser {
    /// Yank the specified version of the specified crate and run all pending background jobs
    fn yank(&self, krate_name: &str, version: &str) -> crate::util::Response<OkBool> {
        let url = format!("/api/v1/crates/{}/{}/yank", krate_name, version);
        let response = self.delete(&url);
        self.app().run_pending_background_jobs();
        response
    }

    /// Unyank the specified version of the specified crate and run all pending background jobs
    fn unyank(&self, krate_name: &str, version: &str) -> crate::util::Response<OkBool> {
        let url = format!("/api/v1/crates/{}/{}/unyank", krate_name, version);
        let response = self.put(&url, &[]);
        self.app().run_pending_background_jobs();
        response
    }
}

impl crate::util::MockCookieUser {
    /// Yank the specified version of the specified crate and run all pending background jobs
    fn yank(&self, krate_name: &str, version: &str) -> crate::util::Response<OkBool> {
        let url = format!("/api/v1/crates/{}/{}/yank", krate_name, version);
        let response = self.delete(&url);
        self.app().run_pending_background_jobs();
        response
    }

    /// Unyank the specified version of the specified crate and run all pending background jobs
    fn unyank(&self, krate_name: &str, version: &str) -> crate::util::Response<OkBool> {
        let url = format!("/api/v1/crates/{}/{}/unyank", krate_name, version);
        let response = self.put(&url, &[]);
        self.app().run_pending_background_jobs();
        response
    }
}

#[test]
#[allow(clippy::bool_assert_comparison)] // for claim::assert_some_eq! with bool
fn yank_works_as_intended() {
    let (app, anon, cookie, token) = TestApp::full().with_token();

    // Upload a new crate, putting it in the git index
    let crate_to_publish = PublishBuilder::new("fyk");
    token.enqueue_publish(crate_to_publish).good();
    app.run_pending_background_jobs();

    let crates = app.crates_from_index_head("3/f/fyk");
    assert_eq!(crates.len(), 1);
    assert_some_eq!(crates[0].yanked, false);

    // make sure it's not yanked
    let json = anon.show_version("fyk", "1.0.0");
    assert!(!json.version.yanked);

    // yank it
    token.yank("fyk", "1.0.0").good();

    let crates = app.crates_from_index_head("3/f/fyk");
    assert_eq!(crates.len(), 1);
    assert_some_eq!(crates[0].yanked, true);

    let json = anon.show_version("fyk", "1.0.0");
    assert!(json.version.yanked);

    // un-yank it
    token.unyank("fyk", "1.0.0").good();

    let crates = app.crates_from_index_head("3/f/fyk");
    assert_eq!(crates.len(), 1);
    assert_some_eq!(crates[0].yanked, false);

    let json = anon.show_version("fyk", "1.0.0");
    assert!(!json.version.yanked);

    // yank it
    cookie.yank("fyk", "1.0.0").good();

    let crates = app.crates_from_index_head("3/f/fyk");
    assert_eq!(crates.len(), 1);
    assert_some_eq!(crates[0].yanked, true);

    let json = anon.show_version("fyk", "1.0.0");
    assert!(json.version.yanked);

    // un-yank it
    cookie.unyank("fyk", "1.0.0").good();

    let crates = app.crates_from_index_head("3/f/fyk");
    assert_eq!(crates.len(), 1);
    assert_some_eq!(crates[0].yanked, false);

    let json = anon.show_version("fyk", "1.0.0");
    assert!(!json.version.yanked);
}

#[test]
fn yank_by_a_non_owner_fails() {
    let (app, _, _, token) = TestApp::full().with_token();

    let another_user = app.db_new_user("bar");
    let another_user = another_user.as_model();
    app.db(|conn| {
        CrateBuilder::new("foo_not", another_user.id)
            .version("1.0.0")
            .expect_build(conn);
    });

    let response = token.yank("foo_not", "1.0.0");
    assert_eq!(response.status(), StatusCode::OK);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "must already be an owner to yank or unyank" }] })
    );
}

#[test]
fn yank_max_version() {
    let (_, anon, _, token) = TestApp::full().with_token();

    // Upload a new crate
    let crate_to_publish = PublishBuilder::new("fyk_max");
    token.enqueue_publish(crate_to_publish).good();

    // double check the max version
    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "1.0.0");

    // add version 2.0.0
    let crate_to_publish = PublishBuilder::new("fyk_max").version("2.0.0");
    let json = token.enqueue_publish(crate_to_publish).good();
    assert_eq!(json.krate.max_version, "2.0.0");

    // yank version 1.0.0
    token.yank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "2.0.0");

    // unyank version 1.0.0
    token.unyank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "2.0.0");

    // yank version 2.0.0
    token.yank("fyk_max", "2.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "1.0.0");

    // yank version 1.0.0
    token.yank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "0.0.0");

    // unyank version 2.0.0
    token.unyank("fyk_max", "2.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "2.0.0");

    // unyank version 1.0.0
    token.unyank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "2.0.0");
}

#[test]
fn publish_after_yank_max_version() {
    let (_, anon, _, token) = TestApp::full().with_token();

    // Upload a new crate
    let crate_to_publish = PublishBuilder::new("fyk_max");
    token.enqueue_publish(crate_to_publish).good();

    // double check the max version
    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "1.0.0");

    // yank version 1.0.0
    token.yank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "0.0.0");

    // add version 2.0.0
    let crate_to_publish = PublishBuilder::new("fyk_max").version("2.0.0");
    let json = token.enqueue_publish(crate_to_publish).good();
    assert_eq!(json.krate.max_version, "2.0.0");

    // unyank version 1.0.0
    token.unyank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "2.0.0");
}

#[test]
fn yank_records_an_audit_action() {
    let (_, anon, _, token) = TestApp::full().with_token();

    // Upload a new crate, putting it in the git index
    let crate_to_publish = PublishBuilder::new("fyk");
    token.enqueue_publish(crate_to_publish).good();

    // Yank it
    token.yank("fyk", "1.0.0").good();

    // Make sure it has one publish and one yank audit action
    let json = anon.show_version("fyk", "1.0.0");
    let actions = json.version.audit_actions;

    assert_eq!(actions.len(), 2);
    let action = &actions[1];
    assert_eq!(action.action, "yank");
    assert_eq!(action.user.id, token.as_model().user_id);
}

#[test]
fn unyank_records_an_audit_action() {
    let (_, anon, _, token) = TestApp::full().with_token();

    // Upload a new crate
    let crate_to_publish = PublishBuilder::new("fyk");
    token.enqueue_publish(crate_to_publish).good();

    // Yank version 1.0.0
    token.yank("fyk", "1.0.0").good();

    // Unyank version 1.0.0
    token.unyank("fyk", "1.0.0").good();

    // Make sure it has one publish, one yank, and one unyank audit action
    let json = anon.show_version("fyk", "1.0.0");
    let actions = json.version.audit_actions;

    assert_eq!(actions.len(), 3);
    let action = &actions[2];
    assert_eq!(action.action, "unyank");
    assert_eq!(action.user.id, token.as_model().user_id);
}
<commit_msg>Fix clippy error on stable due to unknown lint<commit_after>use crate::builders::{CrateBuilder, PublishBuilder};
use crate::util::{RequestHelper, TestApp};
use crate::OkBool;
use http::StatusCode;

impl crate::util::MockTokenUser {
    /// Yank the specified version of the specified crate and run all pending background jobs
    fn yank(&self, krate_name: &str, version: &str) -> crate::util::Response<OkBool> {
        let url = format!("/api/v1/crates/{}/{}/yank", krate_name, version);
        let response = self.delete(&url);
        self.app().run_pending_background_jobs();
        response
    }

    /// Unyank the specified version of the specified crate and run all pending background jobs
    fn unyank(&self, krate_name: &str, version: &str) -> crate::util::Response<OkBool> {
        let url = format!("/api/v1/crates/{}/{}/unyank", krate_name, version);
        let response = self.put(&url, &[]);
        self.app().run_pending_background_jobs();
        response
    }
}

impl crate::util::MockCookieUser {
    /// Yank the specified version of the specified crate and run all pending background jobs
    fn yank(&self, krate_name: &str, version: &str) -> crate::util::Response<OkBool> {
        let url = format!("/api/v1/crates/{}/{}/yank", krate_name, version);
        let response = self.delete(&url);
        self.app().run_pending_background_jobs();
        response
    }

    /// Unyank the specified version of the specified crate and run all pending background jobs
    fn unyank(&self, krate_name: &str, version: &str) -> crate::util::Response<OkBool> {
        let url = format!("/api/v1/crates/{}/{}/unyank", krate_name, version);
        let response = self.put(&url, &[]);
        self.app().run_pending_background_jobs();
        response
    }
}

#[test]
#[allow(unknown_lints, clippy::bool_assert_comparison)] // for claim::assert_some_eq! with bool
fn yank_works_as_intended() {
    let (app, anon, cookie, token) = TestApp::full().with_token();

    // Upload a new crate, putting it in the git index
    let crate_to_publish = PublishBuilder::new("fyk");
    token.enqueue_publish(crate_to_publish).good();
    app.run_pending_background_jobs();

    let crates = app.crates_from_index_head("3/f/fyk");
    assert_eq!(crates.len(), 1);
    assert_some_eq!(crates[0].yanked, false);

    // make sure it's not yanked
    let json = anon.show_version("fyk", "1.0.0");
    assert!(!json.version.yanked);

    // yank it
    token.yank("fyk", "1.0.0").good();

    let crates = app.crates_from_index_head("3/f/fyk");
    assert_eq!(crates.len(), 1);
    assert_some_eq!(crates[0].yanked, true);

    let json = anon.show_version("fyk", "1.0.0");
    assert!(json.version.yanked);

    // un-yank it
    token.unyank("fyk", "1.0.0").good();

    let crates = app.crates_from_index_head("3/f/fyk");
    assert_eq!(crates.len(), 1);
    assert_some_eq!(crates[0].yanked, false);

    let json = anon.show_version("fyk", "1.0.0");
    assert!(!json.version.yanked);

    // yank it
    cookie.yank("fyk", "1.0.0").good();

    let crates = app.crates_from_index_head("3/f/fyk");
    assert_eq!(crates.len(), 1);
    assert_some_eq!(crates[0].yanked, true);

    let json = anon.show_version("fyk", "1.0.0");
    assert!(json.version.yanked);

    // un-yank it
    cookie.unyank("fyk", "1.0.0").good();

    let crates = app.crates_from_index_head("3/f/fyk");
    assert_eq!(crates.len(), 1);
    assert_some_eq!(crates[0].yanked, false);

    let json = anon.show_version("fyk", "1.0.0");
    assert!(!json.version.yanked);
}

#[test]
fn yank_by_a_non_owner_fails() {
    let (app, _, _, token) = TestApp::full().with_token();

    let another_user = app.db_new_user("bar");
    let another_user = another_user.as_model();
    app.db(|conn| {
        CrateBuilder::new("foo_not", another_user.id)
            .version("1.0.0")
            .expect_build(conn);
    });

    let response = token.yank("foo_not", "1.0.0");
    assert_eq!(response.status(), StatusCode::OK);
    assert_eq!(
        response.json(),
        json!({ "errors": [{ "detail": "must already be an owner to yank or unyank" }] })
    );
}

#[test]
fn yank_max_version() {
    let (_, anon, _, token) = TestApp::full().with_token();

    // Upload a new crate
    let crate_to_publish = PublishBuilder::new("fyk_max");
    token.enqueue_publish(crate_to_publish).good();

    // double check the max version
    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "1.0.0");

    // add version 2.0.0
    let crate_to_publish = PublishBuilder::new("fyk_max").version("2.0.0");
    let json = token.enqueue_publish(crate_to_publish).good();
    assert_eq!(json.krate.max_version, "2.0.0");

    // yank version 1.0.0
    token.yank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "2.0.0");

    // unyank version 1.0.0
    token.unyank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "2.0.0");

    // yank version 2.0.0
    token.yank("fyk_max", "2.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "1.0.0");

    // yank version 1.0.0
    token.yank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "0.0.0");

    // unyank version 2.0.0
    token.unyank("fyk_max", "2.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "2.0.0");

    // unyank version 1.0.0
    token.unyank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "2.0.0");
}

#[test]
fn publish_after_yank_max_version() {
    let (_, anon, _, token) = TestApp::full().with_token();

    // Upload a new crate
    let crate_to_publish = PublishBuilder::new("fyk_max");
    token.enqueue_publish(crate_to_publish).good();

    // double check the max version
    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "1.0.0");

    // yank version 1.0.0
    token.yank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "0.0.0");

    // add version 2.0.0
    let crate_to_publish = PublishBuilder::new("fyk_max").version("2.0.0");
    let json = token.enqueue_publish(crate_to_publish).good();
    assert_eq!(json.krate.max_version, "2.0.0");

    // unyank version 1.0.0
    token.unyank("fyk_max", "1.0.0").good();

    let json = anon.show_crate("fyk_max");
    assert_eq!(json.krate.max_version, "2.0.0");
}

#[test]
fn yank_records_an_audit_action() {
    let (_, anon, _, token) = TestApp::full().with_token();

    // Upload a new crate, putting it in the git index
    let crate_to_publish = PublishBuilder::new("fyk");
    token.enqueue_publish(crate_to_publish).good();

    // Yank it
    token.yank("fyk", "1.0.0").good();

    // Make sure it has one publish and one yank audit action
    let json = anon.show_version("fyk", "1.0.0");
    let actions = json.version.audit_actions;

    assert_eq!(actions.len(), 2);
    let action = &actions[1];
    assert_eq!(action.action, "yank");
    assert_eq!(action.user.id, token.as_model().user_id);
}

#[test]
fn unyank_records_an_audit_action() {
    let (_, anon, _, token) = TestApp::full().with_token();

    // Upload a new crate
    let crate_to_publish = PublishBuilder::new("fyk");
    token.enqueue_publish(crate_to_publish).good();

    // Yank version 1.0.0
    token.yank("fyk", "1.0.0").good();

    // Unyank version 1.0.0
    token.unyank("fyk", "1.0.0").good();

    // Make sure it has one publish, one yank, and one unyank audit action
    let json = anon.show_version("fyk", "1.0.0");
    let actions = json.version.audit_actions;

    assert_eq!(actions.len(), 3);
    let action = &actions[2];
    assert_eq!(action.action, "unyank");
    assert_eq!(action.user.id, token.as_model().user_id);
}
<|endoftext|>


<commit_before>use std;
use std::fmt;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SpotifyAudioType {
    Track,
    Podcast,
    NonPlayable,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SpotifyId {
    pub id: u128,
    pub audio_type: SpotifyAudioType,
}

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

const BASE62_DIGITS: &'static [u8] =
    b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const BASE16_DIGITS: &'static [u8] = b"0123456789abcdef";

impl SpotifyId {
    fn as_track(n: u128) -> SpotifyId {
        SpotifyId {
            id: n.to_owned(),
            audio_type: SpotifyAudioType::Track,
        }
    }

    pub fn from_base16(id: &str) -> Result<SpotifyId, SpotifyIdError> {
        let data = id.as_bytes();

        let mut n = 0u128;
        for c in data {
            let d = match BASE16_DIGITS.iter().position(|e| e == c) {
                None => return Err(SpotifyIdError),
                Some(x) => x as u128,
            };
            n = n * 16;
            n = n + d;
        }

        Ok(SpotifyId::as_track(n))
    }

    pub fn from_base62(id: &str) -> Result<SpotifyId, SpotifyIdError> {
        let data = id.as_bytes();

        let mut n = 0u128;
        for c in data {
            let d = match BASE62_DIGITS.iter().position(|e| e == c) {
                None => return Err(SpotifyIdError),
                Some(x) => x as u128,
            };
            n = n * 62;
            n = n + d;
        }
        Ok(SpotifyId::as_track(n))
    }

    pub fn from_raw(data: &[u8]) -> Result<SpotifyId, SpotifyIdError> {
        if data.len() != 16 {
            return Err(SpotifyIdError);
        };

        let mut arr: [u8; 16] = Default::default();
        arr.copy_from_slice(&data[0..16]);

        Ok(SpotifyId::as_track(u128::from_be_bytes(arr)))
    }

    pub fn from_uri(uri: &str) -> Result<SpotifyId, SpotifyIdError> {
        let parts = uri.split(":").collect::<Vec<&str>>();
        let gid = parts.last().unwrap();
        if uri.contains(":episode:") {
            let mut spotify_id = SpotifyId::from_base62(gid).unwrap();
            let _ = std::mem::replace(&mut spotify_id.audio_type, SpotifyAudioType::Podcast);
            Ok(spotify_id)
        } else if uri.contains(":track:") {
            SpotifyId::from_base62(gid)
        } else {
            // show/playlist/artist/album/??
            let mut spotify_id = SpotifyId::from_base62(gid).unwrap();
            let _ = std::mem::replace(&mut spotify_id.audio_type, SpotifyAudioType::NonPlayable);
            Ok(spotify_id)
        }
    }

    pub fn to_base16(&self) -> String {
        format!("{:032x}", self.id)
    }

    pub fn to_base62(&self) -> String {
        let &SpotifyId { id: mut n, .. } = self;

        let mut data = [0u8; 22];
        for i in 0..22 {
            data[21 - i] = BASE62_DIGITS[(n % 62) as usize];
            n /= 62;
        }

        std::str::from_utf8(&data).unwrap().to_owned()
    }

    pub fn to_uri(&self) -> String {
        match self.audio_type {
            SpotifyAudioType::Track => {
                format!("spotify:track:{}", self.to_base62())
            }
            SpotifyAudioType::Podcast => {
                format!("spotify:episode:{}", self.to_base62())
            }
            SpotifyAudioType::NonPlayable => {
                format!("spotify:unknown:{}", self.to_base62())
            }
        }
    }

    pub fn to_raw(&self) -> [u8; 16] {
        self.id.to_be_bytes()
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileId(pub [u8; 20]);

impl FileId {
    pub fn to_base16(&self) -> String {
        self.0
            .iter()
            .map(|b| format!("{:02x}", b))
            .collect::<Vec<String>>()
            .concat()
    }
}

impl fmt::Debug for FileId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("FileId").field(&self.to_base16()).finish()
    }
}

impl fmt::Display for FileId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.to_base16())
    }
}
<commit_msg>Fixed formatting<commit_after>use std;
use std::fmt;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SpotifyAudioType {
    Track,
    Podcast,
    NonPlayable,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SpotifyId {
    pub id: u128,
    pub audio_type: SpotifyAudioType,
}

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

const BASE62_DIGITS: &'static [u8] =
    b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const BASE16_DIGITS: &'static [u8] = b"0123456789abcdef";

impl SpotifyId {
    fn as_track(n: u128) -> SpotifyId {
        SpotifyId {
            id: n.to_owned(),
            audio_type: SpotifyAudioType::Track,
        }
    }

    pub fn from_base16(id: &str) -> Result<SpotifyId, SpotifyIdError> {
        let data = id.as_bytes();

        let mut n = 0u128;
        for c in data {
            let d = match BASE16_DIGITS.iter().position(|e| e == c) {
                None => return Err(SpotifyIdError),
                Some(x) => x as u128,
            };
            n = n * 16;
            n = n + d;
        }

        Ok(SpotifyId::as_track(n))
    }

    pub fn from_base62(id: &str) -> Result<SpotifyId, SpotifyIdError> {
        let data = id.as_bytes();

        let mut n = 0u128;
        for c in data {
            let d = match BASE62_DIGITS.iter().position(|e| e == c) {
                None => return Err(SpotifyIdError),
                Some(x) => x as u128,
            };
            n = n * 62;
            n = n + d;
        }
        Ok(SpotifyId::as_track(n))
    }

    pub fn from_raw(data: &[u8]) -> Result<SpotifyId, SpotifyIdError> {
        if data.len() != 16 {
            return Err(SpotifyIdError);
        };

        let mut arr: [u8; 16] = Default::default();
        arr.copy_from_slice(&data[0..16]);

        Ok(SpotifyId::as_track(u128::from_be_bytes(arr)))
    }

    pub fn from_uri(uri: &str) -> Result<SpotifyId, SpotifyIdError> {
        let parts = uri.split(":").collect::<Vec<&str>>();
        let gid = parts.last().unwrap();
        if uri.contains(":episode:") {
            let mut spotify_id = SpotifyId::from_base62(gid).unwrap();
            let _ = std::mem::replace(&mut spotify_id.audio_type, SpotifyAudioType::Podcast);
            Ok(spotify_id)
        } else if uri.contains(":track:") {
            SpotifyId::from_base62(gid)
        } else {
            // show/playlist/artist/album/??
            let mut spotify_id = SpotifyId::from_base62(gid).unwrap();
            let _ = std::mem::replace(&mut spotify_id.audio_type, SpotifyAudioType::NonPlayable);
            Ok(spotify_id)
        }
    }

    pub fn to_base16(&self) -> String {
        format!("{:032x}", self.id)
    }

    pub fn to_base62(&self) -> String {
        let &SpotifyId { id: mut n, .. } = self;

        let mut data = [0u8; 22];
        for i in 0..22 {
            data[21 - i] = BASE62_DIGITS[(n % 62) as usize];
            n /= 62;
        }

        std::str::from_utf8(&data).unwrap().to_owned()
    }

    pub fn to_uri(&self) -> String {
        match self.audio_type {
            SpotifyAudioType::Track => format!("spotify:track:{}", self.to_base62()),
            SpotifyAudioType::Podcast => format!("spotify:episode:{}", self.to_base62()),
            SpotifyAudioType::NonPlayable => format!("spotify:unknown:{}", self.to_base62()),
        }
    }

    pub fn to_raw(&self) -> [u8; 16] {
        self.id.to_be_bytes()
    }
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileId(pub [u8; 20]);

impl FileId {
    pub fn to_base16(&self) -> String {
        self.0
            .iter()
            .map(|b| format!("{:02x}", b))
            .collect::<Vec<String>>()
            .concat()
    }
}

impl fmt::Debug for FileId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_tuple("FileId").field(&self.to_base16()).finish()
    }
}

impl fmt::Display for FileId {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.to_base16())
    }
}
<|endoftext|>


<commit_before><commit_msg>Add main function to stack example<commit_after><|endoftext|>


<commit_before>extern crate vorbisfile;

use vorbisfile::{VorbisFile, OVError};
use std::io;

fn main() {
    let mut vf = match VorbisFile::new(io::stdin()) {
        Ok(f) => f,
        Err(e) => {
            println!("Error opening input file: {}", e);
            return;
        }
    };
    let mut prev_channels = 0;

    match vf.comment(-1) {
        Some(mut comments) => {
            println!("Encoded by {}", comments.vendor);
            println!("File comments:");
            comments.comments.sort();
            for comment in comments.comments.iter() {
                match comment.find('=') {
                    None => {
                        println!("\t {}", comment);
                    }
                    Some(i) => {
                        println!("\t {}: {}", comment.slice_to(i),
                                 if i < comment.len() {
                                     comment.slice_from(i + 1)
                                 } else {
                                     ""
                                 });
                    }
                }
            }
        }
        None => {
            println!("Failed to get stream comments.");
        }
    }

    loop {
        let res = vf.decode();
        match res {
            Ok(ref channels) if channels.len() != prev_channels => {
                println!("Input has {} channel{}", channels.len(),
                         if channels.len() != 1 {
                             "s"
                         } else {
                             ""
                         });
                prev_channels = channels.len();
            }
            Ok(_) => {}
            Err(OVError::EndOfStream) => {
                return;
            },
            Err(e) => {
                println!("Error decoding input: {}", e);
                return;
            }
        }
    }
}
<commit_msg>Update example too.<commit_after>extern crate vorbisfile;

use vorbisfile::{VorbisFile, OVError};
use std::error::Error;
use std::io;

fn main() {
    let mut vf = match VorbisFile::new(io::stdin()) {
        Ok(f) => f,
        Err(e) => {
            println!("Error opening input file: {}", e.description());
            return;
        }
    };
    let mut prev_channels = 0;

    match vf.comment(-1) {
        Some(mut comments) => {
            println!("Encoded by {}", comments.vendor);
            println!("File comments:");
            comments.comments.sort();
            for comment in comments.comments.iter() {
                match comment.find('=') {
                    None => {
                        println!("\t {}", comment);
                    }
                    Some(i) => {
                        println!("\t {}: {}", comment.slice_to(i),
                                 if i < comment.len() {
                                     comment.slice_from(i + 1)
                                 } else {
                                     ""
                                 });
                    }
                }
            }
        }
        None => {
            println!("Failed to get stream comments.");
        }
    }

    loop {
        let res = vf.decode();
        match res {
            Ok(ref channels) if channels.len() != prev_channels => {
                println!("Input has {} channel{}", channels.len(),
                         if channels.len() != 1 {
                             "s"
                         } else {
                             ""
                         });
                prev_channels = channels.len();
            }
            Ok(_) => {}
            Err(OVError::EndOfStream) => {
                return;
            },
            Err(e) => {
                println!("Error decoding input: {}", e.description());
                return;
            }
        }
    }
}
<|endoftext|>


<commit_before>///! Generate a base bitmap for drawing an overland map with a paint program.

extern crate world;
extern crate image;

use image::Pixel;
use world::{Sector, Location};

const COLS: i16 = 10;
const ROWS: i16 = 10;

fn overland_locs() -> Vec<Location> {
    let mut ret = Vec::new();
    for y in 0..ROWS {
        for x in 0..COLS {
            let sec = Sector::new(x, y, 0);
            for loc in sec.iter() {
                ret.push(loc);
            }
        }
    }
    ret
}

fn main() {
    let locs = overland_locs();
    let (min_x, min_y) = locs.iter().fold(
        (0, 0),
        |(x, y), loc| (x.min(loc.x), y.min(loc.y)),
    );
    let (max_x, max_y) = locs.iter().fold(
        (0, 0),
        |(x, y), loc| (x.max(loc.x), y.max(loc.y)),
    );
    println!("{} {} - {} {}", min_x, min_y, max_x, max_y);

    let mut buf = image::ImageBuffer::new((max_x - min_x) as u32, (max_y - min_y) as u32);

    for (x, y, p) in buf.enumerate_pixels_mut() {
        let loc = Location::new(x as i16 + min_x, y as i16 + min_y, 0);
        let sec = loc.sector();
        if sec.x < 0 || sec.y < 0 || sec.x >= COLS || sec.y >= ROWS {
            *p = image::Rgb::from_channels(0x00, 0x00, 0x00, 0xff);
            continue;
        }
        if (sec.x + sec.y) % 2 == 0 {
            *p = image::Rgb::from_channels(0x00, 0xaa, 0xaa, 0xff);
        } else {
            *p = image::Rgb::from_channels(0x88, 0x88, 0x88, 0xff);
        }
    }

    image::save_buffer(
        "overland_base.png",
        &buf,
        buf.width(),
        buf.height(),
        image::ColorType::RGB(8),
    ).unwrap();
}
<commit_msg>Overland base generator adds pad space<commit_after>///! Generate a base bitmap for drawing an overland map with a paint program.

extern crate world;
extern crate image;

use image::Pixel;
use world::{Sector, Location};

const COLS: i16 = 10;
const ROWS: i16 = 10;

fn overland_locs() -> Vec<Location> {
    let mut ret = Vec::new();
    for y in 0..ROWS {
        for x in 0..COLS {
            let sec = Sector::new(x, y, 0);
            for loc in sec.iter() {
                ret.push(loc);
            }
        }
    }
    ret
}

fn main() {
    let locs = overland_locs();
    let (mut min_x, mut min_y) = locs.iter().fold(
        (0, 0),
        |(x, y), loc| (x.min(loc.x), y.min(loc.y)),
    );
    min_x -= 1;
    min_y -= 1;

    let (max_x, max_y) = locs.iter().fold(
        (0, 0),
        |(x, y), loc| (x.max(loc.x), y.max(loc.y)),
    );
    println!("{} {} - {} {}", min_x, min_y, max_x, max_y);

    let mut buf = image::ImageBuffer::new((max_x - min_x + 1) as u32, (max_y - min_y + 1) as u32);

    for (x, y, p) in buf.enumerate_pixels_mut() {
        let loc = Location::new(x as i16 + min_x, y as i16 + min_y, 0);
        let sec = loc.sector();
        if sec.x < 0 || sec.y < 0 || sec.x >= COLS || sec.y >= ROWS {
            *p = image::Rgb::from_channels(0x00, 0x00, 0x00, 0xff);
            continue;
        }
        if (sec.x + sec.y) % 2 == 0 {
            *p = image::Rgb::from_channels(0x00, 0xaa, 0xaa, 0xff);
        } else {
            *p = image::Rgb::from_channels(0x88, 0x88, 0x88, 0xff);
        }
    }

    image::save_buffer(
        "overland_base.png",
        &buf,
        buf.width(),
        buf.height(),
        image::ColorType::RGB(8),
    ).unwrap();
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

//! Aptos Rosetta API
//!
//! [Rosetta API Spec](https://www.rosetta-api.org/docs/Reference.html)

extern crate core;

use crate::error::ApiError;
use aptos_api::runtime::WebServer;
use aptos_config::config::ApiConfig;
use aptos_logger::debug;
use aptos_rest_client::aptos_api_types::Error;
use aptos_types::chain_id::ChainId;
use std::convert::Infallible;
use tokio::task::JoinHandle;
use warp::{
    http::{HeaderValue, Method, StatusCode},
    reject::{MethodNotAllowed, PayloadTooLarge, UnsupportedMediaType},
    reply, Filter, Rejection, Reply,
};

mod account;
mod block;
mod network;

pub mod client;
pub mod common;
pub mod error;
pub mod types;

pub const CURRENCY: &str = "APTOS";
pub const NUM_DECIMALS: u64 = 6;
pub const MIDDLEWARE_VERSION: &str = "1.0.0";
pub const NODE_VERSION: &str = "0.1";
pub const ROSETTA_VERSION: &str = "1.4.12";

/// Rosetta API context for use on all APIs
#[derive(Clone, Debug)]
pub struct RosettaContext {
    /// A rest client to connect to a fullnode
    rest_client: Option<aptos_rest_client::Client>,
    /// ChainId of the chain to connect to
    pub chain_id: ChainId,
}

impl RosettaContext {
    fn rest_client(&self) -> Result<&aptos_rest_client::Client, ApiError> {
        if let Some(ref client) = self.rest_client {
            Ok(client)
        } else {
            Err(ApiError::NodeIsOffline)
        }
    }
}

/// Creates HTTP server (warp-based) for Rosetta
pub fn bootstrap(
    chain_id: ChainId,
    api_config: ApiConfig,
    rest_client: Option<aptos_rest_client::Client>,
) -> anyhow::Result<tokio::runtime::Runtime> {
    let runtime = tokio::runtime::Builder::new_multi_thread()
        .thread_name("rosetta")
        .enable_all()
        .build()
        .expect("[rosetta] failed to create runtime");

    debug!("Starting up Rosetta server with {:?}", api_config);
    let api = WebServer::from(api_config);

    runtime.spawn(async move {
        let context = RosettaContext {
            rest_client,
            chain_id,
        };
        api.serve(routes(context)).await;
    });
    Ok(runtime)
}

pub async fn bootstrap_async(
    chain_id: ChainId,
    api_config: ApiConfig,
    rest_client: Option<aptos_rest_client::Client>,
) -> anyhow::Result<JoinHandle<()>> {
    debug!("Starting up Rosetta server with {:?}", api_config);
    let api = WebServer::from(api_config);
    let handle = tokio::spawn(async move {
        let context = RosettaContext {
            rest_client,
            chain_id,
        };
        api.serve(routes(context)).await;
    });
    Ok(handle)
}

/// Collection of all routes for the server
pub fn routes(
    context: RosettaContext,
) -> impl Filter<Extract = impl Reply, Error = Infallible> + Clone {
    account::routes(context.clone())
        .or(block::routes(context.clone()))
        .or(network::routes(context))
        // TODO: Add health check?
        .with(
            warp::cors()
                .allow_any_origin()
                .allow_methods(vec![Method::GET, Method::POST])
                .allow_headers(vec![warp::http::header::CONTENT_TYPE]),
        )
        .recover(handle_rejection)
    // TODO Logger?
    // TODO metrics?
}

/// Handle error codes from warp
async fn handle_rejection(err: Rejection) -> Result<impl Reply, Infallible> {
    let code;
    let body;

    if err.is_not_found() {
        code = StatusCode::NOT_FOUND;
        body = reply::json(&Error::new(code, "Not Found".to_owned()));
    } else if let Some(cause) = err.find::<warp::cors::CorsForbidden>() {
        code = StatusCode::FORBIDDEN;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else if let Some(cause) = err.find::<warp::body::BodyDeserializeError>() {
        code = StatusCode::BAD_REQUEST;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else if let Some(cause) = err.find::<warp::reject::LengthRequired>() {
        code = StatusCode::LENGTH_REQUIRED;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else if let Some(cause) = err.find::<PayloadTooLarge>() {
        code = StatusCode::PAYLOAD_TOO_LARGE;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else if let Some(cause) = err.find::<UnsupportedMediaType>() {
        code = StatusCode::UNSUPPORTED_MEDIA_TYPE;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else if let Some(cause) = err.find::<MethodNotAllowed>() {
        code = StatusCode::METHOD_NOT_ALLOWED;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else {
        code = StatusCode::INTERNAL_SERVER_ERROR;
        body = reply::json(&Error::new(code, format!("unexpected error: {:?}", err)));
    }
    let mut rep = reply::with_status(body, code).into_response();
    rep.headers_mut()
        .insert("access-control-allow-origin", HeaderValue::from_static("*"));
    Ok(rep)
}
<commit_msg>[aptos-rosetta] More rosetta documentation<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

//! Aptos Rosetta API
//!
//! [Rosetta API Spec](https://www.rosetta-api.org/docs/Reference.html)

extern crate core;

use crate::error::ApiError;
use aptos_api::runtime::WebServer;
use aptos_config::config::ApiConfig;
use aptos_logger::debug;
use aptos_rest_client::aptos_api_types::Error;
use aptos_types::chain_id::ChainId;
use std::convert::Infallible;
use tokio::task::JoinHandle;
use warp::{
    http::{HeaderValue, Method, StatusCode},
    reject::{MethodNotAllowed, PayloadTooLarge, UnsupportedMediaType},
    reply, Filter, Rejection, Reply,
};

mod account;
mod block;
mod construction;
mod network;

pub mod client;
pub mod common;
pub mod error;
pub mod types;

pub const CURRENCY: &str = "APTOS";
pub const NUM_DECIMALS: u64 = 6;
pub const MIDDLEWARE_VERSION: &str = "1.0.0";
pub const NODE_VERSION: &str = "0.1";
pub const ROSETTA_VERSION: &str = "1.4.12";

/// Rosetta API context for use on all APIs
#[derive(Clone, Debug)]
pub struct RosettaContext {
    /// A rest client to connect to a fullnode
    rest_client: Option<aptos_rest_client::Client>,
    /// ChainId of the chain to connect to
    pub chain_id: ChainId,
}

impl RosettaContext {
    fn rest_client(&self) -> Result<&aptos_rest_client::Client, ApiError> {
        if let Some(ref client) = self.rest_client {
            Ok(client)
        } else {
            Err(ApiError::NodeIsOffline)
        }
    }
}

/// Creates HTTP server (warp-based) for Rosetta
pub fn bootstrap(
    chain_id: ChainId,
    api_config: ApiConfig,
    rest_client: Option<aptos_rest_client::Client>,
) -> anyhow::Result<tokio::runtime::Runtime> {
    let runtime = tokio::runtime::Builder::new_multi_thread()
        .thread_name("rosetta")
        .enable_all()
        .build()
        .expect("[rosetta] failed to create runtime");

    debug!("Starting up Rosetta server with {:?}", api_config);
    let api = WebServer::from(api_config);

    runtime.spawn(async move {
        let context = RosettaContext {
            rest_client,
            chain_id,
        };
        api.serve(routes(context)).await;
    });
    Ok(runtime)
}

pub async fn bootstrap_async(
    chain_id: ChainId,
    api_config: ApiConfig,
    rest_client: Option<aptos_rest_client::Client>,
) -> anyhow::Result<JoinHandle<()>> {
    debug!("Starting up Rosetta server with {:?}", api_config);
    let api = WebServer::from(api_config);
    let handle = tokio::spawn(async move {
        let context = RosettaContext {
            rest_client,
            chain_id,
        };
        api.serve(routes(context)).await;
    });
    Ok(handle)
}

/// Collection of all routes for the server
pub fn routes(
    context: RosettaContext,
) -> impl Filter<Extract = impl Reply, Error = Infallible> + Clone {
    account::routes(context.clone())
        .or(block::routes(context.clone()))
        .or(network::routes(context))
        // TODO: Add health check?
        .with(
            warp::cors()
                .allow_any_origin()
                .allow_methods(vec![Method::GET, Method::POST])
                .allow_headers(vec![warp::http::header::CONTENT_TYPE]),
        )
        .recover(handle_rejection)
    // TODO Logger?
    // TODO metrics?
}

/// Handle error codes from warp
async fn handle_rejection(err: Rejection) -> Result<impl Reply, Infallible> {
    let code;
    let body;

    if err.is_not_found() {
        code = StatusCode::NOT_FOUND;
        body = reply::json(&Error::new(code, "Not Found".to_owned()));
    } else if let Some(cause) = err.find::<warp::cors::CorsForbidden>() {
        code = StatusCode::FORBIDDEN;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else if let Some(cause) = err.find::<warp::body::BodyDeserializeError>() {
        code = StatusCode::BAD_REQUEST;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else if let Some(cause) = err.find::<warp::reject::LengthRequired>() {
        code = StatusCode::LENGTH_REQUIRED;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else if let Some(cause) = err.find::<PayloadTooLarge>() {
        code = StatusCode::PAYLOAD_TOO_LARGE;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else if let Some(cause) = err.find::<UnsupportedMediaType>() {
        code = StatusCode::UNSUPPORTED_MEDIA_TYPE;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else if let Some(cause) = err.find::<MethodNotAllowed>() {
        code = StatusCode::METHOD_NOT_ALLOWED;
        body = reply::json(&Error::new(code, cause.to_string()));
    } else {
        code = StatusCode::INTERNAL_SERVER_ERROR;
        body = reply::json(&Error::new(code, format!("unexpected error: {:?}", err)));
    }
    let mut rep = reply::with_status(body, code).into_response();
    rep.headers_mut()
        .insert("access-control-allow-origin", HeaderValue::from_static("*"));
    Ok(rep)
}
<|endoftext|>


<commit_before>use std::any::Any;
use std::marker::PhantomData;
use std::sync::atomic::{AtomicUsize, Ordering};

use once_cell::sync::OnceCell;

use crate::context::Context;
use crate::lifecycle::InstanceData;

static COUNTER: AtomicUsize = AtomicUsize::new(0);

fn next_id() -> usize {
    COUNTER.fetch_add(1, Ordering::SeqCst)
}

/// A cell that can be used to allocate data that is global to an instance
/// of a Neon addon.
#[derive(Default)]
pub struct Global<T> {
    _type: PhantomData<T>,
    id: OnceCell<usize>,
}

impl<T> Global<T> {
    pub const fn new() -> Self {
        Self {
            _type: PhantomData,
            id: OnceCell::new(),
        }
    }

    fn id(&self) -> usize {
        *self.id.get_or_init(next_id)
    }
}

impl<T: Any + Send + 'static> Global<T> {
    pub fn get<'cx, 'a, C>(&self, cx: &'a mut C) -> Option<&'cx T>
    where
        C: Context<'cx>,
    {
        let r: Option<&T> = InstanceData::globals(cx)
            .get(self.id())
            .as_ref()
            .map(|boxed| boxed.downcast_ref().unwrap());

        unsafe {
            std::mem::transmute(r)
        }
    }

    pub fn get_or_init<'cx, 'a, C, F>(&self, cx: &'a mut C, f: F) -> &'cx T
    where
        C: Context<'cx>,
        F: FnOnce() -> T,
    {
        let r: &T = InstanceData::globals(cx)
            .get(self.id())
            .get_or_insert_with(|| Box::new(f()))
            .downcast_ref()
            .unwrap();

        unsafe {
            std::mem::transmute::<&'a T, &'cx T>(r)
        }
    }
}
<commit_msg>Explicitly name the types in the transmute.<commit_after>use std::any::Any;
use std::marker::PhantomData;
use std::sync::atomic::{AtomicUsize, Ordering};

use once_cell::sync::OnceCell;

use crate::context::Context;
use crate::lifecycle::InstanceData;

static COUNTER: AtomicUsize = AtomicUsize::new(0);

fn next_id() -> usize {
    COUNTER.fetch_add(1, Ordering::SeqCst)
}

/// A cell that can be used to allocate data that is global to an instance
/// of a Neon addon.
#[derive(Default)]
pub struct Global<T> {
    _type: PhantomData<T>,
    id: OnceCell<usize>,
}

impl<T> Global<T> {
    pub const fn new() -> Self {
        Self {
            _type: PhantomData,
            id: OnceCell::new(),
        }
    }

    fn id(&self) -> usize {
        *self.id.get_or_init(next_id)
    }
}

impl<T: Any + Send + 'static> Global<T> {
    pub fn get<'cx, 'a, C>(&self, cx: &'a mut C) -> Option<&'cx T>
    where
        C: Context<'cx>,
    {
        let r: Option<&T> = InstanceData::globals(cx)
            .get(self.id())
            .as_ref()
            .map(|boxed| boxed.downcast_ref().unwrap());

        unsafe {
            std::mem::transmute::<Option<&'a T>, Option<&'cx T>>(r)
        }
    }

    pub fn get_or_init<'cx, 'a, C, F>(&self, cx: &'a mut C, f: F) -> &'cx T
    where
        C: Context<'cx>,
        F: FnOnce() -> T,
    {
        let r: &T = InstanceData::globals(cx)
            .get(self.id())
            .get_or_insert_with(|| Box::new(f()))
            .downcast_ref()
            .unwrap();

        unsafe {
            std::mem::transmute::<&'a T, &'cx T>(r)
        }
    }
}
<|endoftext|>


<commit_before>//! Error conditions.

use std::fmt::{self, Debug, Display, Formatter};

use ruma_common::api::error::{FromHttpResponseError, IntoHttpError};

/// An error that can occur during client operations.
#[derive(Debug)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub enum Error<E, F> {
    /// Queried endpoint requires authentication but was called on an anonymous client.
    AuthenticationRequired,

    /// Construction of the HTTP request failed (this should never happen).
    IntoHttp(IntoHttpError),

    /// The request's URL is invalid (this should never happen).
    Url(http::Error),

    /// Couldn't obtain an HTTP response (e.g. due to network or DNS issues).
    Response(E),

    /// Converting the HTTP response to one of ruma's types failed.
    FromHttpResponse(FromHttpResponseError<F>),
}

impl<E: Display, F: Display> Display for Error<E, F> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::AuthenticationRequired => {
                write!(f, "The queried endpoint requires authentication but was called with an anonymous client.")
            }
            Self::IntoHttp(err) => write!(f, "HTTP request construction failed: {}", err),
            Self::Url(err) => write!(f, "Invalid URL: {}", err),
            Self::Response(err) => write!(f, "Couldn't obtain a response: {}", err),
            Self::FromHttpResponse(err) => write!(f, "HTTP response conversion failed: {}", err),
        }
    }
}

impl<E, F> From<IntoHttpError> for Error<E, F> {
    fn from(err: IntoHttpError) -> Self {
        Error::IntoHttp(err)
    }
}

#[doc(hidden)]
impl<E, F> From<http::uri::InvalidUri> for Error<E, F> {
    fn from(err: http::uri::InvalidUri) -> Self {
        Error::Url(err.into())
    }
}

#[doc(hidden)]
impl<E, F> From<http::uri::InvalidUriParts> for Error<E, F> {
    fn from(err: http::uri::InvalidUriParts) -> Self {
        Error::Url(err.into())
    }
}

impl<E, F> From<FromHttpResponseError<F>> for Error<E, F> {
    fn from(err: FromHttpResponseError<F>) -> Self {
        Error::FromHttpResponse(err)
    }
}

impl<E: Debug + Display, F: Debug + Display> std::error::Error for Error<E, F> {}
<commit_msg>client: Remove unnecessary cfg_attr<commit_after>//! Error conditions.

use std::fmt::{self, Debug, Display, Formatter};

use ruma_common::api::error::{FromHttpResponseError, IntoHttpError};

/// An error that can occur during client operations.
#[derive(Debug)]
#[non_exhaustive]
pub enum Error<E, F> {
    /// Queried endpoint requires authentication but was called on an anonymous client.
    AuthenticationRequired,

    /// Construction of the HTTP request failed (this should never happen).
    IntoHttp(IntoHttpError),

    /// The request's URL is invalid (this should never happen).
    Url(http::Error),

    /// Couldn't obtain an HTTP response (e.g. due to network or DNS issues).
    Response(E),

    /// Converting the HTTP response to one of ruma's types failed.
    FromHttpResponse(FromHttpResponseError<F>),
}

impl<E: Display, F: Display> Display for Error<E, F> {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        match self {
            Self::AuthenticationRequired => {
                write!(f, "The queried endpoint requires authentication but was called with an anonymous client.")
            }
            Self::IntoHttp(err) => write!(f, "HTTP request construction failed: {}", err),
            Self::Url(err) => write!(f, "Invalid URL: {}", err),
            Self::Response(err) => write!(f, "Couldn't obtain a response: {}", err),
            Self::FromHttpResponse(err) => write!(f, "HTTP response conversion failed: {}", err),
        }
    }
}

impl<E, F> From<IntoHttpError> for Error<E, F> {
    fn from(err: IntoHttpError) -> Self {
        Error::IntoHttp(err)
    }
}

#[doc(hidden)]
impl<E, F> From<http::uri::InvalidUri> for Error<E, F> {
    fn from(err: http::uri::InvalidUri) -> Self {
        Error::Url(err.into())
    }
}

#[doc(hidden)]
impl<E, F> From<http::uri::InvalidUriParts> for Error<E, F> {
    fn from(err: http::uri::InvalidUriParts) -> Self {
        Error::Url(err.into())
    }
}

impl<E, F> From<FromHttpResponseError<F>> for Error<E, F> {
    fn from(err: FromHttpResponseError<F>) -> Self {
        Error::FromHttpResponse(err)
    }
}

impl<E: Debug + Display, F: Debug + Display> std::error::Error for Error<E, F> {}
<|endoftext|>


<commit_before>extern crate toml;

pub mod content;
pub mod entry;
pub mod error;
pub mod header;

<commit_msg>Add extern crate fs2<commit_after>extern crate fs2;
extern crate toml;

pub mod content;
pub mod entry;
pub mod error;
pub mod header;

<|endoftext|>


<commit_before>#![cfg_attr(feature = "cargo-clippy", allow(clippy::unneeded_field_pattern))]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::toplevel_ref_arg))]

use super::user_input_ast::*;
use combine::char::*;
use combine::error::StreamError;
use combine::stream::StreamErrorFor;
use combine::*;
use query::occur::Occur;
use query::query_parser::user_input_ast::UserInputBound;

parser! {
    fn field[I]()(I) -> String
    where [I: Stream<Item = char>] {
        (
            letter(),
            many(satisfy(|c: char| c.is_alphanumeric() || c == '_')),
        ).map(|(s1, s2): (char, String)| format!("{}{}", s1, s2))
    }
}

parser! {
    fn word[I]()(I) -> String
    where [I: Stream<Item = char>] {
        many1(satisfy(|c: char| c.is_alphanumeric()))
               .and_then(|s: String| {
                   match s.as_str() {
                     "OR" => Err(StreamErrorFor::<I>::unexpected_static_message("OR")),
                     "AND" => Err(StreamErrorFor::<I>::unexpected_static_message("AND")),
                     "NOT" => Err(StreamErrorFor::<I>::unexpected_static_message("NOT")),
                     _ => Ok(s)
                   }
               })
    }
}

parser! {
    fn literal[I]()(I) -> UserInputLeaf
    where [I: Stream<Item = char>]
    {
        let term_val = || {
            let phrase = (char('"'), many1(satisfy(|c| c != '"')), char('"')).map(|(_, s, _)| s);
            phrase.or(word())
        };
        let term_val_with_field = negative_number().or(term_val());
        let term_query =
            (field(), char(':'), term_val_with_field).map(|(field_name, _, phrase)| UserInputLiteral {
                field_name: Some(field_name),
                phrase,
            });
        let term_default_field = term_val().map(|phrase| UserInputLiteral {
            field_name: None,
            phrase,
        });
        try(term_query)
            .or(term_default_field)
            .map(UserInputLeaf::from)
    }
}

parser! {
    fn negative_number[I]()(I) -> String
    where [I: Stream<Item = char>]
    {
            (char('-'), many1(satisfy(|c: char| c.is_numeric())))
                .map(|(s1, s2): (char, String)| format!("{}{}", s1, s2))
    }
}

parser! {
    fn spaces1[I]()(I) -> ()
    where [I: Stream<Item = char>] {
        skip_many1(space())
    }
}

parser! {
    fn range[I]()(I) -> UserInputLeaf
    where [I: Stream<Item = char>] {
        let term_val = || {
            word().or(negative_number()).or(char('*').map(|_| "*".to_string()))
        };
        let lower_bound = {
            let excl = (char('{'), term_val()).map(|(_, w)| UserInputBound::Exclusive(w));
            let incl = (char('['), term_val()).map(|(_, w)| UserInputBound::Inclusive(w));
            try(excl).or(incl)
        };
        let upper_bound = {
            let excl = (term_val(), char('}')).map(|(w, _)| UserInputBound::Exclusive(w));
            let incl = (term_val(), char(']')).map(|(w, _)| UserInputBound::Inclusive(w));
            try(excl).or(incl)
        };
        (
            optional((field(), char(':')).map(|x| x.0)),
            lower_bound,
            spaces(),
            string("TO"),
            spaces(),
            upper_bound,
        ).map(|(field, lower, _, _, _, upper)| UserInputLeaf::Range {
                field,
                lower,
                upper
        })
    }
}

parser! {
    fn leaf[I]()(I) -> UserInputAST
    where [I: Stream<Item = char>] {
         (char('-'), leaf()).map(|(_, expr)| expr.unary(Occur::MustNot) )
        .or((char('+'), leaf()).map(|(_, expr)| expr.unary(Occur::Must) ))
        .or((char('('), parse_to_ast(), char(')')).map(|(_, expr, _)| expr))
        .or(char('*').map(|_| UserInputAST::from(UserInputLeaf::All) ))
        .or(try(
            (string("NOT"), spaces1(), leaf()).map(|(_, _, expr)| expr.unary(Occur::MustNot))
            )
         )
        .or(try(
            range().map(UserInputAST::from)
            )
        )
        .or(literal().map(|leaf| UserInputAST::Leaf(Box::new(leaf))))
    }
}

enum BinaryOperand {
    Or,
    And,
}

parser! {
    fn binary_operand[I]()(I) -> BinaryOperand
    where [I: Stream<Item = char>] {
        (spaces1(),
         (
            string("AND").map(|_| BinaryOperand::And)
           .or(string("OR").map(|_| BinaryOperand::Or))
         ),
         spaces1()).map(|(_, op,_)| op)
    }
}

enum Element {
    SingleEl(UserInputAST),
    NormalDisjunctive(Vec<Vec<UserInputAST>>),
}

impl Element {
    pub fn into_dnf(self) -> Vec<Vec<UserInputAST>> {
        match self {
            Element::NormalDisjunctive(conjunctions) => conjunctions,
            Element::SingleEl(el) => vec![vec![el]],
        }
    }
}

parser! {
    pub fn parse_to_ast[I]()(I) -> UserInputAST
    where [I: Stream<Item = char>]
    {
        (
            try(
                chainl1(
                    leaf().map(Element::SingleEl),
                    binary_operand().map(|op: BinaryOperand|
                        move |left: Element, right: Element| {
                            let mut dnf = left.into_dnf();
                            if let Element::SingleEl(el) = right {
                                match op {
                                    BinaryOperand::And => {
                                        if let Some(last) = dnf.last_mut() {
                                            last.push(el);
                                        }
                                    }
                                    BinaryOperand::Or => {
                                        dnf.push(vec!(el));
                                    }
                                }
                            } else {
                                unreachable!("Please report.")
                            }
                            Element::NormalDisjunctive(dnf)
                        }
                    )
                )
                .map(|el| el.into_dnf())
                .map(|fnd| {
                    if fnd.len() == 1 {
                        UserInputAST::and(fnd.into_iter().next().unwrap()) //< safe
                    } else {
                        let conjunctions = fnd
                        .into_iter()
                        .map(UserInputAST::and)
                        .collect();
                        UserInputAST::or(conjunctions)
                    }
                })
            )
            .or(
                sep_by(leaf(), spaces())
                .map(|subqueries: Vec<UserInputAST>| {
                    if subqueries.len() == 1 {
                        subqueries.into_iter().next().unwrap()
                    } else {
                        UserInputAST::Clause(subqueries.into_iter().collect())
                    }
                })
            )
        )

    }
}

#[cfg(test)]
mod test {

    use super::*;

    fn test_parse_query_to_ast_helper(query: &str, expected: &str) {
        let query = parse_to_ast().parse(query).unwrap().0;
        let query_str = format!("{:?}", query);
        assert_eq!(query_str, expected);
    }

    fn test_is_parse_err(query: &str) {
        assert!(parse_to_ast().parse(query).is_err());
    }

    #[test]
    fn test_parse_query_to_ast_not_op() {
        assert_eq!(
            format!("{:?}", parse_to_ast().parse("NOT")),
            "Err(UnexpectedParse)"
        );
        test_parse_query_to_ast_helper("NOTa", "\"NOTa\"");
        test_parse_query_to_ast_helper("NOT a", "-(\"a\")");
    }

    #[test]
    fn test_parse_query_to_ast_binary_op() {
        test_parse_query_to_ast_helper("a AND b", "(+(\"a\") +(\"b\"))");
        test_parse_query_to_ast_helper("a OR b", "(?(\"a\") ?(\"b\"))");
        test_parse_query_to_ast_helper("a OR b AND c", "(?(\"a\") ?((+(\"b\") +(\"c\"))))");
        test_parse_query_to_ast_helper("a AND b         AND c", "(+(\"a\") +(\"b\") +(\"c\"))");
        assert_eq!(
            format!("{:?}", parse_to_ast().parse("a OR b aaa")),
            "Err(UnexpectedParse)"
        );
        assert_eq!(
            format!("{:?}", parse_to_ast().parse("a AND b aaa")),
            "Err(UnexpectedParse)"
        );
        assert_eq!(
            format!("{:?}", parse_to_ast().parse("aaa a OR b ")),
            "Err(UnexpectedParse)"
        );
        assert_eq!(
            format!("{:?}", parse_to_ast().parse("aaa ccc a OR b ")),
            "Err(UnexpectedParse)"
        );
    }

    #[test]
    fn test_parse_query_to_ast() {
        test_parse_query_to_ast_helper("+(a b) +d", "(+((\"a\" \"b\")) +(\"d\"))");
        test_parse_query_to_ast_helper("(+a +b) d", "((+(\"a\") +(\"b\")) \"d\")");
        test_parse_query_to_ast_helper("(+a)", "+(\"a\")");
        test_parse_query_to_ast_helper("(+a +b)", "(+(\"a\") +(\"b\"))");
        test_parse_query_to_ast_helper("abc:toto", "abc:\"toto\"");
        test_parse_query_to_ast_helper("+abc:toto", "+(abc:\"toto\")");
        test_parse_query_to_ast_helper("(+abc:toto -titi)", "(+(abc:\"toto\") -(\"titi\"))");
        test_parse_query_to_ast_helper("-abc:toto", "-(abc:\"toto\")");
        test_parse_query_to_ast_helper("abc:a b", "(abc:\"a\" \"b\")");
        test_parse_query_to_ast_helper("abc:\"a b\"", "abc:\"a b\"");
        test_parse_query_to_ast_helper("foo:[1 TO 5]", "foo:[\"1\" TO \"5\"]");
        test_parse_query_to_ast_helper("[1 TO 5]", "[\"1\" TO \"5\"]");
        test_parse_query_to_ast_helper("foo:{a TO z}", "foo:{\"a\" TO \"z\"}");
        test_parse_query_to_ast_helper("foo:[1 TO toto}", "foo:[\"1\" TO \"toto\"}");
        test_parse_query_to_ast_helper("foo:[* TO toto}", "foo:[\"*\" TO \"toto\"}");
        test_parse_query_to_ast_helper("foo:[1 TO *}", "foo:[\"1\" TO \"*\"}");
        test_is_parse_err("abc +    ");
    }
}
<commit_msg>Rename try to attempt as try is becoming a keyword in rust<commit_after>#![cfg_attr(feature = "cargo-clippy", allow(clippy::unneeded_field_pattern))]
#![cfg_attr(feature = "cargo-clippy", allow(clippy::toplevel_ref_arg))]

use super::user_input_ast::*;
use combine::char::*;
use combine::error::StreamError;
use combine::stream::StreamErrorFor;
use combine::*;
use query::occur::Occur;
use query::query_parser::user_input_ast::UserInputBound;

parser! {
    fn field[I]()(I) -> String
    where [I: Stream<Item = char>] {
        (
            letter(),
            many(satisfy(|c: char| c.is_alphanumeric() || c == '_')),
        ).map(|(s1, s2): (char, String)| format!("{}{}", s1, s2))
    }
}

parser! {
    fn word[I]()(I) -> String
    where [I: Stream<Item = char>] {
        many1(satisfy(|c: char| c.is_alphanumeric()))
               .and_then(|s: String| {
                   match s.as_str() {
                     "OR" => Err(StreamErrorFor::<I>::unexpected_static_message("OR")),
                     "AND" => Err(StreamErrorFor::<I>::unexpected_static_message("AND")),
                     "NOT" => Err(StreamErrorFor::<I>::unexpected_static_message("NOT")),
                     _ => Ok(s)
                   }
               })
    }
}

parser! {
    fn literal[I]()(I) -> UserInputLeaf
    where [I: Stream<Item = char>]
    {
        let term_val = || {
            let phrase = (char('"'), many1(satisfy(|c| c != '"')), char('"')).map(|(_, s, _)| s);
            phrase.or(word())
        };
        let term_val_with_field = negative_number().or(term_val());
        let term_query =
            (field(), char(':'), term_val_with_field).map(|(field_name, _, phrase)| UserInputLiteral {
                field_name: Some(field_name),
                phrase,
            });
        let term_default_field = term_val().map(|phrase| UserInputLiteral {
            field_name: None,
            phrase,
        });
        attempt(term_query)
            .or(term_default_field)
            .map(UserInputLeaf::from)
    }
}

parser! {
    fn negative_number[I]()(I) -> String
    where [I: Stream<Item = char>]
    {
            (char('-'), many1(satisfy(|c: char| c.is_numeric())))
                .map(|(s1, s2): (char, String)| format!("{}{}", s1, s2))
    }
}

parser! {
    fn spaces1[I]()(I) -> ()
    where [I: Stream<Item = char>] {
        skip_many1(space())
    }
}

parser! {
    fn range[I]()(I) -> UserInputLeaf
    where [I: Stream<Item = char>] {
        let term_val = || {
            word().or(negative_number()).or(char('*').map(|_| "*".to_string()))
        };
        let lower_bound = {
            let excl = (char('{'), term_val()).map(|(_, w)| UserInputBound::Exclusive(w));
            let incl = (char('['), term_val()).map(|(_, w)| UserInputBound::Inclusive(w));
            attempt(excl).or(incl)
        };
        let upper_bound = {
            let excl = (term_val(), char('}')).map(|(w, _)| UserInputBound::Exclusive(w));
            let incl = (term_val(), char(']')).map(|(w, _)| UserInputBound::Inclusive(w));
            attempt(excl).or(incl)
        };
        (
            optional((field(), char(':')).map(|x| x.0)),
            lower_bound,
            spaces(),
            string("TO"),
            spaces(),
            upper_bound,
        ).map(|(field, lower, _, _, _, upper)| UserInputLeaf::Range {
                field,
                lower,
                upper
        })
    }
}

parser! {
    fn leaf[I]()(I) -> UserInputAST
    where [I: Stream<Item = char>] {
         (char('-'), leaf()).map(|(_, expr)| expr.unary(Occur::MustNot) )
        .or((char('+'), leaf()).map(|(_, expr)| expr.unary(Occur::Must) ))
        .or((char('('), parse_to_ast(), char(')')).map(|(_, expr, _)| expr))
        .or(char('*').map(|_| UserInputAST::from(UserInputLeaf::All) ))
        .or(attempt(
            (string("NOT"), spaces1(), leaf()).map(|(_, _, expr)| expr.unary(Occur::MustNot))
            )
         )
        .or(attempt(
            range().map(UserInputAST::from)
            )
        )
        .or(literal().map(|leaf| UserInputAST::Leaf(Box::new(leaf))))
    }
}

enum BinaryOperand {
    Or,
    And,
}

parser! {
    fn binary_operand[I]()(I) -> BinaryOperand
    where [I: Stream<Item = char>] {
        (spaces1(),
         (
            string("AND").map(|_| BinaryOperand::And)
           .or(string("OR").map(|_| BinaryOperand::Or))
         ),
         spaces1()).map(|(_, op,_)| op)
    }
}

enum Element {
    SingleEl(UserInputAST),
    NormalDisjunctive(Vec<Vec<UserInputAST>>),
}

impl Element {
    pub fn into_dnf(self) -> Vec<Vec<UserInputAST>> {
        match self {
            Element::NormalDisjunctive(conjunctions) => conjunctions,
            Element::SingleEl(el) => vec![vec![el]],
        }
    }
}

parser! {
    pub fn parse_to_ast[I]()(I) -> UserInputAST
    where [I: Stream<Item = char>]
    {
        (
            attempt(
                chainl1(
                    leaf().map(Element::SingleEl),
                    binary_operand().map(|op: BinaryOperand|
                        move |left: Element, right: Element| {
                            let mut dnf = left.into_dnf();
                            if let Element::SingleEl(el) = right {
                                match op {
                                    BinaryOperand::And => {
                                        if let Some(last) = dnf.last_mut() {
                                            last.push(el);
                                        }
                                    }
                                    BinaryOperand::Or => {
                                        dnf.push(vec!(el));
                                    }
                                }
                            } else {
                                unreachable!("Please report.")
                            }
                            Element::NormalDisjunctive(dnf)
                        }
                    )
                )
                .map(|el| el.into_dnf())
                .map(|fnd| {
                    if fnd.len() == 1 {
                        UserInputAST::and(fnd.into_iter().next().unwrap()) //< safe
                    } else {
                        let conjunctions = fnd
                        .into_iter()
                        .map(UserInputAST::and)
                        .collect();
                        UserInputAST::or(conjunctions)
                    }
                })
            )
            .or(
                sep_by(leaf(), spaces())
                .map(|subqueries: Vec<UserInputAST>| {
                    if subqueries.len() == 1 {
                        subqueries.into_iter().next().unwrap()
                    } else {
                        UserInputAST::Clause(subqueries.into_iter().collect())
                    }
                })
            )
        )

    }
}

#[cfg(test)]
mod test {

    use super::*;

    fn test_parse_query_to_ast_helper(query: &str, expected: &str) {
        let query = parse_to_ast().parse(query).unwrap().0;
        let query_str = format!("{:?}", query);
        assert_eq!(query_str, expected);
    }

    fn test_is_parse_err(query: &str) {
        assert!(parse_to_ast().parse(query).is_err());
    }

    #[test]
    fn test_parse_query_to_ast_not_op() {
        assert_eq!(
            format!("{:?}", parse_to_ast().parse("NOT")),
            "Err(UnexpectedParse)"
        );
        test_parse_query_to_ast_helper("NOTa", "\"NOTa\"");
        test_parse_query_to_ast_helper("NOT a", "-(\"a\")");
    }

    #[test]
    fn test_parse_query_to_ast_binary_op() {
        test_parse_query_to_ast_helper("a AND b", "(+(\"a\") +(\"b\"))");
        test_parse_query_to_ast_helper("a OR b", "(?(\"a\") ?(\"b\"))");
        test_parse_query_to_ast_helper("a OR b AND c", "(?(\"a\") ?((+(\"b\") +(\"c\"))))");
        test_parse_query_to_ast_helper("a AND b         AND c", "(+(\"a\") +(\"b\") +(\"c\"))");
        assert_eq!(
            format!("{:?}", parse_to_ast().parse("a OR b aaa")),
            "Err(UnexpectedParse)"
        );
        assert_eq!(
            format!("{:?}", parse_to_ast().parse("a AND b aaa")),
            "Err(UnexpectedParse)"
        );
        assert_eq!(
            format!("{:?}", parse_to_ast().parse("aaa a OR b ")),
            "Err(UnexpectedParse)"
        );
        assert_eq!(
            format!("{:?}", parse_to_ast().parse("aaa ccc a OR b ")),
            "Err(UnexpectedParse)"
        );
    }

    #[test]
    fn test_parse_query_to_ast() {
        test_parse_query_to_ast_helper("+(a b) +d", "(+((\"a\" \"b\")) +(\"d\"))");
        test_parse_query_to_ast_helper("(+a +b) d", "((+(\"a\") +(\"b\")) \"d\")");
        test_parse_query_to_ast_helper("(+a)", "+(\"a\")");
        test_parse_query_to_ast_helper("(+a +b)", "(+(\"a\") +(\"b\"))");
        test_parse_query_to_ast_helper("abc:toto", "abc:\"toto\"");
        test_parse_query_to_ast_helper("+abc:toto", "+(abc:\"toto\")");
        test_parse_query_to_ast_helper("(+abc:toto -titi)", "(+(abc:\"toto\") -(\"titi\"))");
        test_parse_query_to_ast_helper("-abc:toto", "-(abc:\"toto\")");
        test_parse_query_to_ast_helper("abc:a b", "(abc:\"a\" \"b\")");
        test_parse_query_to_ast_helper("abc:\"a b\"", "abc:\"a b\"");
        test_parse_query_to_ast_helper("foo:[1 TO 5]", "foo:[\"1\" TO \"5\"]");
        test_parse_query_to_ast_helper("[1 TO 5]", "[\"1\" TO \"5\"]");
        test_parse_query_to_ast_helper("foo:{a TO z}", "foo:{\"a\" TO \"z\"}");
        test_parse_query_to_ast_helper("foo:[1 TO toto}", "foo:[\"1\" TO \"toto\"}");
        test_parse_query_to_ast_helper("foo:[* TO toto}", "foo:[\"*\" TO \"toto\"}");
        test_parse_query_to_ast_helper("foo:[1 TO *}", "foo:[\"1\" TO \"*\"}");
        test_is_parse_err("abc +    ");
    }
}
<|endoftext|>


<commit_before>// compile-flags: -O

// A reduction of issue #63, where gcc5 (but not 6) will generate invalid code for the following iterator adapter's
// `next` function (seen in librustc)
// ::"core"::iter::Map<::"core"::iter::Chain<::"core"::iter::sources::Once<::"syntax"::ast::NodeId/*S*/,>/*S*/,::"core"::iter::Map<::"core"::slice::Iter<::"syntax"::codemap::Spanned<::"syntax"::ast::PathListItem_/*S*/,>/*S*/,>/*S*/,::"rustc"::closure_I_82<::"rustc"::hir::lowering::LoweringContext/*S*/,>/*S*/,>/*S*/,>/*S*/,::"rustc"::closure_I_83<::"rustc"::hir::lowering::LoweringContext/*S*/,>/*S*/,>
//
//

fn main()
{
    // The function call is kinda needed to trigger the bug
    // - Probably because of how it sets up `rbx` to be non-zero
    println!("{:?}", foo(0, &[]));
}

// Has to have the second map - even if it's just identity
fn foo(n: u32, list: &[u32]) -> Vec<u32> {
    Iterator::chain(
            ::std::iter::once(0u32),
            list.iter().map(|v| *v)
        ).map(|id| id)
        .collect()
}

<commit_msg>Tests - More reduction of GCC5 bug<commit_after>// compile-flags: -O
extern crate test;

// A reduction of issue #63, where gcc5 (but not 6) will generate invalid code for the following iterator adapter's
// `next` function (seen in librustc)
// ::"core"::iter::Map<::"core"::iter::Chain<::"core"::iter::sources::Once<::"syntax"::ast::NodeId/*S*/,>/*S*/,::"core"::iter::Map<::"core"::slice::Iter<::"syntax"::codemap::Spanned<::"syntax"::ast::PathListItem_/*S*/,>/*S*/,>/*S*/,::"rustc"::closure_I_82<::"rustc"::hir::lowering::LoweringContext/*S*/,>/*S*/,>/*S*/,>/*S*/,::"rustc"::closure_I_83<::"rustc"::hir::lowering::LoweringContext/*S*/,>/*S*/,>
//
// Symptom is an abort due to bad enum tag on Option<u32> when handling the second call to `it.next()`

fn main() {
    let n = 0;
    let list: &[u32] = &[1]; // List can be zero length, it's appears to be the _last_ result that leads to a bad tag.
    // Has to have the second map - even if it's just identity, first map probably needs to exist
    let mut it = Iterator::chain(
            ::std::iter::once(0u32),
            list.iter().map(|v| *v)
        ).map(|id| id);

    // First works, and Foo is printed
    it.next();
    println!("Foo");
    // Second one will crash with an abort (used in condition to avoid it being optimised out)
    if it.next().is_none() {
        println!("Bar");
    }
    else {
        println!("Not-Bar");
    }
    if it.next().is_none() {
        println!("Bar");
    }
    else {
        println!("Not-Bar");
    }
}

<|endoftext|>


<commit_before>use rustc_middle::mir;
use rustc_span::Symbol;
use rustc_target::spec::abi::Abi;

use crate::*;
use shims::foreign_items::EmulateByNameResult;

impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}

pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn emulate_foreign_item_by_name(
        &mut self,
        link_name: Symbol,
        abi: Abi,
        args: &[OpTy<'tcx, Tag>],
        dest: &PlaceTy<'tcx, Tag>,
        _ret: mir::BasicBlock,
    ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
        let this = self.eval_context_mut();
        match link_name.as_str() {
            // Linux's `pthread_getattr_np` equivalent
            "pthread_attr_get_np" if this.frame_in_std() => {
                let [_thread, _attr] =
                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                this.write_null(dest)?;
            }
            _ => return Ok(EmulateByNameResult::NotSupported),
        }
        Ok(EmulateByNameResult::NeedsJumping)
    }
}
<commit_msg>Add `__error` to freebsd shims<commit_after>use rustc_middle::mir;
use rustc_span::Symbol;
use rustc_target::spec::abi::Abi;

use crate::*;
use shims::foreign_items::EmulateByNameResult;

impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}

pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    fn emulate_foreign_item_by_name(
        &mut self,
        link_name: Symbol,
        abi: Abi,
        args: &[OpTy<'tcx, Tag>],
        dest: &PlaceTy<'tcx, Tag>,
        _ret: mir::BasicBlock,
    ) -> InterpResult<'tcx, EmulateByNameResult<'mir, 'tcx>> {
        let this = self.eval_context_mut();
        match link_name.as_str() {
            // Linux's `pthread_getattr_np` equivalent
            "pthread_attr_get_np" if this.frame_in_std() => {
                let [_thread, _attr] =
                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                this.write_null(dest)?;
            }

            // errno
            "__error" => {
                let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                let errno_place = this.last_error_place()?;
                this.write_scalar(errno_place.to_ref(this).to_scalar()?, dest)?;
            }

            _ => return Ok(EmulateByNameResult::NotSupported),
        }
        Ok(EmulateByNameResult::NeedsJumping)
    }
}
<|endoftext|>


<commit_before>//! Handles dynamic library loading for proc macro

use crate::{proc_macro::bridge, rustc_server::TokenStream};
use std::fs::File;
use std::path::{Path, PathBuf};

use goblin::{mach::Mach, Object};
use libloading::Library;
use memmap::Mmap;
use ra_proc_macro::ProcMacroKind;

use std::io;

const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";

fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
    io::Error::new(io::ErrorKind::InvalidData, e)
}

fn is_derive_registrar_symbol(symbol: &str) -> bool {
    symbol.contains(NEW_REGISTRAR_SYMBOL)
}

fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> {
    let file = File::open(file)?;
    let buffer = unsafe { Mmap::map(&file)? };
    let object = Object::parse(&buffer).map_err(invalid_data_err)?;

    let name = match object {
        Object::Elf(elf) => {
            let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?;
            symbols.into_iter().find(|s| is_derive_registrar_symbol(s)).map(&str::to_owned)
        }
        Object::PE(pe) => pe
            .exports
            .iter()
            .flat_map(|s| s.name)
            .find(|s| is_derive_registrar_symbol(s))
            .map(&str::to_owned),
        Object::Mach(Mach::Binary(binary)) => {
            let exports = binary.exports().map_err(invalid_data_err)?;
            exports
                .iter()
                .map(|s| {
                    // In macos doc:
                    // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
                    // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be
                    // prepended with an underscore.
                    if s.name.starts_with("_") {
                        &s.name[1..]
                    } else {
                        &s.name
                    }
                })
                .find(|s| is_derive_registrar_symbol(s))
                .map(&str::to_owned)
        }
        _ => return Ok(None),
    };
    return Ok(name);
}

/// Loads dynamic library in platform dependent manner.
///
/// For unix, you have to use RTLD_DEEPBIND flag to escape problems described
/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample)
/// and [here](https://github.com/rust-lang/rust/issues/60593).
///
/// Usage of RTLD_DEEPBIND
/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
///
/// It seems that on Windows that behaviour is default, so we do nothing in that case.
#[cfg(windows)]
fn load_library(file: &Path) -> Result<Library, libloading::Error> {
    Library::new(file)
}

#[cfg(unix)]
fn load_library(file: &Path) -> Result<Library, libloading::Error> {
    use libloading::os::unix::Library as UnixLibrary;
    use std::os::raw::c_int;

    const RTLD_NOW: c_int = 0x00002;
    const RTLD_DEEPBIND: c_int = 0x00008;

    UnixLibrary::open(Some(file), RTLD_NOW | RTLD_DEEPBIND).map(|lib| lib.into())
}

struct ProcMacroLibraryLibloading {
    // Hold the dylib to prevent it from unloading
    _lib: Library,
    exported_macros: Vec<bridge::client::ProcMacro>,
}

impl ProcMacroLibraryLibloading {
    fn open(file: &Path) -> io::Result<Self> {
        let symbol_name = find_registrar_symbol(file)?.ok_or_else(|| {
            invalid_data_err(format!("Cannot find registrar symbol in file {}", file.display()))
        })?;

        let lib = load_library(file).map_err(invalid_data_err)?;
        let exported_macros = {
            let macros: libloading::Symbol<&&[bridge::client::ProcMacro]> =
                unsafe { lib.get(symbol_name.as_bytes()) }.map_err(invalid_data_err)?;
            macros.to_vec()
        };

        Ok(ProcMacroLibraryLibloading { _lib: lib, exported_macros })
    }
}

pub struct Expander {
    inner: ProcMacroLibraryLibloading,
}

impl Expander {
    pub fn new(lib: &Path) -> io::Result<Expander> {
        // Some libraries for dynamic loading require canonicalized path even when it is
        // already absolute
        let lib = lib.canonicalize()?;

        let lib = ensure_file_with_lock_free_access(&lib)?;

        let library = ProcMacroLibraryLibloading::open(&lib)?;

        Ok(Expander { inner: library })
    }

    pub fn expand(
        &self,
        macro_name: &str,
        macro_body: &ra_tt::Subtree,
        attributes: Option<&ra_tt::Subtree>,
    ) -> Result<ra_tt::Subtree, bridge::PanicMessage> {
        let parsed_body = TokenStream::with_subtree(macro_body.clone());

        let parsed_attributes = attributes
            .map_or(crate::rustc_server::TokenStream::new(), |attr| {
                TokenStream::with_subtree(attr.clone())
            });

        for proc_macro in &self.inner.exported_macros {
            match proc_macro {
                bridge::client::ProcMacro::CustomDerive { trait_name, client, .. }
                    if *trait_name == macro_name =>
                {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_body,
                    );
                    return res.map(|it| it.subtree);
                }
                bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_body,
                    );
                    return res.map(|it| it.subtree);
                }
                bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_attributes,
                        parsed_body,
                    );
                    return res.map(|it| it.subtree);
                }
                _ => continue,
            }
        }

        Err(bridge::PanicMessage::String("Nothing to expand".to_string()))
    }

    pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
        self.inner
            .exported_macros
            .iter()
            .map(|proc_macro| match proc_macro {
                bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
                    (trait_name.to_string(), ProcMacroKind::CustomDerive)
                }
                bridge::client::ProcMacro::Bang { name, .. } => {
                    (name.to_string(), ProcMacroKind::FuncLike)
                }
                bridge::client::ProcMacro::Attr { name, .. } => {
                    (name.to_string(), ProcMacroKind::Attr)
                }
            })
            .collect()
    }
}

/// Copy the dylib to temp directory to prevent locking in Windows
#[cfg(windows)]
fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
    let mut to = std::env::temp_dir();
    let file_name = path.file_name().ok_or_else(|| {
        io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("File path is invalid: {}", path.display()),
        )
    })?;

    to.push(file_name);
    std::fs::copy(path, &to)?;
    Ok(to)
}

#[cfg(unix)]
fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
    Ok(path.to_path_buf())
}
<commit_msg>Generate uniq name<commit_after>//! Handles dynamic library loading for proc macro

use crate::{proc_macro::bridge, rustc_server::TokenStream};
use std::fs::File;
use std::path::{Path, PathBuf};

use goblin::{mach::Mach, Object};
use libloading::Library;
use memmap::Mmap;
use ra_proc_macro::ProcMacroKind;
use std::io;

const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";

fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error {
    io::Error::new(io::ErrorKind::InvalidData, e)
}

fn is_derive_registrar_symbol(symbol: &str) -> bool {
    symbol.contains(NEW_REGISTRAR_SYMBOL)
}

fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> {
    let file = File::open(file)?;
    let buffer = unsafe { Mmap::map(&file)? };
    let object = Object::parse(&buffer).map_err(invalid_data_err)?;

    let name = match object {
        Object::Elf(elf) => {
            let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?;
            symbols.into_iter().find(|s| is_derive_registrar_symbol(s)).map(&str::to_owned)
        }
        Object::PE(pe) => pe
            .exports
            .iter()
            .flat_map(|s| s.name)
            .find(|s| is_derive_registrar_symbol(s))
            .map(&str::to_owned),
        Object::Mach(Mach::Binary(binary)) => {
            let exports = binary.exports().map_err(invalid_data_err)?;
            exports
                .iter()
                .map(|s| {
                    // In macos doc:
                    // https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/dlsym.3.html
                    // Unlike other dyld API's, the symbol name passed to dlsym() must NOT be
                    // prepended with an underscore.
                    if s.name.starts_with("_") {
                        &s.name[1..]
                    } else {
                        &s.name
                    }
                })
                .find(|s| is_derive_registrar_symbol(s))
                .map(&str::to_owned)
        }
        _ => return Ok(None),
    };
    return Ok(name);
}

/// Loads dynamic library in platform dependent manner.
///
/// For unix, you have to use RTLD_DEEPBIND flag to escape problems described
/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample)
/// and [here](https://github.com/rust-lang/rust/issues/60593).
///
/// Usage of RTLD_DEEPBIND
/// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
///
/// It seems that on Windows that behaviour is default, so we do nothing in that case.
#[cfg(windows)]
fn load_library(file: &Path) -> Result<Library, libloading::Error> {
    Library::new(file)
}

#[cfg(unix)]
fn load_library(file: &Path) -> Result<Library, libloading::Error> {
    use libloading::os::unix::Library as UnixLibrary;
    use std::os::raw::c_int;

    const RTLD_NOW: c_int = 0x00002;
    const RTLD_DEEPBIND: c_int = 0x00008;

    UnixLibrary::open(Some(file), RTLD_NOW | RTLD_DEEPBIND).map(|lib| lib.into())
}

struct ProcMacroLibraryLibloading {
    // Hold the dylib to prevent it from unloading
    _lib: Library,
    exported_macros: Vec<bridge::client::ProcMacro>,
}

impl ProcMacroLibraryLibloading {
    fn open(file: &Path) -> io::Result<Self> {
        let symbol_name = find_registrar_symbol(file)?.ok_or_else(|| {
            invalid_data_err(format!("Cannot find registrar symbol in file {}", file.display()))
        })?;

        let lib = load_library(file).map_err(invalid_data_err)?;
        let exported_macros = {
            let macros: libloading::Symbol<&&[bridge::client::ProcMacro]> =
                unsafe { lib.get(symbol_name.as_bytes()) }.map_err(invalid_data_err)?;
            macros.to_vec()
        };

        Ok(ProcMacroLibraryLibloading { _lib: lib, exported_macros })
    }
}

pub struct Expander {
    inner: ProcMacroLibraryLibloading,
}

impl Expander {
    pub fn new(lib: &Path) -> io::Result<Expander> {
        // Some libraries for dynamic loading require canonicalized path even when it is
        // already absolute
        let lib = lib.canonicalize()?;

        let lib = ensure_file_with_lock_free_access(&lib)?;

        let library = ProcMacroLibraryLibloading::open(&lib)?;

        Ok(Expander { inner: library })
    }

    pub fn expand(
        &self,
        macro_name: &str,
        macro_body: &ra_tt::Subtree,
        attributes: Option<&ra_tt::Subtree>,
    ) -> Result<ra_tt::Subtree, bridge::PanicMessage> {
        let parsed_body = TokenStream::with_subtree(macro_body.clone());

        let parsed_attributes = attributes
            .map_or(crate::rustc_server::TokenStream::new(), |attr| {
                TokenStream::with_subtree(attr.clone())
            });

        for proc_macro in &self.inner.exported_macros {
            match proc_macro {
                bridge::client::ProcMacro::CustomDerive { trait_name, client, .. }
                    if *trait_name == macro_name =>
                {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_body,
                    );
                    return res.map(|it| it.subtree);
                }
                bridge::client::ProcMacro::Bang { name, client } if *name == macro_name => {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_body,
                    );
                    return res.map(|it| it.subtree);
                }
                bridge::client::ProcMacro::Attr { name, client } if *name == macro_name => {
                    let res = client.run(
                        &crate::proc_macro::bridge::server::SameThread,
                        crate::rustc_server::Rustc::default(),
                        parsed_attributes,
                        parsed_body,
                    );
                    return res.map(|it| it.subtree);
                }
                _ => continue,
            }
        }

        Err(bridge::PanicMessage::String("Nothing to expand".to_string()))
    }

    pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> {
        self.inner
            .exported_macros
            .iter()
            .map(|proc_macro| match proc_macro {
                bridge::client::ProcMacro::CustomDerive { trait_name, .. } => {
                    (trait_name.to_string(), ProcMacroKind::CustomDerive)
                }
                bridge::client::ProcMacro::Bang { name, .. } => {
                    (name.to_string(), ProcMacroKind::FuncLike)
                }
                bridge::client::ProcMacro::Attr { name, .. } => {
                    (name.to_string(), ProcMacroKind::Attr)
                }
            })
            .collect()
    }
}

/// Copy the dylib to temp directory to prevent locking in Windows
#[cfg(windows)]
fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
    use std::{ffi::OsString, time::SystemTime};

    let mut to = std::env::temp_dir();

    let file_name = path.file_name().ok_or_else(|| {
        io::Error::new(
            io::ErrorKind::InvalidInput,
            format!("File path is invalid: {}", path.display()),
        )
    })?;

    // generate a time deps unique number
    let t = SystemTime::now().duration_since(std::time::UNIX_EPOCH).expect("Time went backwards");

    let mut unique_name = OsString::from(t.as_millis().to_string());
    unique_name.push(file_name);

    to.push(unique_name);
    std::fs::copy(path, &to).unwrap();
    Ok(to)
}

#[cfg(unix)]
fn ensure_file_with_lock_free_access(path: &Path) -> io::Result<PathBuf> {
    Ok(path.to_path_buf())
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{context::Context, filters};

use diem_config::config::ApiConfig;
use diem_types::chain_id::ChainId;
use storage_interface::MoveDbReader;

use std::sync::Arc;
use tokio::runtime::{Builder, Runtime};

/// Creates HTTP server (warp-based)
/// Returns handle to corresponding Tokio runtime
pub fn bootstrap(chain_id: ChainId, db: Arc<dyn MoveDbReader>, config: &ApiConfig) -> Runtime {
    let runtime = Builder::new_multi_thread()
        .thread_name("api")
        .enable_all()
        .build()
        .expect("[api] failed to create runtime");

    let address = config.address.clone();
    runtime.spawn(async move {
        let service = Arc::new(Context::new(chain_id, db));
        let routes = filters::routes(service);
        let server = warp::serve(routes).bind(address);
        server.await
    });
    runtime
}
<commit_msg>fix lint<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::{context::Context, filters};

use diem_config::config::ApiConfig;
use diem_types::chain_id::ChainId;
use storage_interface::MoveDbReader;

use std::sync::Arc;
use tokio::runtime::{Builder, Runtime};

/// Creates HTTP server (warp-based)
/// Returns handle to corresponding Tokio runtime
pub fn bootstrap(chain_id: ChainId, db: Arc<dyn MoveDbReader>, config: &ApiConfig) -> Runtime {
    let runtime = Builder::new_multi_thread()
        .thread_name("api")
        .enable_all()
        .build()
        .expect("[api] failed to create runtime");

    let address = config.address;
    runtime.spawn(async move {
        let service = Arc::new(Context::new(chain_id, db));
        let routes = filters::routes(service);
        let server = warp::serve(routes).bind(address);
        server.await
    });
    runtime
}
<|endoftext|>


<commit_before>extern crate syntect;
use syntect::parsing::SyntaxSet;
use syntect::highlighting::{Theme, ThemeSet, Style};
use syntect::util::as_24_bit_terminal_escaped;
use syntect::easy::HighlightFile;

use std::io::BufRead;

fn load_theme(path: &String) -> Theme {
    // TODO: cache this
    ThemeSet::get_theme(path).unwrap()
}

fn main() {
    let ss = SyntaxSet::load_defaults_newlines(); // note we load the version with newlines
    let ts = ThemeSet::load_defaults();

    let args: Vec<String> = std::env::args().collect();
    let src;
    let theme;
    let themeRef;

    if args.len() < 2 {
        println!("USAGE: ./syncat [THEME_FILE] SRC_FILE");
        return;
    } else if args.len() == 2 {
        themeRef = &ts.themes["base16-ocean.dark"];
        src = &args[1];
    } else {
        theme = load_theme(&args[1]);
        themeRef = &theme;
        src = &args[2];
    }

    let mut highlighter = HighlightFile::new(src, &ss, themeRef).unwrap();

    // We use read_line instead of `for line in highlighter.reader.lines()` because that
    // doesn't return strings with a `\n`, and including the `\n` gets us more robust highlighting.
    // See the documentation for `SyntaxSet::load_syntaxes`.
    // It also allows re-using the line buffer, which should be a tiny bit faster.
    let mut line = String::new();
    while highlighter.reader.read_line(&mut line).unwrap() > 0 {
        {
            let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight(&line);
            print!("{}", as_24_bit_terminal_escaped(&regions[..], true));
        }
        line.clear();
    }
}
<commit_msg>syncat: cache scheme<commit_after>extern crate syntect;
use std::path::Path;
use syntect::parsing::SyntaxSet;
use syntect::highlighting::{Theme, ThemeSet, Style};
use syntect::util::as_24_bit_terminal_escaped;
use syntect::easy::HighlightFile;
use syntect::dumps::{from_dump_file, dump_to_file};

use std::io::BufRead;

fn load_theme(tm_file: &String) -> Theme {
    let tm_path = Path::new(tm_file);
    let tm_cache = tm_path.with_extension("themedump");

    if tm_cache.exists() {
        from_dump_file(tm_cache).unwrap()
    } else {
        let theme = ThemeSet::get_theme(tm_path).unwrap();
        dump_to_file(&theme, tm_cache).unwrap();
        theme

    }
}

fn main() {
    let ss = SyntaxSet::load_defaults_newlines(); // note we load the version with newlines
    let ts = ThemeSet::load_defaults();

    let args: Vec<String> = std::env::args().collect();
    let src;
    let theme;
    let theme_ref;

    if args.len() < 2 {
        println!("USAGE: ./syncat [THEME_FILE] SRC_FILE");
        return;
    } else if args.len() == 2 {
        theme_ref = &ts.themes["base16-ocean.dark"];
        src = &args[1];
    } else {
        theme = load_theme(&args[1]);
        theme_ref = &theme;
        src = &args[2];
    }

    let mut highlighter = HighlightFile::new(src, &ss, theme_ref).unwrap();

    // We use read_line instead of `for line in highlighter.reader.lines()` because that
    // doesn't return strings with a `\n`, and including the `\n` gets us more robust highlighting.
    // See the documentation for `SyntaxSet::load_syntaxes`.
    // It also allows re-using the line buffer, which should be a tiny bit faster.
    let mut line = String::new();
    while highlighter.reader.read_line(&mut line).unwrap() > 0 {
        {
            let regions: Vec<(Style, &str)> = highlighter.highlight_lines.highlight(&line);
            print!("{}", as_24_bit_terminal_escaped(&regions[..], true));
        }
        line.clear();
    }
}
<|endoftext|>