<commit_before>use std::time::Duration;
use std::thread;
use std::cmp;
use std::cell::RefCell;

use game::*;
use ecs::*;
use util::Schedule;

const FAILED_ACTION_DELAY: u64 = 16;
const MIN_TURN_TIME: u64 = 1;

pub const TURN_DURATION_BASE: u64 = 16;
pub const ENV_TURN_OFFSET: u64 = 0;
pub const NPC_TURN_OFFSET: u64 = 1;
pub const PC_TURN_OFFSET: u64 = 2;

#[derive(Clone, Copy)]
pub struct ActionEnv<'a> {
    pub ecs: &'a EcsCtx,
    pub id: u64,
}

#[derive(Clone, Copy)]
pub struct Turn<'a> {
    pub ecs: &'a EcsCtx,
    pub id: u64,
}

pub enum TurnResolution {
    Quit,
    Schedule(EntityId, u64),
}

impl TurnResolution {
    pub fn game_continues(&self) -> bool {
        match *self {
            TurnResolution::Quit => false,
            _ => true,
        }
    }
}

pub struct TurnEnv<'a, 'b: 'a, Renderer: 'a + KnowledgeRenderer> {
    pub turn_id: u64,
    pub action_id: &'a mut u64,
    pub level_id: LevelId,
    pub entity_id: EntityId,
    pub pc_id: EntityId,
    pub renderer: &'a RefCell<Renderer>,
    pub ecs: &'b mut EcsCtx,
    pub spatial_hash: &'b mut SpatialHashTable,
    pub behaviour_ctx: &'a BehaviourCtx<Renderer>,
    pub rules: &'a Vec<Box<Rule>>,
    pub rule_resolution: &'a mut RuleResolution,
    pub ecs_action: &'a mut EcsAction,
    pub action_schedule: &'a mut Schedule<ActionArgs>,
    pub turn_schedule: &'a mut Schedule<EntityId>,
    pub pc_observer: &'a Shadowcast,
    pub entity_ids: &'a EntityIdReserver,
    pub rng: &'a GameRng,
}

impl<'a> Turn<'a> {
    pub fn new(ecs: &'a EcsCtx, id: u64) -> Self {
        Turn {
            ecs: ecs,
            id: id,
        }
    }
}

impl<'a> ActionEnv<'a> {
    pub fn new(ecs: &'a EcsCtx, id: u64) -> Self {
        ActionEnv {
            ecs: ecs,
            id: id,
        }
    }
}

impl<'a, 'b, Renderer: KnowledgeRenderer> TurnEnv<'a, 'b, Renderer> {
    pub fn turn(&mut self) -> Result<TurnResolution> {

        self.pc_render()?;

        let resolution = self.take_turn()?;

        match resolution {
            TurnResolution::Schedule(id, old_delay) => {
                let new_delay = if let Some(delay) = self.process_transformation()? {
                    delay
                } else {
                    old_delay
                };

                Ok(TurnResolution::Schedule(id, new_delay))
            }
            other => Ok(other),
        }
    }

    fn process_transformation(&mut self) -> Result<Option<u64>> {
        if let Some(transformation) = self.get_transformation() {
            let action_args = transformation.to_action_args(self.entity_id);
            self.try_commit_action(action_args)?;

            let delay = self.ecs.turn_time(self.entity_id);
            return Ok(delay);
        }

        Ok(None)
    }

    fn get_transformation(&self) -> Option<TransformationType> {
        // The state of the cell in which an actor ends their turn determines
        // whether a transformation will occur.

        let entity = self.ecs.entity(self.entity_id);

        if let Some(position) = entity.position() {
            if let Some(transformation_state) = entity.transformation_state() {
                if self.spatial_hash.get(position).moon() {
                    if transformation_state == TransformationState::Real {
                        return entity.transformation_type();
                    }
                } else {
                    if transformation_state == TransformationState::Other {
                        return entity.transformation_type();
                    }
                }
            }
        }

        None
    }

    fn take_turn(&mut self) -> Result<TurnResolution> {
        loop {
            match self.get_meta_action()? {
                MetaAction::External(External::Quit) => return Ok(TurnResolution::Quit),
                MetaAction::ActionArgs(action_args) => {
                    if let Some(delay) = self.try_commit_action(action_args)? {
                        self.declare_action_return(true)?;
                        return Ok(TurnResolution::Schedule(self.entity_id, delay));
                    } else {
                        self.declare_action_return(false)?;
                        if self.is_pc_turn() {
                            continue;
                        } else {
                            return Ok(TurnResolution::Schedule(self.entity_id, FAILED_ACTION_DELAY));
                        }
                    }
                }
            }
        }
    }

    fn is_pc_turn(&self) -> bool {
        self.entity_id == self.pc_id
    }

    fn check_rules(&mut self) -> Result<()> {
        self.rule_resolution.reset();

        let rule_env = RuleEnv {
            ecs: self.ecs,
            spatial_hash: self.spatial_hash,
        };

        for rule in self.rules {
            rule.check(rule_env, self.ecs_action, self.rule_resolution)?;

            if self.rule_resolution.is_reject() {
                return Ok(())
            }
        }
        Ok(())
    }

    fn commit(&mut self) {
        self.spatial_hash.update(ActionEnv::new(self.ecs, *self.action_id), self.ecs_action);
        self.ecs.commit(self.ecs_action);
    }

    fn pc_render(&mut self) -> Result<bool> {

        let entity = self.ecs.entity(self.pc_id);

        if !self.ecs.contains_should_render(self.entity_id) {
            return Ok(false);
        }

        let mut knowledge = entity.drawable_knowledge_borrow_mut().ok_or(Error::MissingComponent)?;
        let level_knowledge = knowledge.level_mut_or_insert_size(self.level_id,
                                                                 self.spatial_hash.width(),
                                                                 self.spatial_hash.height());
        let position = entity.position().ok_or(Error::MissingComponent)?;
        let vision_distance = entity.vision_distance().ok_or(Error::MissingComponent)?;
        let action_env = ActionEnv::new(self.ecs, *self.action_id);

        if self.pc_observer.observe(position, self.spatial_hash, vision_distance, level_knowledge, action_env) {
            self.renderer.borrow_mut().render(level_knowledge, *self.action_id, position);
            Ok(true)
        } else {
            Ok(false)
        }
    }

    fn try_commit_action(&mut self, action: ActionArgs) -> Result<Option<u64>> {

        let mut turn_time = self.ecs.turn_time(self.entity_id);
        let mut first = true;

        self.action_schedule.insert(action, 0);

        while let Some(action_event) = self.action_schedule.next() {

            // render the scene if time has passed
            if action_event.time_delta != 0 {
                if self.pc_render()? {
                    // if the change in scene was visible, add a delay
                    thread::sleep(Duration::from_millis(action_event.time_delta));
                }
            }

            *self.action_id += 1;

            // construct an action from the action args
            action_event.event.to_action(&mut self.ecs_action, self.ecs, self.spatial_hash, self.entity_ids)?;

            self.check_rules()?;

            let mut action_time = 0;

            if self.rule_resolution.is_accept() {
                if first {
                    first = false;
                    if let Some(alternative_turn_time) = self.ecs_action.alternative_turn_time() {
                        turn_time = Some(alternative_turn_time);
                    }
                }
                action_time = self.ecs_action.action_time_ms().unwrap_or(0);

                self.commit();
            } else {
                // Committing the action clears its data.
                // It must be cleared explicitly if the action is rejected.
                self.ecs_action.clear();
            }

            for reaction in self.rule_resolution.drain_reactions() {
                self.action_schedule.insert(reaction.action, action_time + reaction.delay);
            }
        }

        if first {
            return Ok(None);
        }

        Ok(turn_time.map(|t| cmp::max(t, MIN_TURN_TIME)))
    }

    fn get_meta_action(&self) -> Result<MetaAction> {
        let entity = self.ecs.entity(self.entity_id);
        let mut behaviour_state = entity.behaviour_state_borrow_mut().ok_or(Error::MissingComponent)?;
        if !behaviour_state.is_initialised() {
            let behaviour_type = entity.behaviour_type().ok_or(Error::MissingComponent)?;
            behaviour_state.initialise(self.behaviour_ctx.graph(), self.behaviour_ctx.nodes().index(behaviour_type))?;
        }
        let input = BehaviourInput {
            entity: entity,
            spatial_hash: self.spatial_hash,
            level_id: self.level_id,
            action_env: ActionEnv::new(self.ecs, *self.action_id),
            renderer: self.renderer,
            rng: self.rng,
        };
        Ok(behaviour_state.run(self.behaviour_ctx.graph(), input)?)
    }

    fn declare_action_return(&self, value: bool) -> Result<()> {
        let entity = self.ecs.entity(self.entity_id);
        let mut behaviour_state = entity.behaviour_state_borrow_mut().ok_or(Error::MissingComponent)?;
        behaviour_state.declare_return(value)?;
        Ok(())
    }
}
<commit_msg>Meaningful names for turn lifetimes<commit_after>use std::time::Duration;
use std::thread;
use std::cmp;
use std::cell::RefCell;

use game::*;
use ecs::*;
use util::Schedule;

const FAILED_ACTION_DELAY: u64 = 16;
const MIN_TURN_TIME: u64 = 1;

pub const TURN_DURATION_BASE: u64 = 16;
pub const ENV_TURN_OFFSET: u64 = 0;
pub const NPC_TURN_OFFSET: u64 = 1;
pub const PC_TURN_OFFSET: u64 = 2;

#[derive(Clone, Copy)]
pub struct ActionEnv<'game> {
    pub ecs: &'game EcsCtx,
    pub id: u64,
}

#[derive(Clone, Copy)]
pub struct Turn<'game> {
    pub ecs: &'game EcsCtx,
    pub id: u64,
}

pub enum TurnResolution {
    Quit,
    Schedule(EntityId, u64),
}

impl TurnResolution {
    pub fn game_continues(&self) -> bool {
        match *self {
            TurnResolution::Quit => false,
            _ => true,
        }
    }
}

pub struct TurnEnv<'game, 'level: 'game, Renderer: 'game + KnowledgeRenderer> {
    pub turn_id: u64,
    pub action_id: &'game mut u64,
    pub level_id: LevelId,
    pub entity_id: EntityId,
    pub pc_id: EntityId,
    pub renderer: &'game RefCell<Renderer>,
    pub ecs: &'level mut EcsCtx,
    pub spatial_hash: &'level mut SpatialHashTable,
    pub behaviour_ctx: &'game BehaviourCtx<Renderer>,
    pub rules: &'game Vec<Box<Rule>>,
    pub rule_resolution: &'game mut RuleResolution,
    pub ecs_action: &'game mut EcsAction,
    pub action_schedule: &'game mut Schedule<ActionArgs>,
    pub turn_schedule: &'game mut Schedule<EntityId>,
    pub pc_observer: &'game Shadowcast,
    pub entity_ids: &'game EntityIdReserver,
    pub rng: &'game GameRng,
}

impl<'game> Turn<'game> {
    pub fn new(ecs: &'game EcsCtx, id: u64) -> Self {
        Turn {
            ecs: ecs,
            id: id,
        }
    }
}

impl<'game> ActionEnv<'game> {
    pub fn new(ecs: &'game EcsCtx, id: u64) -> Self {
        ActionEnv {
            ecs: ecs,
            id: id,
        }
    }
}

impl<'game, 'level, Renderer: KnowledgeRenderer> TurnEnv<'game, 'level, Renderer> {
    pub fn turn(&mut self) -> Result<TurnResolution> {

        self.pc_render()?;

        let resolution = self.take_turn()?;

        match resolution {
            TurnResolution::Schedule(id, old_delay) => {
                let new_delay = if let Some(delay) = self.process_transformation()? {
                    delay
                } else {
                    old_delay
                };

                Ok(TurnResolution::Schedule(id, new_delay))
            }
            other => Ok(other),
        }
    }

    fn process_transformation(&mut self) -> Result<Option<u64>> {
        if let Some(transformation) = self.get_transformation() {
            let action_args = transformation.to_action_args(self.entity_id);
            self.try_commit_action(action_args)?;

            let delay = self.ecs.turn_time(self.entity_id);
            return Ok(delay);
        }

        Ok(None)
    }

    fn get_transformation(&self) -> Option<TransformationType> {
        // The state of the cell in which an actor ends their turn determines
        // whether a transformation will occur.

        let entity = self.ecs.entity(self.entity_id);

        if let Some(position) = entity.position() {
            if let Some(transformation_state) = entity.transformation_state() {
                if self.spatial_hash.get(position).moon() {
                    if transformation_state == TransformationState::Real {
                        return entity.transformation_type();
                    }
                } else {
                    if transformation_state == TransformationState::Other {
                        return entity.transformation_type();
                    }
                }
            }
        }

        None
    }

    fn take_turn(&mut self) -> Result<TurnResolution> {
        loop {
            match self.get_meta_action()? {
                MetaAction::External(External::Quit) => return Ok(TurnResolution::Quit),
                MetaAction::ActionArgs(action_args) => {
                    if let Some(delay) = self.try_commit_action(action_args)? {
                        self.declare_action_return(true)?;
                        return Ok(TurnResolution::Schedule(self.entity_id, delay));
                    } else {
                        self.declare_action_return(false)?;
                        if self.is_pc_turn() {
                            continue;
                        } else {
                            return Ok(TurnResolution::Schedule(self.entity_id, FAILED_ACTION_DELAY));
                        }
                    }
                }
            }
        }
    }

    fn is_pc_turn(&self) -> bool {
        self.entity_id == self.pc_id
    }

    fn check_rules(&mut self) -> Result<()> {
        self.rule_resolution.reset();

        let rule_env = RuleEnv {
            ecs: self.ecs,
            spatial_hash: self.spatial_hash,
        };

        for rule in self.rules {
            rule.check(rule_env, self.ecs_action, self.rule_resolution)?;

            if self.rule_resolution.is_reject() {
                return Ok(())
            }
        }
        Ok(())
    }

    fn commit(&mut self) {
        self.spatial_hash.update(ActionEnv::new(self.ecs, *self.action_id), self.ecs_action);
        self.ecs.commit(self.ecs_action);
    }

    fn pc_render(&mut self) -> Result<bool> {

        let entity = self.ecs.entity(self.pc_id);

        if !self.ecs.contains_should_render(self.entity_id) {
            return Ok(false);
        }

        let mut knowledge = entity.drawable_knowledge_borrow_mut().ok_or(Error::MissingComponent)?;
        let level_knowledge = knowledge.level_mut_or_insert_size(self.level_id,
                                                                 self.spatial_hash.width(),
                                                                 self.spatial_hash.height());
        let position = entity.position().ok_or(Error::MissingComponent)?;
        let vision_distance = entity.vision_distance().ok_or(Error::MissingComponent)?;
        let action_env = ActionEnv::new(self.ecs, *self.action_id);

        if self.pc_observer.observe(position, self.spatial_hash, vision_distance, level_knowledge, action_env) {
            self.renderer.borrow_mut().render(level_knowledge, *self.action_id, position);
            Ok(true)
        } else {
            Ok(false)
        }
    }

    fn try_commit_action(&mut self, action: ActionArgs) -> Result<Option<u64>> {

        let mut turn_time = self.ecs.turn_time(self.entity_id);
        let mut first = true;

        self.action_schedule.insert(action, 0);

        while let Some(action_event) = self.action_schedule.next() {

            // render the scene if time has passed
            if action_event.time_delta != 0 {
                if self.pc_render()? {
                    // if the change in scene was visible, add a delay
                    thread::sleep(Duration::from_millis(action_event.time_delta));
                }
            }

            *self.action_id += 1;

            // construct an action from the action args
            action_event.event.to_action(&mut self.ecs_action, self.ecs, self.spatial_hash, self.entity_ids)?;

            self.check_rules()?;

            let mut action_time = 0;

            if self.rule_resolution.is_accept() {
                if first {
                    first = false;
                    if let Some(alternative_turn_time) = self.ecs_action.alternative_turn_time() {
                        turn_time = Some(alternative_turn_time);
                    }
                }
                action_time = self.ecs_action.action_time_ms().unwrap_or(0);

                self.commit();
            } else {
                // Committing the action clears its data.
                // It must be cleared explicitly if the action is rejected.
                self.ecs_action.clear();
            }

            for reaction in self.rule_resolution.drain_reactions() {
                self.action_schedule.insert(reaction.action, action_time + reaction.delay);
            }
        }

        if first {
            return Ok(None);
        }

        Ok(turn_time.map(|t| cmp::max(t, MIN_TURN_TIME)))
    }

    fn get_meta_action(&self) -> Result<MetaAction> {
        let entity = self.ecs.entity(self.entity_id);
        let mut behaviour_state = entity.behaviour_state_borrow_mut().ok_or(Error::MissingComponent)?;
        if !behaviour_state.is_initialised() {
            let behaviour_type = entity.behaviour_type().ok_or(Error::MissingComponent)?;
            behaviour_state.initialise(self.behaviour_ctx.graph(), self.behaviour_ctx.nodes().index(behaviour_type))?;
        }
        let input = BehaviourInput {
            entity: entity,
            spatial_hash: self.spatial_hash,
            level_id: self.level_id,
            action_env: ActionEnv::new(self.ecs, *self.action_id),
            renderer: self.renderer,
            rng: self.rng,
        };
        Ok(behaviour_state.run(self.behaviour_ctx.graph(), input)?)
    }

    fn declare_action_return(&self, value: bool) -> Result<()> {
        let entity = self.ecs.entity(self.entity_id);
        let mut behaviour_state = entity.behaviour_state_borrow_mut().ok_or(Error::MissingComponent)?;
        behaviour_state.declare_return(value)?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Gists interface

use std::collections::HashMap;
use std::hash::Hash;

use futures::future;
use hyper::client::Connect;
use url::form_urlencoded;

use {Github, Future, serde_json};
use users::User;

/// reference to gists associated with a github user
pub struct UserGists<C>
where
    C: Clone + Connect,
{
    github: Github<C>,
    owner: String,
}

impl<C: Clone + Connect> UserGists<C> {
    #[doc(hidden)]
    pub fn new<O>(github: Github<C>, owner: O) -> Self
    where
        O: Into<String>,
    {
        UserGists {
            github: github,
            owner: owner.into(),
        }
    }

    pub fn list(&self, options: &GistListOptions) -> Future<Vec<Gist>> {
        let mut uri = vec![format!("/users/{}/gists", self.owner)];
        if let Some(query) = options.serialize() {
            uri.push(query);
        }
        self.github.get(&uri.join("?"))
    }
}

pub struct Gists<C>
where
    C: Clone + Connect,
{
    github: Github<C>,
}

impl<C: Clone + Connect> Gists<C> {
    #[doc(hidden)]
    pub fn new(github: Github<C>) -> Self {
        Self { github }
    }

    fn path(&self, more: &str) -> String {
        format!("/gists{}", more)
    }

    pub fn star(&self, id: &str) -> Future<()> {
        self.github.put_no_response(
            &self.path(&format!("/{}/star", id)),
            Vec::new(),
        )
    }

    pub fn unstar(&self, id: &str) -> Future<()> {
        self.github.delete(&self.path(&format!("/{}/star", id)))
    }

    pub fn fork(&self, id: &str) -> Future<Gist> {
        self.github.post(
            &self.path(&format!("/{}/forks", id)),
            Vec::new(),
        )
    }

    pub fn forks(&self, id: &str) -> Future<Vec<GistFork>> {
        self.github.get(&self.path(&format!("/{}/forks", id)))
    }

    pub fn delete(&self, id: &str) -> Future<()> {
        self.github.delete(&self.path(&format!("/{}", id)))
    }

    pub fn get(&self, id: &str) -> Future<Gist> {
        self.github.get(&self.path(&format!("/{}", id)))
    }

    pub fn getrev(&self, id: &str, sha: &str) -> Future<Gist> {
        self.github.get(&self.path(&format!("/{}/{}", id, sha)))
    }

    pub fn list(&self, options: &GistListOptions) -> Future<Vec<Gist>> {
        let mut uri = vec![self.path("")];
        if let Some(query) = options.serialize() {
            uri.push(query);
        }
        self.github.get::<Vec<Gist>>(&uri.join("?"))
    }

    pub fn public(&self) -> Future<Vec<Gist>> {
        self.github.get(&self.path("/public"))
    }

    pub fn starred(&self) -> Future<Vec<Gist>> {
        self.github.get(&self.path("/starred"))
    }

    pub fn create(&self, gist: &GistOptions) -> Future<Gist> {
        self.github.post(&self.path(""), json!(gist))
    }

    // todo: edit
}

// representations

#[derive(Default)]
pub struct GistListOptions {
    params: HashMap<&'static str, String>,
}

impl GistListOptions {
    pub fn since<T>(timestamp: T) -> GistListOptions
    where
        T: Into<String>,
    {
        let mut params = HashMap::new();
        params.insert("since", timestamp.into());
        GistListOptions { params: params }
    }

    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Option<String> {
        if self.params.is_empty() {
            None
        } else {
            let encoded: String = form_urlencoded::Serializer::new(String::new())
                .extend_pairs(&self.params)
                .finish();
            Some(encoded)
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct GistFile {
    pub size: u64,
    pub raw_url: String,
    pub content: Option<String>,
    #[serde(rename = "type")]
    pub content_type: String,
    pub truncated: Option<bool>,
    pub language: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct Gist {
    pub url: String,
    pub forks_url: String,
    pub commits_url: String,
    pub id: String,
    pub description: Option<String>,
    pub public: bool,
    pub owner: User,
    pub user: Option<User>,
    pub files: HashMap<String, GistFile>,
    pub truncated: bool,
    pub comments: u64,
    pub comments_url: String,
    pub html_url: String,
    pub git_pull_url: String,
    pub git_push_url: String,
    pub created_at: String,
    pub updated_at: String,
}

#[derive(Debug, Deserialize)]
pub struct GistFork {
    pub user: User,
    pub url: String,
    pub id: String,
    pub created_at: String,
    pub updated_at: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct Content {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub filename: Option<String>,
    pub content: String,
}

impl Content {
    pub fn new<F, C>(filename: Option<F>, content: C) -> Content
    where
        F: Into<String>,
        C: Into<String>,
    {
        Content {
            filename: filename.map(|f| f.into()),
            content: content.into(),
        }
    }
}

pub struct GistOptionsBuilder(GistOptions);

impl GistOptionsBuilder {
    pub fn new<K, V>(files: HashMap<K, V>) -> GistOptionsBuilder
    where
        K: Clone + Hash + Eq + Into<String>,
        V: Into<String>,
    {
        let mut contents = HashMap::new();
        for (k, v) in files.into_iter() {
            contents.insert(k.into(), Content::new(None as Option<String>, v.into()));
        }
        GistOptionsBuilder(GistOptions {
            files: contents,
            ..Default::default()
        })
    }

    pub fn description<D>(&mut self, desc: D) -> &mut GistOptionsBuilder
    where
        D: Into<String>,
    {
        self.0.description = Some(desc.into());
        self
    }

    pub fn public(&mut self, p: bool) -> &mut GistOptionsBuilder {
        self.0.public = Some(p);
        self
    }

    pub fn build(&self) -> GistOptions {
        GistOptions {
            files: self.0.files.clone(),
            description: self.0.description.clone(),
            public: self.0.public,
        }
    }
}

#[derive(Debug, Default, Serialize)]
pub struct GistOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub public: Option<bool>,
    pub files: HashMap<String, Content>,
}

impl GistOptions {
    pub fn new<D, K, V>(desc: Option<D>, public: bool, files: HashMap<K, V>) -> GistOptions
    where
        D: Into<String>,
        K: Hash + Eq + Into<String>,
        V: Into<String>,
    {
        let mut contents = HashMap::new();
        for (k, v) in files.into_iter() {
            contents.insert(k.into(), Content::new(None as Option<String>, v.into()));
        }
        GistOptions {
            description: desc.map(|d| d.into()),
            public: Some(public),
            files: contents,
        }
    }

    pub fn builder<K, V>(files: HashMap<K, V>) -> GistOptionsBuilder
    where
        K: Clone + Hash + Eq + Into<String>,
        V: Into<String>,
    {
        GistOptionsBuilder::new(files)
    }
}

#[cfg(test)]
mod tests {
    use super::GistOptions;
    use serde::ser::Serialize;
    use serde_json;
    use std::collections::HashMap;

    fn test_encoding<E: Serialize>(tests: Vec<(E, &str)>) {
        for test in tests {
            match test {
                (k, v) => assert_eq!(serde_json::to_string(&k).unwrap(), v),
            }
        }
    }
    #[test]
    fn gist_reqs() {
        let mut files = HashMap::new();
        files.insert("foo", "bar");
        let tests = vec![
            (
                GistOptions::new(None as Option<String>, true, files.clone()),
                r#"{"public":true,"files":{"foo":{"content":"bar"}}}"#
            ),
            (
                GistOptions::new(Some("desc"), true, files.clone()),
                r#"{"description":"desc","public":true,"files":{"foo":{"content":"bar"}}}"#
            ),
        ];
        test_encoding(tests);
    }

    #[test]
    fn gist_req() {
        let mut files = HashMap::new();
        files.insert("test", "foo");
        let tests = vec![
            (
                GistOptions::builder(files.clone()).build(),
                r#"{"files":{"test":{"content":"foo"}}}"#
            ),
            (
                GistOptions::builder(files.clone())
                    .description("desc")
                    .build(),
                r#"{"description":"desc","files":{"test":{"content":"foo"}}}"#
            ),
            (
                GistOptions::builder(files.clone())
                    .description("desc")
                    .public(false)
                    .build(),
                r#"{"description":"desc","public":false,"files":{"test":{"content":"foo"}}}"#
            ),
        ];
        test_encoding(tests)
    }
}
<commit_msg>Anonymous Gists do not have an owner<commit_after>//! Gists interface

use std::collections::HashMap;
use std::hash::Hash;

use futures::future;
use hyper::client::Connect;
use url::form_urlencoded;

use {Github, Future, serde_json};
use users::User;

/// reference to gists associated with a github user
pub struct UserGists<C>
where
    C: Clone + Connect,
{
    github: Github<C>,
    owner: String,
}

impl<C: Clone + Connect> UserGists<C> {
    #[doc(hidden)]
    pub fn new<O>(github: Github<C>, owner: O) -> Self
    where
        O: Into<String>,
    {
        UserGists {
            github: github,
            owner: owner.into(),
        }
    }

    pub fn list(&self, options: &GistListOptions) -> Future<Vec<Gist>> {
        let mut uri = vec![format!("/users/{}/gists", self.owner)];
        if let Some(query) = options.serialize() {
            uri.push(query);
        }
        self.github.get(&uri.join("?"))
    }
}

pub struct Gists<C>
where
    C: Clone + Connect,
{
    github: Github<C>,
}

impl<C: Clone + Connect> Gists<C> {
    #[doc(hidden)]
    pub fn new(github: Github<C>) -> Self {
        Self { github }
    }

    fn path(&self, more: &str) -> String {
        format!("/gists{}", more)
    }

    pub fn star(&self, id: &str) -> Future<()> {
        self.github.put_no_response(
            &self.path(&format!("/{}/star", id)),
            Vec::new(),
        )
    }

    pub fn unstar(&self, id: &str) -> Future<()> {
        self.github.delete(&self.path(&format!("/{}/star", id)))
    }

    pub fn fork(&self, id: &str) -> Future<Gist> {
        self.github.post(
            &self.path(&format!("/{}/forks", id)),
            Vec::new(),
        )
    }

    pub fn forks(&self, id: &str) -> Future<Vec<GistFork>> {
        self.github.get(&self.path(&format!("/{}/forks", id)))
    }

    pub fn delete(&self, id: &str) -> Future<()> {
        self.github.delete(&self.path(&format!("/{}", id)))
    }

    pub fn get(&self, id: &str) -> Future<Gist> {
        self.github.get(&self.path(&format!("/{}", id)))
    }

    pub fn getrev(&self, id: &str, sha: &str) -> Future<Gist> {
        self.github.get(&self.path(&format!("/{}/{}", id, sha)))
    }

    pub fn list(&self, options: &GistListOptions) -> Future<Vec<Gist>> {
        let mut uri = vec![self.path("")];
        if let Some(query) = options.serialize() {
            uri.push(query);
        }
        self.github.get::<Vec<Gist>>(&uri.join("?"))
    }

    pub fn public(&self) -> Future<Vec<Gist>> {
        self.github.get(&self.path("/public"))
    }

    pub fn starred(&self) -> Future<Vec<Gist>> {
        self.github.get(&self.path("/starred"))
    }

    pub fn create(&self, gist: &GistOptions) -> Future<Gist> {
        self.github.post(&self.path(""), json!(gist))
    }

    // todo: edit
}

// representations

#[derive(Default)]
pub struct GistListOptions {
    params: HashMap<&'static str, String>,
}

impl GistListOptions {
    pub fn since<T>(timestamp: T) -> GistListOptions
    where
        T: Into<String>,
    {
        let mut params = HashMap::new();
        params.insert("since", timestamp.into());
        GistListOptions { params: params }
    }

    /// serialize options as a string. returns None if no options are defined
    pub fn serialize(&self) -> Option<String> {
        if self.params.is_empty() {
            None
        } else {
            let encoded: String = form_urlencoded::Serializer::new(String::new())
                .extend_pairs(&self.params)
                .finish();
            Some(encoded)
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct GistFile {
    pub size: u64,
    pub raw_url: String,
    pub content: Option<String>,
    #[serde(rename = "type")]
    pub content_type: String,
    pub truncated: Option<bool>,
    pub language: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct Gist {
    pub url: String,
    pub forks_url: String,
    pub commits_url: String,
    pub id: String,
    pub description: Option<String>,
    pub public: bool,
    pub owner: Option<User>,
    pub user: Option<User>,
    pub files: HashMap<String, GistFile>,
    pub truncated: bool,
    pub comments: u64,
    pub comments_url: String,
    pub html_url: String,
    pub git_pull_url: String,
    pub git_push_url: String,
    pub created_at: String,
    pub updated_at: String,
}

#[derive(Debug, Deserialize)]
pub struct GistFork {
    pub user: User,
    pub url: String,
    pub id: String,
    pub created_at: String,
    pub updated_at: String,
}

#[derive(Debug, Clone, Serialize)]
pub struct Content {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub filename: Option<String>,
    pub content: String,
}

impl Content {
    pub fn new<F, C>(filename: Option<F>, content: C) -> Content
    where
        F: Into<String>,
        C: Into<String>,
    {
        Content {
            filename: filename.map(|f| f.into()),
            content: content.into(),
        }
    }
}

pub struct GistOptionsBuilder(GistOptions);

impl GistOptionsBuilder {
    pub fn new<K, V>(files: HashMap<K, V>) -> GistOptionsBuilder
    where
        K: Clone + Hash + Eq + Into<String>,
        V: Into<String>,
    {
        let mut contents = HashMap::new();
        for (k, v) in files.into_iter() {
            contents.insert(k.into(), Content::new(None as Option<String>, v.into()));
        }
        GistOptionsBuilder(GistOptions {
            files: contents,
            ..Default::default()
        })
    }

    pub fn description<D>(&mut self, desc: D) -> &mut GistOptionsBuilder
    where
        D: Into<String>,
    {
        self.0.description = Some(desc.into());
        self
    }

    pub fn public(&mut self, p: bool) -> &mut GistOptionsBuilder {
        self.0.public = Some(p);
        self
    }

    pub fn build(&self) -> GistOptions {
        GistOptions {
            files: self.0.files.clone(),
            description: self.0.description.clone(),
            public: self.0.public,
        }
    }
}

#[derive(Debug, Default, Serialize)]
pub struct GistOptions {
    #[serde(skip_serializing_if = "Option::is_none")]
    pub description: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub public: Option<bool>,
    pub files: HashMap<String, Content>,
}

impl GistOptions {
    pub fn new<D, K, V>(desc: Option<D>, public: bool, files: HashMap<K, V>) -> GistOptions
    where
        D: Into<String>,
        K: Hash + Eq + Into<String>,
        V: Into<String>,
    {
        let mut contents = HashMap::new();
        for (k, v) in files.into_iter() {
            contents.insert(k.into(), Content::new(None as Option<String>, v.into()));
        }
        GistOptions {
            description: desc.map(|d| d.into()),
            public: Some(public),
            files: contents,
        }
    }

    pub fn builder<K, V>(files: HashMap<K, V>) -> GistOptionsBuilder
    where
        K: Clone + Hash + Eq + Into<String>,
        V: Into<String>,
    {
        GistOptionsBuilder::new(files)
    }
}

#[cfg(test)]
mod tests {
    use super::GistOptions;
    use serde::ser::Serialize;
    use serde_json;
    use std::collections::HashMap;

    fn test_encoding<E: Serialize>(tests: Vec<(E, &str)>) {
        for test in tests {
            match test {
                (k, v) => assert_eq!(serde_json::to_string(&k).unwrap(), v),
            }
        }
    }
    #[test]
    fn gist_reqs() {
        let mut files = HashMap::new();
        files.insert("foo", "bar");
        let tests = vec![
            (
                GistOptions::new(None as Option<String>, true, files.clone()),
                r#"{"public":true,"files":{"foo":{"content":"bar"}}}"#
            ),
            (
                GistOptions::new(Some("desc"), true, files.clone()),
                r#"{"description":"desc","public":true,"files":{"foo":{"content":"bar"}}}"#
            ),
        ];
        test_encoding(tests);
    }

    #[test]
    fn gist_req() {
        let mut files = HashMap::new();
        files.insert("test", "foo");
        let tests = vec![
            (
                GistOptions::builder(files.clone()).build(),
                r#"{"files":{"test":{"content":"foo"}}}"#
            ),
            (
                GistOptions::builder(files.clone())
                    .description("desc")
                    .build(),
                r#"{"description":"desc","files":{"test":{"content":"foo"}}}"#
            ),
            (
                GistOptions::builder(files.clone())
                    .description("desc")
                    .public(false)
                    .build(),
                r#"{"description":"desc","public":false,"files":{"test":{"content":"foo"}}}"#
            ),
        ];
        test_encoding(tests)
    }
}
<|endoftext|>


<commit_before>// SPDX-License-Identifier: MIT
// Copyright (C) 2018-present iced project and contributors

//! iced-x86 JavaScript bindings

#![allow(unknown_lints)]
#![warn(absolute_paths_not_starting_with_crate)]
#![warn(anonymous_parameters)]
#![warn(elided_lifetimes_in_paths)]
#![warn(explicit_outlives_requirements)]
#![warn(invalid_html_tags)]
#![warn(keyword_idents)]
#![warn(macro_use_extern_crate)]
#![warn(meta_variable_misuse)]
#![warn(missing_docs)]
#![warn(non_ascii_idents)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_lifetimes)]
#![warn(unused_must_use)]
#![warn(unused_qualifications)]
#![warn(unused_results)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::collapsible_if)]
#![allow(clippy::field_reassign_with_default)]
#![allow(clippy::manual_range_contains)]
#![allow(clippy::match_ref_pats)]
#![allow(clippy::ptr_eq)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::type_complexity)]
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::wrong_self_convention)]
#![warn(clippy::cloned_instead_of_copied)]
#![warn(clippy::dbg_macro)]
#![warn(clippy::debug_assert_with_mut_call)]
#![warn(clippy::default_trait_access)]
#![warn(clippy::doc_markdown)]
#![warn(clippy::empty_line_after_outer_attr)]
#![warn(clippy::expect_used)]
#![warn(clippy::explicit_into_iter_loop)]
#![warn(clippy::explicit_iter_loop)]
#![warn(clippy::fallible_impl_from)]
#![warn(clippy::get_unwrap)]
#![warn(clippy::implicit_saturating_sub)]
#![warn(clippy::large_digit_groups)]
#![warn(clippy::let_unit_value)]
#![warn(clippy::match_bool)]
#![warn(clippy::match_on_vec_items)]
#![warn(clippy::match_wild_err_arm)]
#![warn(clippy::missing_errors_doc)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
#![warn(clippy::rc_buffer)]
#![warn(clippy::redundant_closure)]
#![warn(clippy::redundant_closure_for_method_calls)]
#![warn(clippy::same_functions_in_if_condition)]
#![warn(clippy::todo)]
#![warn(clippy::unimplemented)]
#![warn(clippy::unreadable_literal)]
#![warn(clippy::unused_self)]
#![warn(clippy::unwrap_in_result)]
#![warn(clippy::unwrap_used)]
#![warn(clippy::used_underscore_binding)]
#![warn(clippy::useless_let_if_seq)]
#![warn(clippy::useless_transmute)]
#![warn(clippy::zero_sized_map_values)]

#[cfg(all(feature = "encoder", feature = "block_encoder"))]
mod block_encoder;
#[cfg(all(feature = "encoder", feature = "block_encoder"))]
mod block_encoder_options;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod cc;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info"), feature = "instr_create"))]
mod code;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod code_ext;
#[cfg(feature = "instr_api")]
mod code_size;
#[cfg(feature = "instr_info")]
#[cfg(feature = "instr_api")]
mod condition_code;
#[cfg(any(feature = "encoder", all(feature = "decoder", feature = "instr_info")))]
mod constant_offsets;
#[cfg(feature = "instr_info")]
mod cpuid_feature;
#[cfg(feature = "decoder")]
mod decoder;
#[cfg(feature = "decoder")]
mod decoder_error;
#[cfg(feature = "decoder")]
mod decoder_options;
#[cfg(feature = "encoder")]
mod encoder;
#[cfg(any(feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
mod encoding_kind;
#[cfg(any(feature = "decoder", feature = "instr_info", feature = "encoder", feature = "instr_api", feature = "instr_create"))]
mod ex_utils;
#[cfg(feature = "fast_fmt")]
mod fast_fmt;
#[cfg(any(feature = "instr_info", all(feature = "instr_info", feature = "instr_api")))]
mod flow_control;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod format_mnemonic_options;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod formatter;
#[cfg(feature = "instr_info")]
mod info;
mod instruction;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod mandatory_prefix;
#[cfg(feature = "instr_create")]
mod memory_operand;
#[cfg(any(feature = "instr_api", feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
mod memory_size;
#[cfg(feature = "instr_info")]
mod memory_size_ext;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod memory_size_options;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info")))]
mod mnemonic;
#[cfg(feature = "mvex")]
mod mvex_cvt_fn;
#[cfg(feature = "mvex")]
mod mvex_eh_bit;
#[cfg(feature = "mvex")]
mod mvex_rm_conv;
#[cfg(feature = "mvex")]
mod mvex_tt_lut;
#[cfg(feature = "instr_info")]
mod op_access;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_info;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_operand_kind;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_table_kind;
#[cfg(feature = "instr_api")]
mod op_kind;
#[cfg(any(feature = "instr_api", feature = "instr_info", feature = "instr_create"))]
mod register;
#[cfg(feature = "instr_info")]
mod register_ext;
#[cfg(feature = "instr_create")]
mod rep_prefix_kind;
#[cfg(feature = "instr_info")]
mod rflags_bits;
#[cfg(feature = "instr_api")]
mod rounding_control;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod tuple_type;

#[cfg(all(feature = "encoder", feature = "block_encoder"))]
pub use block_encoder::*;
#[cfg(all(feature = "encoder", feature = "block_encoder"))]
pub use block_encoder_options::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use cc::*;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info"), feature = "instr_create"))]
pub use code::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use code_ext::*;
#[cfg(feature = "instr_api")]
pub use code_size::*;
#[cfg(feature = "instr_info")]
#[cfg(feature = "instr_api")]
pub use condition_code::*;
#[cfg(any(feature = "encoder", all(feature = "decoder", feature = "instr_info")))]
pub use constant_offsets::*;
#[cfg(feature = "instr_info")]
pub use cpuid_feature::*;
#[cfg(feature = "decoder")]
pub use decoder::*;
#[cfg(feature = "decoder")]
pub use decoder_error::*;
#[cfg(feature = "decoder")]
pub use decoder_options::*;
#[cfg(feature = "encoder")]
pub use encoder::*;
#[cfg(any(feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
pub use encoding_kind::*;
#[cfg(feature = "fast_fmt")]
pub use fast_fmt::*;
#[cfg(any(feature = "instr_info", all(feature = "instr_info", feature = "instr_api")))]
pub use flow_control::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use format_mnemonic_options::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use formatter::*;
#[cfg(feature = "instr_info")]
pub use info::*;
pub use instruction::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use mandatory_prefix::*;
#[cfg(feature = "instr_create")]
pub use memory_operand::*;
#[cfg(any(feature = "instr_api", feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
pub use memory_size::*;
#[cfg(feature = "instr_info")]
pub use memory_size_ext::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use memory_size_options::*;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info")))]
pub use mnemonic::*;
#[cfg(feature = "mvex")]
pub use mvex_cvt_fn::*;
#[cfg(feature = "mvex")]
pub use mvex_eh_bit::*;
#[cfg(feature = "mvex")]
pub use mvex_rm_conv::*;
#[cfg(feature = "mvex")]
pub use mvex_tt_lut::*;
#[cfg(feature = "instr_info")]
pub use op_access::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_info::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_operand_kind::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_table_kind::*;
#[cfg(feature = "instr_api")]
pub use op_kind::*;
#[cfg(any(feature = "instr_api", feature = "instr_info", feature = "instr_create"))]
pub use register::*;
#[cfg(feature = "instr_info")]
pub use register_ext::*;
#[cfg(feature = "instr_create")]
pub use rep_prefix_kind::*;
#[cfg(feature = "instr_info")]
pub use rflags_bits::*;
#[cfg(feature = "instr_api")]
pub use rounding_control::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use tuple_type::*;
use wasm_bindgen::prelude::*;

/// Gets feature flags.
///
/// Flag | Value
/// -----|-------
/// 0x01 | `VEX`
/// 0x02 | `EVEX`
/// 0x04 | `XOP`
/// 0x08 | `3DNow!`
/// 0x10 | `MVEX`
#[wasm_bindgen(js_name = "getIcedFeatures")]
pub fn get_iced_features() -> u32 {
	#[allow(unused_mut)]
	let mut flags = 0;
	#[cfg(not(feature = "no_vex"))]
	{
		flags |= 1;
	}
	#[cfg(not(feature = "no_evex"))]
	{
		flags |= 2;
	}
	#[cfg(not(feature = "no_xop"))]
	{
		flags |= 4;
	}
	#[cfg(not(feature = "no_d3now"))]
	{
		flags |= 8;
	}
	#[cfg(feature = "mvex")]
	{
		flags |= 0x10;
	}
	flags
}
<commit_msg>Fix clippy warning due to `wasm-bindgen`<commit_after>// SPDX-License-Identifier: MIT
// Copyright (C) 2018-present iced project and contributors

//! iced-x86 JavaScript bindings

#![allow(unknown_lints)]
#![warn(absolute_paths_not_starting_with_crate)]
#![warn(anonymous_parameters)]
#![warn(elided_lifetimes_in_paths)]
#![warn(explicit_outlives_requirements)]
#![warn(invalid_html_tags)]
#![warn(keyword_idents)]
#![warn(macro_use_extern_crate)]
#![warn(meta_variable_misuse)]
#![warn(missing_docs)]
#![warn(non_ascii_idents)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_lifetimes)]
#![warn(unused_must_use)]
#![warn(unused_qualifications)]
#![warn(unused_results)]
#![allow(clippy::cast_lossless)]
#![allow(clippy::collapsible_else_if)]
#![allow(clippy::collapsible_if)]
#![allow(clippy::field_reassign_with_default)]
#![allow(clippy::manual_range_contains)]
#![allow(clippy::match_ref_pats)]
#![allow(clippy::ptr_eq)]
#![allow(clippy::too_many_arguments)]
#![allow(clippy::type_complexity)]
#![allow(clippy::unused_unit)] // wasm-bindgen 0.2.79 https://github.com/rustwasm/wasm-bindgen/issues/2774
#![allow(clippy::upper_case_acronyms)]
#![allow(clippy::wrong_self_convention)]
#![warn(clippy::cloned_instead_of_copied)]
#![warn(clippy::dbg_macro)]
#![warn(clippy::debug_assert_with_mut_call)]
#![warn(clippy::default_trait_access)]
#![warn(clippy::doc_markdown)]
#![warn(clippy::empty_line_after_outer_attr)]
#![warn(clippy::expect_used)]
#![warn(clippy::explicit_into_iter_loop)]
#![warn(clippy::explicit_iter_loop)]
#![warn(clippy::fallible_impl_from)]
#![warn(clippy::get_unwrap)]
#![warn(clippy::implicit_saturating_sub)]
#![warn(clippy::large_digit_groups)]
#![warn(clippy::let_unit_value)]
#![warn(clippy::match_bool)]
#![warn(clippy::match_on_vec_items)]
#![warn(clippy::match_wild_err_arm)]
#![warn(clippy::missing_errors_doc)]
#![warn(clippy::needless_borrow)]
#![warn(clippy::print_stderr)]
#![warn(clippy::print_stdout)]
#![warn(clippy::rc_buffer)]
#![warn(clippy::redundant_closure)]
#![warn(clippy::redundant_closure_for_method_calls)]
#![warn(clippy::same_functions_in_if_condition)]
#![warn(clippy::todo)]
#![warn(clippy::unimplemented)]
#![warn(clippy::unreadable_literal)]
#![warn(clippy::unused_self)]
#![warn(clippy::unwrap_in_result)]
#![warn(clippy::unwrap_used)]
#![warn(clippy::used_underscore_binding)]
#![warn(clippy::useless_let_if_seq)]
#![warn(clippy::useless_transmute)]
#![warn(clippy::zero_sized_map_values)]

#[cfg(all(feature = "encoder", feature = "block_encoder"))]
mod block_encoder;
#[cfg(all(feature = "encoder", feature = "block_encoder"))]
mod block_encoder_options;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod cc;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info"), feature = "instr_create"))]
mod code;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod code_ext;
#[cfg(feature = "instr_api")]
mod code_size;
#[cfg(feature = "instr_info")]
#[cfg(feature = "instr_api")]
mod condition_code;
#[cfg(any(feature = "encoder", all(feature = "decoder", feature = "instr_info")))]
mod constant_offsets;
#[cfg(feature = "instr_info")]
mod cpuid_feature;
#[cfg(feature = "decoder")]
mod decoder;
#[cfg(feature = "decoder")]
mod decoder_error;
#[cfg(feature = "decoder")]
mod decoder_options;
#[cfg(feature = "encoder")]
mod encoder;
#[cfg(any(feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
mod encoding_kind;
#[cfg(any(feature = "decoder", feature = "instr_info", feature = "encoder", feature = "instr_api", feature = "instr_create"))]
mod ex_utils;
#[cfg(feature = "fast_fmt")]
mod fast_fmt;
#[cfg(any(feature = "instr_info", all(feature = "instr_info", feature = "instr_api")))]
mod flow_control;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod format_mnemonic_options;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod formatter;
#[cfg(feature = "instr_info")]
mod info;
mod instruction;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod mandatory_prefix;
#[cfg(feature = "instr_create")]
mod memory_operand;
#[cfg(any(feature = "instr_api", feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
mod memory_size;
#[cfg(feature = "instr_info")]
mod memory_size_ext;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
mod memory_size_options;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info")))]
mod mnemonic;
#[cfg(feature = "mvex")]
mod mvex_cvt_fn;
#[cfg(feature = "mvex")]
mod mvex_eh_bit;
#[cfg(feature = "mvex")]
mod mvex_rm_conv;
#[cfg(feature = "mvex")]
mod mvex_tt_lut;
#[cfg(feature = "instr_info")]
mod op_access;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_info;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_operand_kind;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod op_code_table_kind;
#[cfg(feature = "instr_api")]
mod op_kind;
#[cfg(any(feature = "instr_api", feature = "instr_info", feature = "instr_create"))]
mod register;
#[cfg(feature = "instr_info")]
mod register_ext;
#[cfg(feature = "instr_create")]
mod rep_prefix_kind;
#[cfg(feature = "instr_info")]
mod rflags_bits;
#[cfg(feature = "instr_api")]
mod rounding_control;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
mod tuple_type;

#[cfg(all(feature = "encoder", feature = "block_encoder"))]
pub use block_encoder::*;
#[cfg(all(feature = "encoder", feature = "block_encoder"))]
pub use block_encoder_options::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use cc::*;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info"), feature = "instr_create"))]
pub use code::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use code_ext::*;
#[cfg(feature = "instr_api")]
pub use code_size::*;
#[cfg(feature = "instr_info")]
#[cfg(feature = "instr_api")]
pub use condition_code::*;
#[cfg(any(feature = "encoder", all(feature = "decoder", feature = "instr_info")))]
pub use constant_offsets::*;
#[cfg(feature = "instr_info")]
pub use cpuid_feature::*;
#[cfg(feature = "decoder")]
pub use decoder::*;
#[cfg(feature = "decoder")]
pub use decoder_error::*;
#[cfg(feature = "decoder")]
pub use decoder_options::*;
#[cfg(feature = "encoder")]
pub use encoder::*;
#[cfg(any(feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
pub use encoding_kind::*;
#[cfg(feature = "fast_fmt")]
pub use fast_fmt::*;
#[cfg(any(feature = "instr_info", all(feature = "instr_info", feature = "instr_api")))]
pub use flow_control::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use format_mnemonic_options::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use formatter::*;
#[cfg(feature = "instr_info")]
pub use info::*;
pub use instruction::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use mandatory_prefix::*;
#[cfg(feature = "instr_create")]
pub use memory_operand::*;
#[cfg(any(feature = "instr_api", feature = "instr_info", all(feature = "encoder", feature = "op_code_info")))]
pub use memory_size::*;
#[cfg(feature = "instr_info")]
pub use memory_size_ext::*;
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
pub use memory_size_options::*;
#[cfg(any(feature = "instr_api", all(feature = "encoder", feature = "op_code_info")))]
pub use mnemonic::*;
#[cfg(feature = "mvex")]
pub use mvex_cvt_fn::*;
#[cfg(feature = "mvex")]
pub use mvex_eh_bit::*;
#[cfg(feature = "mvex")]
pub use mvex_rm_conv::*;
#[cfg(feature = "mvex")]
pub use mvex_tt_lut::*;
#[cfg(feature = "instr_info")]
pub use op_access::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_info::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_operand_kind::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use op_code_table_kind::*;
#[cfg(feature = "instr_api")]
pub use op_kind::*;
#[cfg(any(feature = "instr_api", feature = "instr_info", feature = "instr_create"))]
pub use register::*;
#[cfg(feature = "instr_info")]
pub use register_ext::*;
#[cfg(feature = "instr_create")]
pub use rep_prefix_kind::*;
#[cfg(feature = "instr_info")]
pub use rflags_bits::*;
#[cfg(feature = "instr_api")]
pub use rounding_control::*;
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
pub use tuple_type::*;
use wasm_bindgen::prelude::*;

/// Gets feature flags.
///
/// Flag | Value
/// -----|-------
/// 0x01 | `VEX`
/// 0x02 | `EVEX`
/// 0x04 | `XOP`
/// 0x08 | `3DNow!`
/// 0x10 | `MVEX`
#[wasm_bindgen(js_name = "getIcedFeatures")]
pub fn get_iced_features() -> u32 {
	#[allow(unused_mut)]
	let mut flags = 0;
	#[cfg(not(feature = "no_vex"))]
	{
		flags |= 1;
	}
	#[cfg(not(feature = "no_evex"))]
	{
		flags |= 2;
	}
	#[cfg(not(feature = "no_xop"))]
	{
		flags |= 4;
	}
	#[cfg(not(feature = "no_d3now"))]
	{
		flags |= 8;
	}
	#[cfg(feature = "mvex")]
	{
		flags |= 0x10;
	}
	flags
}
<|endoftext|>


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

// xfail-test
pub fn main() {

    fn foo() { }

    let bar: ~fn() = ~foo;
}
<commit_msg>Remove test issue-3461<commit_after><|endoftext|>


<commit_before>use byteorder::{BigEndian, WriteBytesExt};
use generic_array::{ArrayLength, GenericArray};
use std::io::{Result, Error, ErrorKind, Read, Write};
use std::mem::size_of;

pub trait Message {
    fn hash(&self) -> i64 { 0 }
    fn encode(&self, buffer: &mut Write) -> Result<()>;
    fn decode(&mut self, buffer: &mut Read) -> Result<()> { Err(Error::new(ErrorKind::Other, "Unimplemented")) }
    fn size(&self) -> usize;
}

impl Message for bool {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let value : i8 = match *self {
            true => 1,
            false => 0
        };
        value.encode(buffer)
    }

    fn size(&self) -> usize {
        size_of::<i8>()
    }
}

impl Message for u8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_u8(*self)
    }

    fn size(&self) -> usize {
        size_of::<u8>()
    }
}

impl Message for i8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i8(*self)
    }

    fn size(&self) -> usize {
        size_of::<i8>()
    }
}

impl Message for i16 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i16::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<i16>()
    }
}

impl Message for i32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i32::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<i32>()
    }
}

impl Message for i64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i64::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<i64>()
    }
}

impl Message for f32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f32::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<f32>()
    }
}

impl Message for f64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f64::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for str {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let len : i32 = self.len() as i32 + 1;
        len.encode(buffer)?;
        for &b in self.as_bytes() {
            b.encode(buffer)?;
        }
        (1 as u8).encode(buffer)?;
        Ok(())
    }

    fn size(&self) -> usize {
        size_of::<i32>() + self.len() + 1
    }
}

impl<T> Message for Vec<T> where
    T : Message {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        for val in self.iter() {
            val.encode(buffer)?;
        }
        Ok(())
    }

    fn size(&self) -> usize {
        size_of::<T>() * self.len()
    }
}

impl<T,N> Message for GenericArray<T, N> where
    T : Message, N : ArrayLength<T> {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        for val in self.iter() {
            val.encode(buffer)?;
        }
        Ok(())
    }

    fn size(&self) -> usize {
        size_of::<T>() * self.len()
    }
}
<commit_msg>Fix some Message::size implementations.<commit_after>use byteorder::{BigEndian, WriteBytesExt};
use generic_array::{ArrayLength, GenericArray};
use std::io::{Result, Error, ErrorKind, Read, Write};
use std::mem::size_of;

pub trait Message {
    fn hash(&self) -> i64 { 0 }
    fn encode(&self, buffer: &mut Write) -> Result<()>;
    fn decode(&mut self, buffer: &mut Read) -> Result<()> { Err(Error::new(ErrorKind::Other, "Unimplemented")) }
    fn size(&self) -> usize;
}

impl Message for bool {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let value : i8 = match *self {
            true => 1,
            false => 0
        };
        value.encode(buffer)
    }

    fn size(&self) -> usize {
        size_of::<i8>()
    }
}

impl Message for u8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_u8(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i8(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i16 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i16::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i32::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i64::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f32::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f64::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for str {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let len : i32 = self.len() as i32 + 1;
        len.encode(buffer)?;
        for &b in self.as_bytes() {
            b.encode(buffer)?;
        }
        (1 as u8).encode(buffer)?;
        Ok(())
    }

    fn size(&self) -> usize {
        size_of::<i32>() + self.len() + 1
    }
}

impl<T> Message for Vec<T> where
    T : Message {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        for val in self.iter() {
            val.encode(buffer)?;
        }
        Ok(())
    }

    fn size(&self) -> usize {
        self.iter().map(Message::size).sum()
    }
}

impl<T,N> Message for GenericArray<T, N> where
    T : Message, N : ArrayLength<T> {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        for val in self.iter() {
            val.encode(buffer)?;
        }
        Ok(())
    }

    fn size(&self) -> usize {
        self.iter().map(Message::size).sum()
    }
}
<|endoftext|>


<commit_before>//! Quicksort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Quicksort".
//!
//! Source: https://en.wikipedia.org/wiki/Quicksort

extern crate libc;

use std::fmt::Debug;
use std::slice;

/// Quicksort
///
/// # Details
///
///
///
/// # Scaling
///
///
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::quick::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd>(array: &mut [T]) {
    let n = array.len();

    if n <= 1 {
        // Don't do anything
    } else if n == 2 {
        if array.first() > array.last() {
            array.swap(0, 1);
        }
    } else {
        // Pick a pivot: Pick the middle element by skipping half the length and keeping just one.
        // let it_pivot = array.iter().skip(n / 2).take(1);
        // Take the first element as the pivot.
        // let it_pivot = array.iter().take(1);
        //
        // for it in it_pivot {
        //     println!("  0. it: {:?}", it);
        // }

        // Loop over array, finding smaller elements than the pivot.
        // for it in array.iter().skip(1) {
        //     //println!("  1. it: {:?}", it);
        //     if it < it_pivot {
        //         println!("  1. it: {:?} smaller than pivot!", it);
        //     }
        // }
        // array.swap(0,1);

        // array.iter().enumerate().map(|(i,x)| {});

        // // Take the first element as pivot.
        // let a = array.iter_mut().skip(1).enumerate().fold(
        //     (0, array[0]), |acc, item| {
        //         if acc.1 > item.1 {
        //             // Element is smaller than pivot; swap them!
        //             array.swap(acc.0, item.0);
        //             // Return the accumulator as being the new index of pivot (which is now at
        //             // at the location of the fold()) with the pivot value which shouldn't change.
        //             (item.0, acc.1)
        //         } else {
        //             // Nothing to do as element is larger than pivot. Just return new accumulator.
        //             (acc.0, acc.1)
        //         }
        //     }
        // );

        // Use the first element as the pivot, and loop over the rest of the vector.
        let mut pivot = 0;
        for i in 1..n {
            // The loop element is smaller than the pivot. Shuffle things around to place that
            // element before the pivot.
            if array[pivot] > array[i] {
                // First, let's swap the element and the pivot.
                array.swap(pivot, i);
                // Two cases are possible here:
                //     1) The element was the one next to the pivot in the vector. As such, the
                //        new pivot's location is the index "i".
                //     2) The element swaped was further down the vector. If we just swap the pivot
                //        and that element, we are sending the pivot _after_ larger elements,
                //        breaking the ordering! Additionally to the first swap, the pivot (now
                //        being at index "i" after the first swap) is again swapped with the
                //        element that was next to it before (index "pivot+1").
                if i == pivot+1 {
                    pivot = i;
                } else {
                    array.swap(i, pivot+1);
                    pivot = pivot+1;
                }
            }
        }

        // Recursively call the function on slices of the vector.
        sort(&mut array[0..pivot+1]);
        sort(&mut array[pivot+1..n]);
    }
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_i8(array_pointer: *const libc::int8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i16(array_pointer: *const libc::int16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i32(array_pointer: *const libc::int32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i64(array_pointer: *const libc::int64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_u8(array_pointer: *const libc::uint8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u16(array_pointer: *const libc::uint16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u32(array_pointer: *const libc::uint32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u64(array_pointer: *const libc::uint64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_f32(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_f64(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f64, n as usize)
    };
    sort(&mut to_sort);
}
<commit_msg>Cleanup: No need for Debug<commit_after>//! Quicksort algorithm.
//!
//! The `efficient` module contains the efficient sorting algorithm "Quicksort".
//!
//! Source: https://en.wikipedia.org/wiki/Quicksort

extern crate libc;

use std::slice;

/// Quicksort
///
/// # Details
///
///
///
/// # Scaling
///
///
///
/// # Optimizations
///
/// None
///
/// # Notes
///
/// The type T of the vector elements to sort _must_ implement the `PartialOrd` trait so the
/// compiler knows how to compare the elements and sort them.
///
/// # Examples
///
/// ```
/// let mut data: Vec<i32> = vec![4, 2, 3, 1, 5];
/// sorting::efficientsorts::quick::sort(&mut data);
/// assert_eq!(vec![1, 2, 3, 4, 5], data);
/// ```
///
pub fn sort<T: PartialOrd>(array: &mut [T]) {
    let n = array.len();

    if n <= 1 {
        // Don't do anything
    } else if n == 2 {
        if array.first() > array.last() {
            array.swap(0, 1);
        }
    } else {
        // Pick a pivot: Pick the middle element by skipping half the length and keeping just one.
        // let it_pivot = array.iter().skip(n / 2).take(1);
        // Take the first element as the pivot.
        // let it_pivot = array.iter().take(1);
        //
        // for it in it_pivot {
        //     println!("  0. it: {:?}", it);
        // }

        // Loop over array, finding smaller elements than the pivot.
        // for it in array.iter().skip(1) {
        //     //println!("  1. it: {:?}", it);
        //     if it < it_pivot {
        //         println!("  1. it: {:?} smaller than pivot!", it);
        //     }
        // }
        // array.swap(0,1);

        // array.iter().enumerate().map(|(i,x)| {});

        // // Take the first element as pivot.
        // let a = array.iter_mut().skip(1).enumerate().fold(
        //     (0, array[0]), |acc, item| {
        //         if acc.1 > item.1 {
        //             // Element is smaller than pivot; swap them!
        //             array.swap(acc.0, item.0);
        //             // Return the accumulator as being the new index of pivot (which is now at
        //             // at the location of the fold()) with the pivot value which shouldn't change.
        //             (item.0, acc.1)
        //         } else {
        //             // Nothing to do as element is larger than pivot. Just return new accumulator.
        //             (acc.0, acc.1)
        //         }
        //     }
        // );

        // Use the first element as the pivot, and loop over the rest of the vector.
        let mut pivot = 0;
        for i in 1..n {
            // The loop element is smaller than the pivot. Shuffle things around to place that
            // element before the pivot.
            if array[pivot] > array[i] {
                // First, let's swap the element and the pivot.
                array.swap(pivot, i);
                // Two cases are possible here:
                //     1) The element was the one next to the pivot in the vector. As such, the
                //        new pivot's location is the index "i".
                //     2) The element swaped was further down the vector. If we just swap the pivot
                //        and that element, we are sending the pivot _after_ larger elements,
                //        breaking the ordering! Additionally to the first swap, the pivot (now
                //        being at index "i" after the first swap) is again swapped with the
                //        element that was next to it before (index "pivot+1").
                if i == pivot+1 {
                    pivot = i;
                } else {
                    array.swap(i, pivot+1);
                    pivot = pivot+1;
                }
            }
        }

        // Recursively call the function on slices of the vector.
        sort(&mut array[0..pivot+1]);
        sort(&mut array[pivot+1..n]);
    }
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_i8(array_pointer: *const libc::int8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i16(array_pointer: *const libc::int16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i32(array_pointer: *const libc::int32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_i64(array_pointer: *const libc::int64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut i64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_u8(array_pointer: *const libc::uint8_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u8, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u16(array_pointer: *const libc::uint16_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u16, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u32(array_pointer: *const libc::uint32_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_u64(array_pointer: *const libc::uint64_t, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut u64, n as usize)
    };
    sort(&mut to_sort);
}

#[no_mangle]
pub extern "C" fn ffi_quicksort_f32(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f32, n as usize)
    };
    sort(&mut to_sort);
}
#[no_mangle]
pub extern "C" fn ffi_quicksort_f64(array_pointer: *const libc::c_void, n: libc::size_t) {
    assert!(!array_pointer.is_null());
    assert!(n != 0);
    let mut to_sort = unsafe {
        slice::from_raw_parts_mut(array_pointer as *mut f64, n as usize)
    };
    sort(&mut to_sort);
}
<|endoftext|>


<commit_before>use std::{iter, ptr, vec};

use serde::de::{
    self,
    value::{Error, SeqDeserializer},
    Deserializer, IntoDeserializer,
};

#[derive(Debug)]
pub enum ValOrVec<T> {
    Val(T),
    Vec(Vec<T>),
}

impl<T> ValOrVec<T> {
    pub fn push(&mut self, new_val: T) {
        match self {
            ValOrVec::Val(val) => {
                let mut vec = Vec::with_capacity(2);
                // Safety:
                //
                // since the vec is pre-allocated, push can't panic, so there
                // is no opportunity for a panic in the unsafe code.
                unsafe {
                    let existing_val = ptr::read(val);
                    vec.push(existing_val);
                    vec.push(new_val);
                    ptr::write(self, ValOrVec::Vec(vec))
                }
            }
            ValOrVec::Vec(vec) => vec.push(new_val),
        }
    }
}

impl<T> IntoIterator for ValOrVec<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter::new(self)
    }
}

pub enum IntoIter<T> {
    Val(iter::Once<T>),
    Vec(vec::IntoIter<T>),
}

impl<T> IntoIter<T> {
    fn new(vv: ValOrVec<T>) -> Self {
        match vv {
            ValOrVec::Val(val) => IntoIter::Val(iter::once(val)),
            ValOrVec::Vec(vec) => IntoIter::Vec(vec.into_iter()),
        }
    }
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            IntoIter::Val(iter) => iter.next(),
            IntoIter::Vec(iter) => iter.next(),
        }
    }
}

impl<'de, T> IntoDeserializer<'de> for ValOrVec<T>
where
    T: IntoDeserializer<'de> + Deserializer<'de, Error = Error>,
{
    type Deserializer = Self;

    fn into_deserializer(self) -> Self::Deserializer {
        self
    }
}

macro_rules! forward_to_part {
    ($($method:ident,)*) => {
        $(
            fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
                where V: de::Visitor<'de>
            {
                match self {
                    ValOrVec::Val(val) => val.$method(visitor),
                    ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
                }
            }
        )*
    }
}

impl<'de, T> Deserializer<'de> for ValOrVec<T>
where
    T: IntoDeserializer<'de> + Deserializer<'de, Error = Error>,
{
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_any(visitor),
            ValOrVec::Vec(_) => self.deserialize_seq(visitor),
        }
    }

    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        visitor.visit_seq(SeqDeserializer::new(self.into_iter()))
    }

    fn deserialize_enum<V>(
        self,
        name: &'static str,
        variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_enum(name, variants, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_tuple<V>(
        self,
        len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_tuple(len, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_struct<V>(
        self,
        name: &'static str,
        fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_struct(name, fields, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_unit_struct<V>(
        self,
        name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_unit_struct(name, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_tuple_struct<V>(
        self,
        name: &'static str,
        len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => {
                val.deserialize_tuple_struct(name, len, visitor)
            }
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_newtype_struct<V>(
        self,
        name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_newtype_struct(name, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    forward_to_part! {
        deserialize_bool,
        deserialize_char,
        deserialize_str,
        deserialize_string,
        deserialize_bytes,
        deserialize_byte_buf,
        deserialize_unit,
        deserialize_u8,
        deserialize_u16,
        deserialize_u32,
        deserialize_u64,
        deserialize_i8,
        deserialize_i16,
        deserialize_i32,
        deserialize_i64,
        deserialize_f32,
        deserialize_f64,
        deserialize_option,
        deserialize_identifier,
        deserialize_ignored_any,
        deserialize_map,
    }
}
<commit_msg>Expand explanation comment for unsafe code<commit_after>use std::{iter, ptr, vec};

use serde::de::{
    self,
    value::{Error, SeqDeserializer},
    Deserializer, IntoDeserializer,
};

#[derive(Debug)]
pub enum ValOrVec<T> {
    Val(T),
    Vec(Vec<T>),
}

impl<T> ValOrVec<T> {
    pub fn push(&mut self, new_val: T) {
        match self {
            // To transform a Self::Val into a Self::Vec, we take the existing
            // value out via ptr::read and add it to a vector, together with the
            // new value. Since setting self to `ValOrVec::Vec` normally would
            // cause T's Drop implementation to run if it has one (which would
            // free resources that will now be owned by the first vec element),
            // we instead use ptr::write to set self to Self::Vec.
            ValOrVec::Val(val) => {
                let mut vec = Vec::with_capacity(2);
                // Safety: since the vec is pre-allocated, push can't panic, so
                //   there is no opportunity for outside code to observe an
                //   invalid state of self.
                unsafe {
                    let existing_val = ptr::read(val);
                    vec.push(existing_val);
                    vec.push(new_val);
                    ptr::write(self, ValOrVec::Vec(vec))
                }
            }
            ValOrVec::Vec(vec) => vec.push(new_val),
        }
    }
}

impl<T> IntoIterator for ValOrVec<T> {
    type Item = T;
    type IntoIter = IntoIter<T>;

    fn into_iter(self) -> Self::IntoIter {
        IntoIter::new(self)
    }
}

pub enum IntoIter<T> {
    Val(iter::Once<T>),
    Vec(vec::IntoIter<T>),
}

impl<T> IntoIter<T> {
    fn new(vv: ValOrVec<T>) -> Self {
        match vv {
            ValOrVec::Val(val) => IntoIter::Val(iter::once(val)),
            ValOrVec::Vec(vec) => IntoIter::Vec(vec.into_iter()),
        }
    }
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        match self {
            IntoIter::Val(iter) => iter.next(),
            IntoIter::Vec(iter) => iter.next(),
        }
    }
}

impl<'de, T> IntoDeserializer<'de> for ValOrVec<T>
where
    T: IntoDeserializer<'de> + Deserializer<'de, Error = Error>,
{
    type Deserializer = Self;

    fn into_deserializer(self) -> Self::Deserializer {
        self
    }
}

macro_rules! forward_to_part {
    ($($method:ident,)*) => {
        $(
            fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
                where V: de::Visitor<'de>
            {
                match self {
                    ValOrVec::Val(val) => val.$method(visitor),
                    ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
                }
            }
        )*
    }
}

impl<'de, T> Deserializer<'de> for ValOrVec<T>
where
    T: IntoDeserializer<'de> + Deserializer<'de, Error = Error>,
{
    type Error = Error;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_any(visitor),
            ValOrVec::Vec(_) => self.deserialize_seq(visitor),
        }
    }

    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        visitor.visit_seq(SeqDeserializer::new(self.into_iter()))
    }

    fn deserialize_enum<V>(
        self,
        name: &'static str,
        variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_enum(name, variants, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_tuple<V>(
        self,
        len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_tuple(len, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_struct<V>(
        self,
        name: &'static str,
        fields: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_struct(name, fields, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_unit_struct<V>(
        self,
        name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_unit_struct(name, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_tuple_struct<V>(
        self,
        name: &'static str,
        len: usize,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => {
                val.deserialize_tuple_struct(name, len, visitor)
            }
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    fn deserialize_newtype_struct<V>(
        self,
        name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: de::Visitor<'de>,
    {
        match self {
            ValOrVec::Val(val) => val.deserialize_newtype_struct(name, visitor),
            ValOrVec::Vec(_) => Err(de::Error::custom("TODO: Error message")),
        }
    }

    forward_to_part! {
        deserialize_bool,
        deserialize_char,
        deserialize_str,
        deserialize_string,
        deserialize_bytes,
        deserialize_byte_buf,
        deserialize_unit,
        deserialize_u8,
        deserialize_u16,
        deserialize_u32,
        deserialize_u64,
        deserialize_i8,
        deserialize_i16,
        deserialize_i32,
        deserialize_i64,
        deserialize_f32,
        deserialize_f64,
        deserialize_option,
        deserialize_identifier,
        deserialize_ignored_any,
        deserialize_map,
    }
}
<|endoftext|>


<commit_before>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Testing virtio-block.

pub mod fixture;

use std::process::Command;

use fixture::Config;
use fixture::TestVm;
use tempfile::NamedTempFile;

fn prepare_disk_img() -> NamedTempFile {
    let mut disk = NamedTempFile::new().unwrap();
    disk.as_file_mut().set_len(1024 * 1024).unwrap();

    // TODO(b/243127910): Use `mkfs.ext4 -d` to include test data.
    Command::new("sudo")
        .arg("mkfs.ext4")
        .arg(disk.path().to_str().unwrap())
        .output()
        .expect("failed to execute process");
    disk
}

// TODO(b/243127498): Add tests for write and sync operations.
#[test]
fn mount_block() {
    let disk = prepare_disk_img();
    let disk_path = disk.path().to_str().unwrap().to_string();
    println!("disk={disk_path}");

    let config = Config::new().extra_args(vec!["--rwdisk".to_string(), disk_path]);
    let mut vm = TestVm::new(config).unwrap();
    assert_eq!(
        vm.exec_in_guest("mount -t ext4 /dev/vdb /mnt && echo 42")
            .unwrap()
            .trim(),
        "42"
    );
}
<commit_msg>integration_tests: search for mkfs.ext4 in sbin via PATH<commit_after>// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Testing virtio-block.

pub mod fixture;

use std::env;
use std::process::Command;

use fixture::Config;
use fixture::TestVm;
use tempfile::NamedTempFile;

fn prepare_disk_img() -> NamedTempFile {
    let mut disk = NamedTempFile::new().unwrap();
    disk.as_file_mut().set_len(1024 * 1024).unwrap();

    // Add /sbin and /usr/sbin to PATH since some distributions put mkfs.ext4 in one of those
    // directories but don't add them to non-root PATH.
    let path = env::var("PATH").unwrap();
    let path = [&path, "/sbin", "/usr/sbin"].join(":");

    // TODO(b/243127910): Use `mkfs.ext4 -d` to include test data.
    Command::new("mkfs.ext4")
        .arg(disk.path().to_str().unwrap())
        .env("PATH", path)
        .output()
        .expect("failed to execute process");
    disk
}

// TODO(b/243127498): Add tests for write and sync operations.
#[test]
fn mount_block() {
    let disk = prepare_disk_img();
    let disk_path = disk.path().to_str().unwrap().to_string();
    println!("disk={disk_path}");

    let config = Config::new().extra_args(vec!["--rwdisk".to_string(), disk_path]);
    let mut vm = TestVm::new(config).unwrap();
    assert_eq!(
        vm.exec_in_guest("mount -t ext4 /dev/vdb /mnt && echo 42")
            .unwrap()
            .trim(),
        "42"
    );
}
<|endoftext|>


<commit_before>//! Generally, `search_scope` returns files that might contain references for the element.
//! For `pub(crate)` things it's a crate, for `pub` things it's a crate and dependant crates.
//! In some cases, the location of the references is known to within a `TextRange`,
//! e.g. for things like local variables.

use hir::{DefWithBody, HasSource, ModuleSource};
use ra_db::{FileId, SourceDatabase, SourceDatabaseExt};
use ra_prof::profile;
use ra_syntax::{AstNode, TextRange};
use rustc_hash::FxHashSet;

use crate::db::RootDatabase;

use super::{NameDefinition, NameKind};

impl NameDefinition {
    pub(crate) fn search_scope(&self, db: &RootDatabase) -> FxHashSet<(FileId, Option<TextRange>)> {
        let _p = profile("search_scope");

        let module_src = self.container.definition_source(db);
        let file_id = module_src.file_id.original_file(db);

        if let NameKind::Pat((def, _)) = self.kind {
            let mut res = FxHashSet::default();
            let range = match def {
                DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(),
                DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(),
                DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(),
            };
            res.insert((file_id, Some(range)));
            return res;
        }

        let vis =
            self.visibility.as_ref().map(|v| v.syntax().to_string()).unwrap_or("".to_string());

        if vis.as_str() == "pub(super)" {
            if let Some(parent_module) = self.container.parent(db) {
                let mut files = FxHashSet::default();
                let parent_src = parent_module.definition_source(db);
                let file_id = parent_src.file_id.original_file(db);

                match parent_src.ast {
                    ModuleSource::Module(m) => {
                        let range = Some(m.syntax().text_range());
                        files.insert((file_id, range));
                    }
                    ModuleSource::SourceFile(_) => {
                        files.insert((file_id, None));
                        files.extend(parent_module.children(db).map(|m| {
                            let src = m.definition_source(db);
                            (src.file_id.original_file(db), None)
                        }));
                    }
                }
                return files;
            }
        }

        if vis.as_str() != "" {
            let source_root_id = db.file_source_root(file_id);
            let source_root = db.source_root(source_root_id);
            let mut files =
                source_root.walk().map(|id| (id.into(), None)).collect::<FxHashSet<_>>();

            // FIXME: add "pub(in path)"

            if vis.as_str() == "pub(crate)" {
                return files;
            }
            if vis.as_str() == "pub" {
                let krate = self.container.krate(db).unwrap();
                let crate_graph = db.crate_graph();
                for crate_id in crate_graph.iter() {
                    let mut crate_deps = crate_graph.dependencies(crate_id);
                    if crate_deps.any(|dep| dep.crate_id() == krate.crate_id()) {
                        let root_file = crate_graph.crate_root(crate_id);
                        let source_root_id = db.file_source_root(root_file);
                        let source_root = db.source_root(source_root_id);
                        files.extend(source_root.walk().map(|id| (id.into(), None)));
                    }
                }
                return files;
            }
        }

        let mut res = FxHashSet::default();
        let range = match module_src.ast {
            ModuleSource::Module(m) => Some(m.syntax().text_range()),
            ModuleSource::SourceFile(_) => None,
        };
        res.insert((file_id, range));
        res
    }
}
<commit_msg>add search scope stuct<commit_after>//! Generally, `search_scope` returns files that might contain references for the element.
//! For `pub(crate)` things it's a crate, for `pub` things it's a crate and dependant crates.
//! In some cases, the location of the references is known to within a `TextRange`,
//! e.g. for things like local variables.

use hir::{DefWithBody, HasSource, ModuleSource};
use ra_db::{FileId, SourceDatabase, SourceDatabaseExt};
use ra_prof::profile;
use ra_syntax::{AstNode, TextRange};
use rustc_hash::FxHashSet;

use crate::db::RootDatabase;

use super::{NameDefinition, NameKind};

pub struct SearchScope {
    entries: FxHashSet<(FileId, Option<TextRange>)>,
}

impl SearchScope {
    fn new(entries: FxHashSet<(FileId, Option<TextRange>)>) -> SearchScope {
        SearchScope { entries }
    }
}

impl IntoIterator for SearchScope {
    type Item = (FileId, Option<TextRange>);
    type IntoIter = std::collections::hash_set::IntoIter<Self::Item>;
    fn into_iter(self) -> Self::IntoIter {
        self.entries.into_iter()
    }
}

impl NameDefinition {
    pub(crate) fn search_scope(&self, db: &RootDatabase) -> SearchScope {
        let _p = profile("search_scope");

        let module_src = self.container.definition_source(db);
        let file_id = module_src.file_id.original_file(db);

        if let NameKind::Pat((def, _)) = self.kind {
            let mut res = FxHashSet::default();
            let range = match def {
                DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(),
                DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(),
                DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(),
            };
            res.insert((file_id, Some(range)));
            return SearchScope::new(res);
        }

        let vis =
            self.visibility.as_ref().map(|v| v.syntax().to_string()).unwrap_or("".to_string());

        if vis.as_str() == "pub(super)" {
            if let Some(parent_module) = self.container.parent(db) {
                let mut res = FxHashSet::default();
                let parent_src = parent_module.definition_source(db);
                let file_id = parent_src.file_id.original_file(db);

                match parent_src.ast {
                    ModuleSource::Module(m) => {
                        let range = Some(m.syntax().text_range());
                        res.insert((file_id, range));
                    }
                    ModuleSource::SourceFile(_) => {
                        res.insert((file_id, None));
                        res.extend(parent_module.children(db).map(|m| {
                            let src = m.definition_source(db);
                            (src.file_id.original_file(db), None)
                        }));
                    }
                }
                return SearchScope::new(res);
            }
        }

        if vis.as_str() != "" {
            let source_root_id = db.file_source_root(file_id);
            let source_root = db.source_root(source_root_id);
            let mut res = source_root.walk().map(|id| (id.into(), None)).collect::<FxHashSet<_>>();

            // FIXME: add "pub(in path)"

            if vis.as_str() == "pub(crate)" {
                return SearchScope::new(res);
            }
            if vis.as_str() == "pub" {
                let krate = self.container.krate(db).unwrap();
                let crate_graph = db.crate_graph();
                for crate_id in crate_graph.iter() {
                    let mut crate_deps = crate_graph.dependencies(crate_id);
                    if crate_deps.any(|dep| dep.crate_id() == krate.crate_id()) {
                        let root_file = crate_graph.crate_root(crate_id);
                        let source_root_id = db.file_source_root(root_file);
                        let source_root = db.source_root(source_root_id);
                        res.extend(source_root.walk().map(|id| (id.into(), None)));
                    }
                }
                return SearchScope::new(res);
            }
        }

        let mut res = FxHashSet::default();
        let range = match module_src.ast {
            ModuleSource::Module(m) => Some(m.syntax().text_range()),
            ModuleSource::SourceFile(_) => None,
        };
        res.insert((file_id, range));
        SearchScope::new(res)
    }
}
<|endoftext|>