<commit_before>//! Common types for room directory endpoints.

use std::fmt;

use js_int::UInt;
use ruma_identifiers::{MxcUri, RoomAliasId, RoomId, RoomName};
use ruma_serde::Outgoing;
use serde::{
    de::{Error, MapAccess, Visitor},
    ser::SerializeStruct,
    Deserialize, Deserializer, Serialize, Serializer,
};
use serde_json::Value as JsonValue;

/// A chunk of a room list response, describing one room.
///
/// To create an instance of this type, first create a `PublicRoomsChunkInit` and convert it via
/// `PublicRoomsChunk::from` / `.into()`.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct PublicRoomsChunk {
    /// Aliases of the room.
    #[serde(default, skip_serializing_if = "Vec::is_empty")]
    pub aliases: Vec<Box<RoomAliasId>>,

    /// The canonical alias of the room, if any.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[cfg_attr(
        feature = "compat",
        serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
    )]
    pub canonical_alias: Option<Box<RoomAliasId>>,

    /// The name of the room, if any.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<Box<RoomName>>,

    /// The number of members joined to the room.
    pub num_joined_members: UInt,

    /// The ID of the room.
    pub room_id: Box<RoomId>,

    /// The topic of the room, if any.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub topic: Option<String>,

    /// Whether the room may be viewed by guest users without joining.
    pub world_readable: bool,

    /// Whether guest users may join the room and participate in it.
    ///
    /// If they can, they will be subject to ordinary power level rules like any other user.
    pub guest_can_join: bool,

    /// The URL for the room's avatar, if one is set.
    ///
    /// If you activate the `compat` feature, this field being an empty string in JSON will result
    /// in `None` here during deserialization.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[cfg_attr(
        feature = "compat",
        serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
    )]
    pub avatar_url: Option<Box<MxcUri>>,
}

/// Initial set of mandatory fields of `PublicRoomsChunk`.
///
/// This struct will not be updated even if additional fields are added to `PublicRoomsChunk` in a
/// new (non-breaking) release of the Matrix specification.
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct PublicRoomsChunkInit {
    /// The number of members joined to the room.
    pub num_joined_members: UInt,

    /// The ID of the room.
    pub room_id: Box<RoomId>,

    /// Whether the room may be viewed by guest users without joining.
    pub world_readable: bool,

    /// Whether guest users may join the room and participate in it.
    ///
    /// If they can, they will be subject to ordinary power level rules like any other user.
    pub guest_can_join: bool,
}

impl From<PublicRoomsChunkInit> for PublicRoomsChunk {
    fn from(init: PublicRoomsChunkInit) -> Self {
        let PublicRoomsChunkInit { num_joined_members, room_id, world_readable, guest_can_join } =
            init;

        Self {
            aliases: Vec::new(),
            canonical_alias: None,
            name: None,
            num_joined_members,
            room_id,
            topic: None,
            world_readable,
            guest_can_join,
            avatar_url: None,
        }
    }
}

/// A filter for public rooms lists
#[derive(Clone, Debug, Default, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Default)]
pub struct Filter<'a> {
    /// A string to search for in the room metadata, e.g. name, topic, canonical alias etc.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub generic_search_term: Option<&'a str>,
}

impl Filter<'_> {
    /// Creates an empty `Filter`.
    pub fn new() -> Self {
        Default::default()
    }

    /// Returns `true` if the filter is empty.
    pub fn is_empty(&self) -> bool {
        self.generic_search_term.is_none()
    }
}

/// Information about which networks/protocols from application services on the
/// homeserver from which to request rooms.
#[derive(Clone, Debug, PartialEq, Eq, Outgoing)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Clone, PartialEq, Eq, !Deserialize)]
pub enum RoomNetwork<'a> {
    /// Return rooms from the Matrix network.
    Matrix,

    /// Return rooms from all the networks/protocols the homeserver knows about.
    All,

    /// Return rooms from a specific third party network/protocol.
    ThirdParty(&'a str),
}

impl<'a> Default for RoomNetwork<'a> {
    fn default() -> Self {
        RoomNetwork::Matrix
    }
}

impl<'a> Serialize for RoomNetwork<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state;
        match self {
            Self::Matrix => {
                state = serializer.serialize_struct("RoomNetwork", 0)?;
            }
            Self::All => {
                state = serializer.serialize_struct("RoomNetwork", 1)?;
                state.serialize_field("include_all_networks", &true)?;
            }
            Self::ThirdParty(network) => {
                state = serializer.serialize_struct("RoomNetwork", 1)?;
                state.serialize_field("third_party_instance_id", network)?;
            }
        }
        state.end()
    }
}

impl<'de> Deserialize<'de> for IncomingRoomNetwork {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_map(RoomNetworkVisitor)
    }
}

struct RoomNetworkVisitor;
impl<'de> Visitor<'de> for RoomNetworkVisitor {
    type Value = IncomingRoomNetwork;

    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("Network selection")
    }

    fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
    where
        M: MapAccess<'de>,
    {
        let mut include_all_networks = false;
        let mut third_party_instance_id = None;
        while let Some((key, value)) = access.next_entry::<String, JsonValue>()? {
            match key.as_str() {
                "include_all_networks" => {
                    include_all_networks = match value.as_bool() {
                        Some(b) => b,
                        _ => false,
                    }
                }
                "third_party_instance_id" => {
                    third_party_instance_id = value.as_str().map(|v| v.to_owned())
                }
                _ => {}
            };
        }

        if include_all_networks {
            if third_party_instance_id.is_none() {
                Ok(IncomingRoomNetwork::All)
            } else {
                Err(M::Error::custom(
                    "`include_all_networks = true` and `third_party_instance_id` are mutually exclusive.",
                ))
            }
        } else {
            Ok(match third_party_instance_id {
                Some(network) => IncomingRoomNetwork::ThirdParty(network),
                None => IncomingRoomNetwork::Matrix,
            })
        }
    }
}

#[cfg(test)]
mod tests {
    use serde_json::{from_value as from_json_value, json, to_value as to_json_value};

    use super::{IncomingRoomNetwork, RoomNetwork};

    #[test]
    fn serialize_matrix_network_only() {
        let json = json!({});
        assert_eq!(to_json_value(RoomNetwork::Matrix).unwrap(), json);
    }

    #[test]
    fn deserialize_matrix_network_only() {
        let json = json!({ "include_all_networks": false });
        assert_eq!(
            from_json_value::<IncomingRoomNetwork>(json).unwrap(),
            IncomingRoomNetwork::Matrix
        );
    }

    #[test]
    fn serialize_default_network_is_empty() {
        let json = json!({});
        assert_eq!(to_json_value(RoomNetwork::default()).unwrap(), json);
    }

    #[test]
    fn deserialize_empty_network_is_default() {
        let json = json!({});
        assert_eq!(
            from_json_value::<IncomingRoomNetwork>(json).unwrap(),
            IncomingRoomNetwork::Matrix
        );
    }

    #[test]
    fn serialize_include_all_networks() {
        let json = json!({ "include_all_networks": true });
        assert_eq!(to_json_value(RoomNetwork::All).unwrap(), json);
    }

    #[test]
    fn deserialize_include_all_networks() {
        let json = json!({ "include_all_networks": true });
        assert_eq!(from_json_value::<IncomingRoomNetwork>(json).unwrap(), IncomingRoomNetwork::All);
    }

    #[test]
    fn serialize_third_party_network() {
        let json = json!({ "third_party_instance_id": "freenode" });
        assert_eq!(to_json_value(RoomNetwork::ThirdParty("freenode")).unwrap(), json);
    }

    #[test]
    fn deserialize_third_party_network() {
        let json = json!({ "third_party_instance_id": "freenode" });
        assert_eq!(
            from_json_value::<IncomingRoomNetwork>(json).unwrap(),
            IncomingRoomNetwork::ThirdParty("freenode".into())
        );
    }

    #[test]
    fn deserialize_include_all_networks_and_third_party_exclusivity() {
        let json = json!({ "include_all_networks": true, "third_party_instance_id": "freenode" });
        assert_eq!(
            from_json_value::<IncomingRoomNetwork>(json).unwrap_err().to_string().as_str(),
            "`include_all_networks = true` and `third_party_instance_id` are mutually exclusive."
        );
    }
}
<commit_msg>common: Remove aliases from PublicRoomsChunk<commit_after>//! Common types for room directory endpoints.

use std::fmt;

use js_int::UInt;
use ruma_identifiers::{MxcUri, RoomAliasId, RoomId, RoomName};
use ruma_serde::Outgoing;
use serde::{
    de::{Error, MapAccess, Visitor},
    ser::SerializeStruct,
    Deserialize, Deserializer, Serialize, Serializer,
};
use serde_json::Value as JsonValue;

/// A chunk of a room list response, describing one room.
///
/// To create an instance of this type, first create a `PublicRoomsChunkInit` and convert it via
/// `PublicRoomsChunk::from` / `.into()`.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
pub struct PublicRoomsChunk {
    /// The canonical alias of the room, if any.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[cfg_attr(
        feature = "compat",
        serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
    )]
    pub canonical_alias: Option<Box<RoomAliasId>>,

    /// The name of the room, if any.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub name: Option<Box<RoomName>>,

    /// The number of members joined to the room.
    pub num_joined_members: UInt,

    /// The ID of the room.
    pub room_id: Box<RoomId>,

    /// The topic of the room, if any.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub topic: Option<String>,

    /// Whether the room may be viewed by guest users without joining.
    pub world_readable: bool,

    /// Whether guest users may join the room and participate in it.
    ///
    /// If they can, they will be subject to ordinary power level rules like any other user.
    pub guest_can_join: bool,

    /// The URL for the room's avatar, if one is set.
    ///
    /// If you activate the `compat` feature, this field being an empty string in JSON will result
    /// in `None` here during deserialization.
    #[serde(skip_serializing_if = "Option::is_none")]
    #[cfg_attr(
        feature = "compat",
        serde(default, deserialize_with = "ruma_serde::empty_string_as_none")
    )]
    pub avatar_url: Option<Box<MxcUri>>,
}

/// Initial set of mandatory fields of `PublicRoomsChunk`.
///
/// This struct will not be updated even if additional fields are added to `PublicRoomsChunk` in a
/// new (non-breaking) release of the Matrix specification.
#[derive(Debug)]
#[allow(clippy::exhaustive_structs)]
pub struct PublicRoomsChunkInit {
    /// The number of members joined to the room.
    pub num_joined_members: UInt,

    /// The ID of the room.
    pub room_id: Box<RoomId>,

    /// Whether the room may be viewed by guest users without joining.
    pub world_readable: bool,

    /// Whether guest users may join the room and participate in it.
    ///
    /// If they can, they will be subject to ordinary power level rules like any other user.
    pub guest_can_join: bool,
}

impl From<PublicRoomsChunkInit> for PublicRoomsChunk {
    fn from(init: PublicRoomsChunkInit) -> Self {
        let PublicRoomsChunkInit { num_joined_members, room_id, world_readable, guest_can_join } =
            init;

        Self {
            canonical_alias: None,
            name: None,
            num_joined_members,
            room_id,
            topic: None,
            world_readable,
            guest_can_join,
            avatar_url: None,
        }
    }
}

/// A filter for public rooms lists
#[derive(Clone, Debug, Default, Outgoing, Serialize)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Default)]
pub struct Filter<'a> {
    /// A string to search for in the room metadata, e.g. name, topic, canonical alias etc.
    #[serde(skip_serializing_if = "Option::is_none")]
    pub generic_search_term: Option<&'a str>,
}

impl Filter<'_> {
    /// Creates an empty `Filter`.
    pub fn new() -> Self {
        Default::default()
    }

    /// Returns `true` if the filter is empty.
    pub fn is_empty(&self) -> bool {
        self.generic_search_term.is_none()
    }
}

/// Information about which networks/protocols from application services on the
/// homeserver from which to request rooms.
#[derive(Clone, Debug, PartialEq, Eq, Outgoing)]
#[cfg_attr(not(feature = "unstable-exhaustive-types"), non_exhaustive)]
#[incoming_derive(Clone, PartialEq, Eq, !Deserialize)]
pub enum RoomNetwork<'a> {
    /// Return rooms from the Matrix network.
    Matrix,

    /// Return rooms from all the networks/protocols the homeserver knows about.
    All,

    /// Return rooms from a specific third party network/protocol.
    ThirdParty(&'a str),
}

impl<'a> Default for RoomNetwork<'a> {
    fn default() -> Self {
        RoomNetwork::Matrix
    }
}

impl<'a> Serialize for RoomNetwork<'a> {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut state;
        match self {
            Self::Matrix => {
                state = serializer.serialize_struct("RoomNetwork", 0)?;
            }
            Self::All => {
                state = serializer.serialize_struct("RoomNetwork", 1)?;
                state.serialize_field("include_all_networks", &true)?;
            }
            Self::ThirdParty(network) => {
                state = serializer.serialize_struct("RoomNetwork", 1)?;
                state.serialize_field("third_party_instance_id", network)?;
            }
        }
        state.end()
    }
}

impl<'de> Deserialize<'de> for IncomingRoomNetwork {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_map(RoomNetworkVisitor)
    }
}

struct RoomNetworkVisitor;
impl<'de> Visitor<'de> for RoomNetworkVisitor {
    type Value = IncomingRoomNetwork;

    fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("Network selection")
    }

    fn visit_map<M>(self, mut access: M) -> Result<Self::Value, M::Error>
    where
        M: MapAccess<'de>,
    {
        let mut include_all_networks = false;
        let mut third_party_instance_id = None;
        while let Some((key, value)) = access.next_entry::<String, JsonValue>()? {
            match key.as_str() {
                "include_all_networks" => {
                    include_all_networks = match value.as_bool() {
                        Some(b) => b,
                        _ => false,
                    }
                }
                "third_party_instance_id" => {
                    third_party_instance_id = value.as_str().map(|v| v.to_owned())
                }
                _ => {}
            };
        }

        if include_all_networks {
            if third_party_instance_id.is_none() {
                Ok(IncomingRoomNetwork::All)
            } else {
                Err(M::Error::custom(
                    "`include_all_networks = true` and `third_party_instance_id` are mutually exclusive.",
                ))
            }
        } else {
            Ok(match third_party_instance_id {
                Some(network) => IncomingRoomNetwork::ThirdParty(network),
                None => IncomingRoomNetwork::Matrix,
            })
        }
    }
}

#[cfg(test)]
mod tests {
    use serde_json::{from_value as from_json_value, json, to_value as to_json_value};

    use super::{IncomingRoomNetwork, RoomNetwork};

    #[test]
    fn serialize_matrix_network_only() {
        let json = json!({});
        assert_eq!(to_json_value(RoomNetwork::Matrix).unwrap(), json);
    }

    #[test]
    fn deserialize_matrix_network_only() {
        let json = json!({ "include_all_networks": false });
        assert_eq!(
            from_json_value::<IncomingRoomNetwork>(json).unwrap(),
            IncomingRoomNetwork::Matrix
        );
    }

    #[test]
    fn serialize_default_network_is_empty() {
        let json = json!({});
        assert_eq!(to_json_value(RoomNetwork::default()).unwrap(), json);
    }

    #[test]
    fn deserialize_empty_network_is_default() {
        let json = json!({});
        assert_eq!(
            from_json_value::<IncomingRoomNetwork>(json).unwrap(),
            IncomingRoomNetwork::Matrix
        );
    }

    #[test]
    fn serialize_include_all_networks() {
        let json = json!({ "include_all_networks": true });
        assert_eq!(to_json_value(RoomNetwork::All).unwrap(), json);
    }

    #[test]
    fn deserialize_include_all_networks() {
        let json = json!({ "include_all_networks": true });
        assert_eq!(from_json_value::<IncomingRoomNetwork>(json).unwrap(), IncomingRoomNetwork::All);
    }

    #[test]
    fn serialize_third_party_network() {
        let json = json!({ "third_party_instance_id": "freenode" });
        assert_eq!(to_json_value(RoomNetwork::ThirdParty("freenode")).unwrap(), json);
    }

    #[test]
    fn deserialize_third_party_network() {
        let json = json!({ "third_party_instance_id": "freenode" });
        assert_eq!(
            from_json_value::<IncomingRoomNetwork>(json).unwrap(),
            IncomingRoomNetwork::ThirdParty("freenode".into())
        );
    }

    #[test]
    fn deserialize_include_all_networks_and_third_party_exclusivity() {
        let json = json!({ "include_all_networks": true, "third_party_instance_id": "freenode" });
        assert_eq!(
            from_json_value::<IncomingRoomNetwork>(json).unwrap_err().to_string().as_str(),
            "`include_all_networks = true` and `third_party_instance_id` are mutually exclusive."
        );
    }
}
<|endoftext|>


<commit_before>extern crate rand;

use rand::random;
use std::io::BufferedReader;
use std::io;

fn main() {
    println!("I'm thinking of a number between 1 and 100. Can you guess it?");
    let x = random();
    let mut reader = BufferedReader::new(io::stdin());
    while !reader.eof() {
        let line = reader.read_line().unwrap();
        let num = from_str::<int>(line.slice_to(line.len() - 1));
        match num {
            Some(number_string) => println!("Well, it was a number."),
            None                => println!("Doesn't count.")
        }
    }
}
<commit_msg>Compiles, but still contains warnings. No EOF functionality yet.<commit_after>extern crate rand;

use rand::random;
use std::io::BufferedReader;
use std::io;

fn main() {
    println!("I'm thinking of a number between 1 and 100. Can you guess it?");
    let x = random::<int>();
    let mut reader = BufferedReader::new(io::stdin());
    while true {
        let line = reader.read_line().unwrap();
        let num = from_str::<int>(line.slice_to(line.len() - 1));
        match num {
            Some(number_string) => println!("Well, it was a number."),
            None                => println!("Doesn't count.")
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::{remove_dir_all, File};
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::process::Command;

use telemetry::{latitude_longitude_to_point, Meters, Point};
use waypoint_generator::WaypointGenerator;

/**
 * Loads and returns waypoints from a KML file.
 */
#[allow(dead_code)]
pub struct KmlWaypointGenerator {
    waypoints: Vec<Point>,
    current_waypoint: u32,
}

impl KmlWaypointGenerator {
    #[allow(dead_code)]
    pub fn new(file_name: &str) -> KmlWaypointGenerator {
        KmlWaypointGenerator {
            waypoints: KmlWaypointGenerator::load_waypoints(file_name),
            current_waypoint: 0,
        }
    }
    fn load_waypoints(file_name: &str) -> Vec<Point> {
        let path = Path::new(file_name);
        if !path.exists() || !path.is_file() {
            panic!("File does not exist: {}", file_name);
        }

        // A KML file is a zip archive containing a single file named "doc.kml"
        // that is an XML file
        let temp_directory = "/tmp/waypoints";
        match remove_dir_all(temp_directory) {
            Ok(()) => (),
            Err(err) => error!("Unable to remove temp directory: {}", err),
        };
        let zip_io_result = Command::new("unzip")
            .arg(file_name)
            .arg("-d")  // Output directory
            .arg(temp_directory)
            .spawn();
        let mut zip_child = match zip_io_result {
            Ok(child) => (child),
            Err(e) => panic!("Failed to unzip file: {}", e),
        };

        match zip_child.wait() {
            Ok(_) => (),
            Err(e) => panic!("Failed to unzip file: {}", e),
        };

        let mut waypoints = Vec::<Point>::new();
        let file_path = Path::new("/tmp/waypoints/doc.kml");
        let file = match File::open(&file_path) {
            Ok(f) => f,
            Err(_) => panic!("Couldn't open doc.kml"),
        };
        let xml_file = BufReader::new(file);
        let mut coordinates_open_tag = false;
        // We should use a real XML parser here, but Google Earth saves the
        // <coordinates> tag on one line, then the coordinates on the next,
        // then the closing </coordinates> tag on the next, so we'll just rely
        // on that fact
        for line_option in xml_file.lines() {
            match line_option {
                Ok(line) => {
                    if line.contains("<coordinates>") {
                        coordinates_open_tag = true;
                    } else if coordinates_open_tag {
                        let mut latitude = 0.0f64;
                        let mut longitude = 0.0f64;
                        for long_lat_alt in line.split_whitespace() {
                            let mut iterator = long_lat_alt.split(',');
                            let mut success = true;
                            match iterator.next() {
                                Some(longitude_str) => {
                                    let parsed_longitude = longitude_str.parse::<f64>();
                                    match parsed_longitude {
                                        Ok(longitude_) => longitude = longitude_,
                                        Err(e) => {
                                            println!(
                                                "Unable to parse longitude: '{}', {}",
                                                longitude_str, e
                                            );
                                            success = false;
                                        }
                                    }
                                }
                                None => println!("No longitude"),
                            }

                            match iterator.next() {
                                Some(latitude_str) => {
                                    let parsed_latitude = latitude_str.parse::<f64>();
                                    match parsed_latitude {
                                        Ok(latitude_) => latitude = latitude_,
                                        Err(e) => {
                                            println!(
                                                "Unable to parse latitude: '{}', {}",
                                                latitude_str, e
                                            );
                                            success = false;
                                        }
                                    }
                                }
                                None => println!("No latitude"),
                            }

                            if success {
                                waypoints.push(latitude_longitude_to_point(latitude, longitude));
                            }
                        }
                        break;
                    }
                }
                Err(e) => println!("error {}", e),
            }
        }
        waypoints
    }
}

impl WaypointGenerator for KmlWaypointGenerator {
    #[allow(unused_variables)]
    fn get_current_waypoint(&self, point: &Point) -> Point {
        // TODO
        Point { x: 0.0, y: 0.0 }
    }

    #[allow(unused_variables)]
    fn get_current_raw_waypoint(&self, point: &Point) -> Point {
        // TODO
        Point { x: 0.0, y: 0.0 }
    }

    fn next(&mut self) {
        // TODO
    }

    #[allow(unused_variables)]
    fn reached(&self, point: &Point) -> bool {
        // TODO
        return false;
    }

    fn done(&self) -> bool {
        // TODO
        return false;
    }

    #[allow(unused_variables)]
    fn reach_distance(&self) -> Meters {
        1.0
    }
}
<commit_msg>Allow using KMZ or KML files<commit_after>use std::fs::{remove_dir_all, File};
use std::io::{BufRead, BufReader};
use std::path::Path;
use std::process::Command;

use telemetry::{latitude_longitude_to_point, Meters, Point};
use waypoint_generator::WaypointGenerator;

/**
 * Loads and returns waypoints from a KML file.
 */
#[allow(dead_code)]
pub struct KmlWaypointGenerator {
    waypoints: Vec<Point>,
    current_waypoint: u32,
}

impl KmlWaypointGenerator {
    #[allow(dead_code)]
    pub fn new(file_name: &str) -> KmlWaypointGenerator {
        KmlWaypointGenerator {
            waypoints: KmlWaypointGenerator::load_waypoints(file_name),
            current_waypoint: 0,
        }
    }
    fn load_waypoints(file_name: &str) -> Vec<Point> {
        let path = Path::new(file_name);
        if !path.exists() || !path.is_file() {
            panic!("File does not exist: {}", file_name);
        }
        let extension = match path.extension() {
            Some(ext) => match ext.to_str() {
                Some(ext2) => ext2,
                None => "",
            },
            None => "",
        };
        let kml_file_name = if extension == "kmz" {
            // A KML file is a zip archive containing a single file named "doc.kml"
            // that is an XML file
            let temp_directory = "/tmp/waypoints";
            match remove_dir_all(temp_directory) {
                Ok(()) => (),
                Err(err) => error!("Unable to remove temp directory: {}", err),
            };
            let zip_io_result = Command::new("unzip")
                .arg(file_name)
                .arg("-d")  // Output directory
                .arg(temp_directory)
                .spawn();
            let mut zip_child = match zip_io_result {
                Ok(child) => (child),
                Err(e) => panic!("Failed to unzip file: {}", e),
            };

            match zip_child.wait() {
                Ok(_) => "/tmp/waypoints/doc.kml",
                Err(e) => panic!("Failed to unzip file: {}", e),
            }
        } else {
            file_name
        };

        let mut waypoints = Vec::<Point>::new();
        let file_path = Path::new(kml_file_name);
        let file = match File::open(&file_path) {
            Ok(f) => f,
            Err(_) => panic!("Couldn't open doc.kml"),
        };
        let xml_file = BufReader::new(file);
        let mut coordinates_open_tag = false;
        // We should use a real XML parser here, but Google Earth saves the
        // <coordinates> tag on one line, then the coordinates on the next,
        // then the closing </coordinates> tag on the next, so we'll just rely
        // on that fact
        for line_option in xml_file.lines() {
            match line_option {
                Ok(line) => {
                    if line.contains("<coordinates>") {
                        coordinates_open_tag = true;
                    } else if coordinates_open_tag {
                        let mut latitude = 0.0f64;
                        let mut longitude = 0.0f64;
                        for long_lat_alt in line.split_whitespace() {
                            let mut iterator = long_lat_alt.split(',');
                            let mut success = true;
                            match iterator.next() {
                                Some(longitude_str) => {
                                    let parsed_longitude = longitude_str.parse::<f64>();
                                    match parsed_longitude {
                                        Ok(longitude_) => longitude = longitude_,
                                        Err(e) => {
                                            println!(
                                                "Unable to parse longitude: '{}', {}",
                                                longitude_str, e
                                            );
                                            success = false;
                                        }
                                    }
                                }
                                None => println!("No longitude"),
                            }

                            match iterator.next() {
                                Some(latitude_str) => {
                                    let parsed_latitude = latitude_str.parse::<f64>();
                                    match parsed_latitude {
                                        Ok(latitude_) => latitude = latitude_,
                                        Err(e) => {
                                            println!(
                                                "Unable to parse latitude: '{}', {}",
                                                latitude_str, e
                                            );
                                            success = false;
                                        }
                                    }
                                }
                                None => println!("No latitude"),
                            }

                            if success {
                                waypoints.push(latitude_longitude_to_point(latitude, longitude));
                            }
                        }
                        break;
                    }
                }
                Err(e) => println!("error {}", e),
            }
        }
        waypoints
    }
}

impl WaypointGenerator for KmlWaypointGenerator {
    #[allow(unused_variables)]
    fn get_current_waypoint(&self, point: &Point) -> Point {
        // TODO
        Point { x: 0.0, y: 0.0 }
    }

    #[allow(unused_variables)]
    fn get_current_raw_waypoint(&self, point: &Point) -> Point {
        // TODO
        Point { x: 0.0, y: 0.0 }
    }

    fn next(&mut self) {
        // TODO
    }

    #[allow(unused_variables)]
    fn reached(&self, point: &Point) -> bool {
        // TODO
        return false;
    }

    fn done(&self) -> bool {
        // TODO
        return false;
    }

    #[allow(unused_variables)]
    fn reach_distance(&self) -> Meters {
        1.0
    }
}
<|endoftext|>


<commit_before>//! A simple as possible example demonstrating how to use the `draw` API to display a texture.

use nannou::prelude::*;

fn main() {
    nannou::app(model).run();
}

struct Model {
    // Store the window ID so we can refer to this specific window later if needed.
    texture: wgpu::Texture,
}

fn model(app: &App) -> Model {
    // Create a new window! Store the ID so we can refer to it later.
    app.new_window().size(512, 512).view(view).build().unwrap();
    // Load the image from disk and upload it to a GPU texture.
    let assets = app.assets_path().unwrap();
    let img_path = assets.join("images").join("nature").join("nature_1.jpg");
    let texture = wgpu::Texture::from_path(app, img_path).unwrap();
    Model { texture }
}

// Draw the state of your `Model` into the given `Frame` here.
fn view(app: &App, model: &Model, frame: Frame) {
    frame.clear(BLACK);

    let draw = app.draw();
    draw.texture(&model.texture);

    draw.to_frame(app, &frame).unwrap();
}
<commit_msg>Remove window ID related comments in draw_texture.rs<commit_after>//! A simple as possible example demonstrating how to use the `draw` API to display a texture.

use nannou::prelude::*;

fn main() {
    nannou::app(model).run();
}

struct Model {
    texture: wgpu::Texture,
}

fn model(app: &App) -> Model {
    // Create a new window!
    app.new_window().size(512, 512).view(view).build().unwrap();
    // Load the image from disk and upload it to a GPU texture.
    let assets = app.assets_path().unwrap();
    let img_path = assets.join("images").join("nature").join("nature_1.jpg");
    let texture = wgpu::Texture::from_path(app, img_path).unwrap();
    Model { texture }
}

// Draw the state of your `Model` into the given `Frame` here.
fn view(app: &App, model: &Model, frame: Frame) {
    frame.clear(BLACK);

    let draw = app.draw();
    draw.texture(&model.texture);

    draw.to_frame(app, &frame).unwrap();
}
<|endoftext|>


<commit_before>use wayland_sys::server::*;

use event_loop::{create_event_loop, EventLoop};

pub struct Display {
    ptr: *mut wl_display,
}

pub fn create_display() -> (Display, EventLoop) {
    unsafe {
        let ptr = ffi_dispatch!(
            WAYLAND_SERVER_HANDLE,
            wl_display_create,
        );
        let el_ptr = ffi_dispatch!(
            WAYLAND_SERVER_HANDLE,
            wl_display_get_event_loop,
            ptr
        );
        (Display { ptr: ptr }, create_event_loop(el_ptr, Some(ptr)))
    }
}

impl Display {
    /// Flush events to the clients
    ///
    /// Will send as many pending events as possible to the respective sockets of the clients.
    /// Will not block, but might not send everything if the socket buffer fills up.
    fn flush_clients(&self) {
        let ret = unsafe { ffi_dispatch!(
            WAYLAND_SERVER_HANDLE,
            wl_display_flush_clients,
            display
        )};
    }
}

impl Drop for Display {
    fn drop(&mut self) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_display_destroy,
                self.ptr
            );
        }
    }
}
<commit_msg>server: bugfix wrong c/c<commit_after>use wayland_sys::server::*;

use event_loop::{create_event_loop, EventLoop};

pub struct Display {
    ptr: *mut wl_display,
}

pub fn create_display() -> (Display, EventLoop) {
    unsafe {
        let ptr = ffi_dispatch!(
            WAYLAND_SERVER_HANDLE,
            wl_display_create,
        );
        let el_ptr = ffi_dispatch!(
            WAYLAND_SERVER_HANDLE,
            wl_display_get_event_loop,
            ptr
        );
        (Display { ptr: ptr }, create_event_loop(el_ptr, Some(ptr)))
    }
}

impl Display {
    /// Flush events to the clients
    ///
    /// Will send as many pending events as possible to the respective sockets of the clients.
    /// Will not block, but might not send everything if the socket buffer fills up.
    fn flush_clients(&self) {
        let ret = unsafe { ffi_dispatch!(
            WAYLAND_SERVER_HANDLE,
            wl_display_flush_clients,
            self.ptr
        )};
    }
}

impl Drop for Display {
    fn drop(&mut self) {
        unsafe {
            ffi_dispatch!(
                WAYLAND_SERVER_HANDLE,
                wl_display_destroy,
                self.ptr
            );
        }
    }
}
<|endoftext|>


<commit_before>#![deny(elided_lifetimes_in_paths)]

use askama_shared::heritage::{Context, Heritage};
use askama_shared::input::{Print, Source, TemplateInput};
use askama_shared::parser::{parse, Expr, Node};
use askama_shared::{
    generator, get_template_source, read_config_file, CompileError, Config, Integrations,
};
use proc_macro::TokenStream;
use proc_macro2::Span;

use std::collections::HashMap;
use std::path::PathBuf;

#[proc_macro_derive(Template, attributes(template))]
pub fn derive_template(input: TokenStream) -> TokenStream {
    let ast: syn::DeriveInput = syn::parse(input).unwrap();
    match build_template(&ast) {
        Ok(source) => source.parse().unwrap(),
        Err(e) => syn::Error::new(Span::call_site(), e)
            .to_compile_error()
            .into(),
    }
}

/// Takes a `syn::DeriveInput` and generates source code for it
///
/// Reads the metadata from the `template()` attribute to get the template
/// metadata, then fetches the source from the filesystem. The source is
/// parsed, and the parse tree is fed to the code generator. Will print
/// the parse tree and/or generated source according to the `print` key's
/// value as passed to the `template()` attribute.
fn build_template(ast: &syn::DeriveInput) -> Result<String, CompileError> {
    let config_toml = read_config_file()?;
    let config = Config::new(&config_toml)?;
    let input = TemplateInput::new(ast, &config)?;
    let source: String = match input.source {
        Source::Source(ref s) => s.clone(),
        Source::Path(_) => get_template_source(&input.path)?,
    };

    let mut sources = HashMap::new();
    find_used_templates(&input, &mut sources, source)?;

    let mut parsed = HashMap::new();
    for (path, src) in &sources {
        parsed.insert(path, parse(src, input.syntax)?);
    }

    let mut contexts = HashMap::new();
    for (path, nodes) in &parsed {
        contexts.insert(*path, Context::new(input.config, path, nodes)?);
    }

    let ctx = &contexts[&input.path];
    let heritage = if !ctx.blocks.is_empty() || ctx.extends.is_some() {
        Some(Heritage::new(ctx, &contexts))
    } else {
        None
    };

    if input.print == Print::Ast || input.print == Print::All {
        eprintln!("{:?}", parsed[&input.path]);
    }

    let code = generator::generate(&input, &contexts, &heritage, INTEGRATIONS)?;
    if input.print == Print::Code || input.print == Print::All {
        eprintln!("{}", code);
    }
    Ok(code)
}

fn find_used_templates(
    input: &TemplateInput<'_>,
    map: &mut HashMap<PathBuf, String>,
    source: String,
) -> Result<(), CompileError> {
    let mut check = vec![(input.path.clone(), source)];
    while let Some((path, source)) = check.pop() {
        for n in parse(&source, input.syntax)? {
            match n {
                Node::Extends(Expr::StrLit(extends)) => {
                    let extends = input.config.find_template(extends, Some(&path))?;
                    let source = get_template_source(&extends)?;
                    check.push((extends, source));
                }
                Node::Import(_, import, _) => {
                    let import = input.config.find_template(import, Some(&path))?;
                    let source = get_template_source(&import)?;
                    check.push((import, source));
                }
                _ => {}
            }
        }
        map.insert(path, source);
    }
    Ok(())
}

const INTEGRATIONS: Integrations = Integrations {
    actix: cfg!(feature = "actix-web"),
    gotham: cfg!(feature = "gotham"),
    iron: cfg!(feature = "iron"),
    mendes: cfg!(feature = "mendes"),
    rocket: cfg!(feature = "rocket"),
    tide: cfg!(feature = "tide"),
    warp: cfg!(feature = "warp"),
};
<commit_msg>Handle build hangs due to unintended template recursion. (#539)<commit_after>#![deny(elided_lifetimes_in_paths)]

use askama_shared::heritage::{Context, Heritage};
use askama_shared::input::{Print, Source, TemplateInput};
use askama_shared::parser::{parse, Expr, Node};
use askama_shared::{
    generator, get_template_source, read_config_file, CompileError, Config, Integrations,
};
use proc_macro::TokenStream;
use proc_macro2::Span;

use std::collections::HashMap;
use std::path::PathBuf;

#[proc_macro_derive(Template, attributes(template))]
pub fn derive_template(input: TokenStream) -> TokenStream {
    let ast: syn::DeriveInput = syn::parse(input).unwrap();
    match build_template(&ast) {
        Ok(source) => source.parse().unwrap(),
        Err(e) => syn::Error::new(Span::call_site(), e)
            .to_compile_error()
            .into(),
    }
}

/// Takes a `syn::DeriveInput` and generates source code for it
///
/// Reads the metadata from the `template()` attribute to get the template
/// metadata, then fetches the source from the filesystem. The source is
/// parsed, and the parse tree is fed to the code generator. Will print
/// the parse tree and/or generated source according to the `print` key's
/// value as passed to the `template()` attribute.
fn build_template(ast: &syn::DeriveInput) -> Result<String, CompileError> {
    let config_toml = read_config_file()?;
    let config = Config::new(&config_toml)?;
    let input = TemplateInput::new(ast, &config)?;
    let source: String = match input.source {
        Source::Source(ref s) => s.clone(),
        Source::Path(_) => get_template_source(&input.path)?,
    };

    let mut sources = HashMap::new();
    find_used_templates(&input, &mut sources, source)?;

    let mut parsed = HashMap::new();
    for (path, src) in &sources {
        parsed.insert(path, parse(src, input.syntax)?);
    }

    let mut contexts = HashMap::new();
    for (path, nodes) in &parsed {
        contexts.insert(*path, Context::new(input.config, path, nodes)?);
    }

    let ctx = &contexts[&input.path];
    let heritage = if !ctx.blocks.is_empty() || ctx.extends.is_some() {
        Some(Heritage::new(ctx, &contexts))
    } else {
        None
    };

    if input.print == Print::Ast || input.print == Print::All {
        eprintln!("{:?}", parsed[&input.path]);
    }

    let code = generator::generate(&input, &contexts, &heritage, INTEGRATIONS)?;
    if input.print == Print::Code || input.print == Print::All {
        eprintln!("{}", code);
    }
    Ok(code)
}

fn find_used_templates(
    input: &TemplateInput<'_>,
    map: &mut HashMap<PathBuf, String>,
    source: String,
) -> Result<(), CompileError> {
    let mut dependency_graph = Vec::new();
    let mut check = vec![(input.path.clone(), source)];
    while let Some((path, source)) = check.pop() {
        for n in parse(&source, input.syntax)? {
            match n {
                Node::Extends(Expr::StrLit(extends)) => {
                    let extends = input.config.find_template(extends, Some(&path))?;
                    let dependency_path = (path.clone(), extends.clone());
                    if dependency_graph.contains(&dependency_path) {
                        return Err(CompileError::String(format!(
                            "cyclic dependecy in graph {:#?}",
                            dependency_graph
                                .iter()
                                .map(|e| format!("{:#?} --> {:#?}", e.0, e.1))
                                .collect::<Vec<String>>()
                        )));
                    }
                    dependency_graph.push(dependency_path);
                    let source = get_template_source(&extends)?;
                    check.push((extends, source));
                }
                Node::Import(_, import, _) => {
                    let import = input.config.find_template(import, Some(&path))?;
                    let source = get_template_source(&import)?;
                    check.push((import, source));
                }
                _ => {}
            }
        }
        map.insert(path, source);
    }
    Ok(())
}

const INTEGRATIONS: Integrations = Integrations {
    actix: cfg!(feature = "actix-web"),
    gotham: cfg!(feature = "gotham"),
    iron: cfg!(feature = "iron"),
    mendes: cfg!(feature = "mendes"),
    rocket: cfg!(feature = "rocket"),
    tide: cfg!(feature = "tide"),
    warp: cfg!(feature = "warp"),
};
<|endoftext|>


<commit_before>use hir::AsAssocItem;
use ide_db::helpers::{
    insert_use::{insert_use, ImportScope},
    mod_path_to_ast,
};
use syntax::{
    ast::{self, make},
    match_ast, ted, AstNode, SyntaxNode,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: replace_qualified_name_with_use
//
// Adds a use statement for a given fully-qualified name.
//
// ```
// # mod std { pub mod collections { pub struct HashMap<T, U>(T, U); } }
// fn process(map: std::collections::$0HashMap<String, String>) {}
// ```
// ->
// ```
// use std::collections::HashMap;
//
// # mod std { pub mod collections { pub struct HashMap<T, U>(T, U); } }
// fn process(map: HashMap<String, String>) {}
// ```
pub(crate) fn replace_qualified_name_with_use(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let path: ast::Path = ctx.find_node_at_offset()?;
    // We don't want to mess with use statements
    if path.syntax().ancestors().find_map(ast::UseTree::cast).is_some() {
        cov_mark::hit!(not_applicable_in_use);
        return None;
    }

    if path.qualifier().is_none() {
        cov_mark::hit!(dont_import_trivial_paths);
        return None;
    }

    // only offer replacement for non assoc items
    match ctx.sema.resolve_path(&path)? {
        hir::PathResolution::Def(def) if def.as_assoc_item(ctx.sema.db).is_none() => (),
        hir::PathResolution::Macro(_) => (),
        _ => return None,
    }
    // then search for an import for the first path segment of what we want to replace
    // that way it is less likely that we import the item from a different location due re-exports
    let module = match ctx.sema.resolve_path(&path.first_qualifier_or_self())? {
        hir::PathResolution::Def(module @ hir::ModuleDef::Module(_)) => module,
        _ => return None,
    };

    let scope = ImportScope::find_insert_use_container_with_macros(path.syntax(), &ctx.sema)?;
    let path_to_qualifier = ctx.sema.scope(path.syntax()).module()?.find_use_path_prefixed(
        ctx.sema.db,
        module,
        ctx.config.insert_use.prefix_kind,
    )?;
    let target = path.syntax().text_range();
    acc.add(
        AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite),
        "Replace qualified path with use",
        target,
        |builder| {
            // Now that we've brought the name into scope, re-qualify all paths that could be
            // affected (that is, all paths inside the node we added the `use` to).
            let scope = match scope {
                ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
                ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
                ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
            };
            // stick the found import in front of the to be replaced path
            let path = match mod_path_to_ast(&path_to_qualifier).qualifier() {
                Some(qualifier) => make::path_concat(qualifier, path),
                None => path,
            };
            shorten_paths(scope.as_syntax_node(), &path.clone_for_update());
            insert_use(&scope, path, &ctx.config.insert_use);
        },
    )
}

/// Adds replacements to `re` that shorten `path` in all descendants of `node`.
fn shorten_paths(node: &SyntaxNode, path: &ast::Path) {
    for child in node.children() {
        match_ast! {
            match child {
                // Don't modify `use` items, as this can break the `use` item when injecting a new
                // import into the use tree.
                ast::Use(_it) => continue,
                // Don't descend into submodules, they don't have the same `use` items in scope.
                // FIXME: This isn't true due to `super::*` imports?
                ast::Module(_it) => continue,
                ast::Path(p) => if maybe_replace_path(p.clone(), path.clone()).is_none() {
                    shorten_paths(p.syntax(), path);
                },
                _ => shorten_paths(&child, path),
            }
        }
    }
}

fn maybe_replace_path(path: ast::Path, target: ast::Path) -> Option<()> {
    if !path_eq_no_generics(path.clone(), target) {
        return None;
    }

    // Shorten `path`, leaving only its last segment.
    if let Some(parent) = path.qualifier() {
        ted::remove(parent.syntax());
    }
    if let Some(double_colon) = path.coloncolon_token() {
        ted::remove(&double_colon);
    }

    Some(())
}

fn path_eq_no_generics(lhs: ast::Path, rhs: ast::Path) -> bool {
    let mut lhs_curr = lhs;
    let mut rhs_curr = rhs;
    loop {
        match lhs_curr.segment().zip(rhs_curr.segment()) {
            Some((lhs, rhs))
                if lhs.coloncolon_token().is_some() == rhs.coloncolon_token().is_some()
                    && lhs
                        .name_ref()
                        .zip(rhs.name_ref())
                        .map_or(false, |(lhs, rhs)| lhs.text() == rhs.text()) =>
            {
                ()
            }
            _ => return false,
        }

        match (lhs_curr.qualifier(), rhs_curr.qualifier()) {
            (Some(lhs), Some(rhs)) => {
                lhs_curr = lhs;
                rhs_curr = rhs;
            }
            (None, None) => return true,
            _ => return false,
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn test_replace_already_imported() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fs { pub struct Path; } }
use std::fs;

fn main() {
    std::f$0s::Path
}",
            r"
mod std { pub mod fs { pub struct Path; } }
use std::fs;

fn main() {
    fs::Path
}",
        )
    }

    #[test]
    fn test_replace_add_use_no_anchor() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fs { pub struct Path; } }
std::fs::Path$0
    ",
            r"
use std::fs::Path;

mod std { pub mod fs { pub struct Path; } }
Path
    ",
        );
    }

    #[test]
    fn test_replace_add_use_no_anchor_middle_segment() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fs { pub struct Path; } }
std::fs$0::Path
    ",
            r"
use std::fs;

mod std { pub mod fs { pub struct Path; } }
fs::Path
    ",
        );
    }
    #[test]
    #[test]
    fn dont_import_trivial_paths() {
        cov_mark::check!(dont_import_trivial_paths);
        check_assist_not_applicable(replace_qualified_name_with_use, r"impl foo$0 for () {}");
    }

    #[test]
    fn test_replace_not_applicable_in_use() {
        cov_mark::check!(not_applicable_in_use);
        check_assist_not_applicable(replace_qualified_name_with_use, r"use std::fmt$0;");
    }

    #[test]
    fn replaces_all_affected_paths() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fmt { pub trait Debug {} } }
fn main() {
    std::fmt::Debug$0;
    let x: std::fmt::Debug = std::fmt::Debug;
}
    ",
            r"
use std::fmt::Debug;

mod std { pub mod fmt { pub trait Debug {} } }
fn main() {
    Debug;
    let x: Debug = Debug;
}
    ",
        );
    }

    #[test]
    fn does_not_replace_in_submodules() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fmt { pub trait Debug {} } }
fn main() {
    std::fmt::Debug$0;
}

mod sub {
    fn f() {
        std::fmt::Debug;
    }
}
    ",
            r"
use std::fmt::Debug;

mod std { pub mod fmt { pub trait Debug {} } }
fn main() {
    Debug;
}

mod sub {
    fn f() {
        std::fmt::Debug;
    }
}
    ",
        );
    }

    #[test]
    fn does_not_replace_in_use() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fmt { pub trait Display {} } }
use std::fmt::Display;

fn main() {
    std::fmt$0;
}
    ",
            r"
mod std { pub mod fmt { pub trait Display {} } }
use std::fmt::{self, Display};

fn main() {
    fmt;
}
    ",
        );
    }

    #[test]
    fn does_not_replace_assoc_item_path() {
        check_assist_not_applicable(
            replace_qualified_name_with_use,
            r"
pub struct Foo;
impl Foo {
    pub fn foo() {}
}

fn main() {
    Foo::foo$0();
}
",
        );
    }

    #[test]
    fn replace_reuses_path_qualifier() {
        check_assist(
            replace_qualified_name_with_use,
            r"
pub mod foo {
    struct Foo;
}

mod bar {
    pub use super::foo::Foo as Bar;
}

fn main() {
    foo::Foo$0;
}
",
            r"
use foo::Foo;

pub mod foo {
    struct Foo;
}

mod bar {
    pub use super::foo::Foo as Bar;
}

fn main() {
    Foo;
}
",
        );
    }
}
<commit_msg>Don't concat path in replace_qualified assist when they start with a keyword<commit_after>use hir::AsAssocItem;
use ide_db::helpers::{
    insert_use::{insert_use, ImportScope},
    mod_path_to_ast,
};
use syntax::{
    ast::{self, make},
    match_ast, ted, AstNode, SyntaxNode,
};

use crate::{AssistContext, AssistId, AssistKind, Assists};

// Assist: replace_qualified_name_with_use
//
// Adds a use statement for a given fully-qualified name.
//
// ```
// # mod std { pub mod collections { pub struct HashMap<T, U>(T, U); } }
// fn process(map: std::collections::$0HashMap<String, String>) {}
// ```
// ->
// ```
// use std::collections::HashMap;
//
// # mod std { pub mod collections { pub struct HashMap<T, U>(T, U); } }
// fn process(map: HashMap<String, String>) {}
// ```
pub(crate) fn replace_qualified_name_with_use(
    acc: &mut Assists,
    ctx: &AssistContext,
) -> Option<()> {
    let path: ast::Path = ctx.find_node_at_offset()?;
    // We don't want to mess with use statements
    if path.syntax().ancestors().find_map(ast::UseTree::cast).is_some() {
        cov_mark::hit!(not_applicable_in_use);
        return None;
    }

    if path.qualifier().is_none() {
        cov_mark::hit!(dont_import_trivial_paths);
        return None;
    }

    // only offer replacement for non assoc items
    match ctx.sema.resolve_path(&path)? {
        hir::PathResolution::Def(def) if def.as_assoc_item(ctx.sema.db).is_none() => (),
        hir::PathResolution::Macro(_) => (),
        _ => return None,
    }
    // then search for an import for the first path segment of what we want to replace
    // that way it is less likely that we import the item from a different location due re-exports
    let module = match ctx.sema.resolve_path(&path.first_qualifier_or_self())? {
        hir::PathResolution::Def(module @ hir::ModuleDef::Module(_)) => module,
        _ => return None,
    };

    let starts_with_name_ref = !matches!(
        path.first_segment().and_then(|it| it.kind()),
        Some(
            ast::PathSegmentKind::CrateKw
                | ast::PathSegmentKind::SuperKw
                | ast::PathSegmentKind::SelfKw
        )
    );
    let path_to_qualifier = starts_with_name_ref
        .then(|| {
            ctx.sema.scope(path.syntax()).module().and_then(|m| {
                m.find_use_path_prefixed(ctx.sema.db, module, ctx.config.insert_use.prefix_kind)
            })
        })
        .flatten();

    let scope = ImportScope::find_insert_use_container_with_macros(path.syntax(), &ctx.sema)?;
    let target = path.syntax().text_range();
    acc.add(
        AssistId("replace_qualified_name_with_use", AssistKind::RefactorRewrite),
        "Replace qualified path with use",
        target,
        |builder| {
            // Now that we've brought the name into scope, re-qualify all paths that could be
            // affected (that is, all paths inside the node we added the `use` to).
            let scope = match scope {
                ImportScope::File(it) => ImportScope::File(builder.make_mut(it)),
                ImportScope::Module(it) => ImportScope::Module(builder.make_mut(it)),
                ImportScope::Block(it) => ImportScope::Block(builder.make_mut(it)),
            };
            // stick the found import in front of the to be replaced path
            let path = match path_to_qualifier.and_then(|it| mod_path_to_ast(&it).qualifier()) {
                Some(qualifier) => make::path_concat(qualifier, path),
                None => path,
            };
            shorten_paths(scope.as_syntax_node(), &path.clone_for_update());
            insert_use(&scope, path, &ctx.config.insert_use);
        },
    )
}

/// Adds replacements to `re` that shorten `path` in all descendants of `node`.
fn shorten_paths(node: &SyntaxNode, path: &ast::Path) {
    for child in node.children() {
        match_ast! {
            match child {
                // Don't modify `use` items, as this can break the `use` item when injecting a new
                // import into the use tree.
                ast::Use(_it) => continue,
                // Don't descend into submodules, they don't have the same `use` items in scope.
                // FIXME: This isn't true due to `super::*` imports?
                ast::Module(_it) => continue,
                ast::Path(p) => if maybe_replace_path(p.clone(), path.clone()).is_none() {
                    shorten_paths(p.syntax(), path);
                },
                _ => shorten_paths(&child, path),
            }
        }
    }
}

fn maybe_replace_path(path: ast::Path, target: ast::Path) -> Option<()> {
    if !path_eq_no_generics(path.clone(), target) {
        return None;
    }

    // Shorten `path`, leaving only its last segment.
    if let Some(parent) = path.qualifier() {
        ted::remove(parent.syntax());
    }
    if let Some(double_colon) = path.coloncolon_token() {
        ted::remove(&double_colon);
    }

    Some(())
}

fn path_eq_no_generics(lhs: ast::Path, rhs: ast::Path) -> bool {
    let mut lhs_curr = lhs;
    let mut rhs_curr = rhs;
    loop {
        match lhs_curr.segment().zip(rhs_curr.segment()) {
            Some((lhs, rhs))
                if lhs.coloncolon_token().is_some() == rhs.coloncolon_token().is_some()
                    && lhs
                        .name_ref()
                        .zip(rhs.name_ref())
                        .map_or(false, |(lhs, rhs)| lhs.text() == rhs.text()) =>
            {
                ()
            }
            _ => return false,
        }

        match (lhs_curr.qualifier(), rhs_curr.qualifier()) {
            (Some(lhs), Some(rhs)) => {
                lhs_curr = lhs;
                rhs_curr = rhs;
            }
            (None, None) => return true,
            _ => return false,
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    #[test]
    fn test_replace_already_imported() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fs { pub struct Path; } }
use std::fs;

fn main() {
    std::f$0s::Path
}",
            r"
mod std { pub mod fs { pub struct Path; } }
use std::fs;

fn main() {
    fs::Path
}",
        )
    }

    #[test]
    fn test_replace_add_use_no_anchor() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fs { pub struct Path; } }
std::fs::Path$0
    ",
            r"
use std::fs::Path;

mod std { pub mod fs { pub struct Path; } }
Path
    ",
        );
    }

    #[test]
    fn test_replace_add_use_no_anchor_middle_segment() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fs { pub struct Path; } }
std::fs$0::Path
    ",
            r"
use std::fs;

mod std { pub mod fs { pub struct Path; } }
fs::Path
    ",
        );
    }
    #[test]
    #[test]
    fn dont_import_trivial_paths() {
        cov_mark::check!(dont_import_trivial_paths);
        check_assist_not_applicable(replace_qualified_name_with_use, r"impl foo$0 for () {}");
    }

    #[test]
    fn test_replace_not_applicable_in_use() {
        cov_mark::check!(not_applicable_in_use);
        check_assist_not_applicable(replace_qualified_name_with_use, r"use std::fmt$0;");
    }

    #[test]
    fn replaces_all_affected_paths() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fmt { pub trait Debug {} } }
fn main() {
    std::fmt::Debug$0;
    let x: std::fmt::Debug = std::fmt::Debug;
}
    ",
            r"
use std::fmt::Debug;

mod std { pub mod fmt { pub trait Debug {} } }
fn main() {
    Debug;
    let x: Debug = Debug;
}
    ",
        );
    }

    #[test]
    fn does_not_replace_in_submodules() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fmt { pub trait Debug {} } }
fn main() {
    std::fmt::Debug$0;
}

mod sub {
    fn f() {
        std::fmt::Debug;
    }
}
    ",
            r"
use std::fmt::Debug;

mod std { pub mod fmt { pub trait Debug {} } }
fn main() {
    Debug;
}

mod sub {
    fn f() {
        std::fmt::Debug;
    }
}
    ",
        );
    }

    #[test]
    fn does_not_replace_in_use() {
        check_assist(
            replace_qualified_name_with_use,
            r"
mod std { pub mod fmt { pub trait Display {} } }
use std::fmt::Display;

fn main() {
    std::fmt$0;
}
    ",
            r"
mod std { pub mod fmt { pub trait Display {} } }
use std::fmt::{self, Display};

fn main() {
    fmt;
}
    ",
        );
    }

    #[test]
    fn does_not_replace_assoc_item_path() {
        check_assist_not_applicable(
            replace_qualified_name_with_use,
            r"
pub struct Foo;
impl Foo {
    pub fn foo() {}
}

fn main() {
    Foo::foo$0();
}
",
        );
    }

    #[test]
    fn replace_reuses_path_qualifier() {
        check_assist(
            replace_qualified_name_with_use,
            r"
pub mod foo {
    pub struct Foo;
}

mod bar {
    pub use super::foo::Foo as Bar;
}

fn main() {
    foo::Foo$0;
}
",
            r"
use foo::Foo;

pub mod foo {
    pub struct Foo;
}

mod bar {
    pub use super::foo::Foo as Bar;
}

fn main() {
    Foo;
}
",
        );
    }
}
<|endoftext|>


<commit_before>/*
Copyright (C) 2018-2019 de4dot@gmail.com

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

pub(crate) mod enums;
mod instr_infos;
pub(super) mod misc;
pub(super) mod mnemonic_opts_parser;
pub(super) mod number;
pub(super) mod opt_value;
pub(super) mod options;
mod options_parser;
pub(super) mod options_test_case_parser;
pub(super) mod opts_info;
mod opts_infos;
pub(super) mod registers;
pub(super) mod sym_res;
pub(super) mod sym_res_test_case;
pub(super) mod sym_res_test_parser;

use self::instr_infos::*;
#[cfg(feature = "encoder")]
use super::super::encoder::tests::non_decoded_tests;
use super::super::test_utils::create_decoder;
use super::super::test_utils::from_str_conv::to_vec_u8;
use super::super::{Code, Decoder, Instruction};
use super::Formatter;
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
#[cfg(not(feature = "std"))]
use alloc::string::String;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;

fn get_lines_ignore_comments(filename: &Path) -> Vec<String> {
	let display_filename = filename.display().to_string();
	let file = File::open(filename).unwrap_or_else(|_| panic!("Couldn't open file {}", display_filename));
	BufReader::new(file)
		.lines()
		.map(|r| r.unwrap_or_else(|e| panic!(e.to_string())))
		.filter(|line| !line.is_empty() && !line.starts_with('#'))
		.collect()
}

pub(super) fn formatter_test(bitness: u32, dir: &str, filename: &str, is_misc: bool, fmt_factory: fn() -> Box<Formatter>) {
	let infos = get_infos(bitness, is_misc);
	let lines = get_formatted_lines(bitness, dir, filename);
	if infos.len() != lines.len() {
		panic!("Infos len ({}) != fmt len ({}); dir={}, filename: {}, is_misc: {}", infos.len(), lines.len(), dir, filename, is_misc);
	}
	for i in infos.iter().zip(lines.iter().map(|x| x.as_str())) {
		format_test_info(i.0, i.1, fmt_factory());
	}
}

#[cfg(feature = "encoder")]
pub(super) fn formatter_test_nondec(bitness: u32, dir: &str, filename: &str, fmt_factory: fn() -> Box<Formatter>) {
	let instrs = non_decoded_tests::get_infos(bitness);
	let lines = get_formatted_lines(bitness, dir, filename);
	if instrs.len() != instrs.len() {
		panic!("Instrs len ({}) != fmt len ({}); dir={}, filename: {}", instrs.len(), lines.len(), dir, filename);
	}
	for i in instrs.iter().zip(lines.iter().map(|x| x.as_str())) {
		format_test_instruction(&(i.0).1, i.1, fmt_factory());
	}
}

fn format_test_info(info: &InstructionInfo, formatted_string: &str, formatter: Box<Formatter>) {
	format_test(info.bitness, &info.hex_bytes, info.code, info.options, formatted_string, formatter);
}

#[cfg(feature = "encoder")]
fn format_test_instruction(instruction: &Instruction, formatted_string: &str, formatter: Box<Formatter>) {
	format_test_instruction_core(instruction, formatted_string, formatter);
}

fn format_test(bitness: u32, hex_bytes: &str, code: Code, options: u32, formatted_string: &str, formatter: Box<Formatter>) {
	let bytes = to_vec_u8(hex_bytes).unwrap();
	let mut decoder = create_decoder(bitness, &bytes, options).0;
	let mut ip = decoder.ip();
	let instr = decoder.decode();
	assert_eq!(code, instr.code());
	assert_eq!(ip as u16, instr.ip16());
	assert_eq!(ip as u32, instr.ip32());
	assert_eq!(ip, instr.ip());
	ip += instr.len() as u64;
	assert_eq!(ip, decoder.ip());
	assert_eq!(ip as u16, instr.next_ip16());
	assert_eq!(ip as u32, instr.next_ip32());
	assert_eq!(ip, instr.next_ip());
	format_test_instruction_core(&instr, formatted_string, formatter);
}

fn format_test_instruction_core(instruction: &Instruction, formatted_string: &str, mut formatter: Box<Formatter>) {
	let mut actual_formatted_string = String::new();
	formatter.format(instruction, &mut actual_formatted_string);
	assert_eq!(formatted_string, actual_formatted_string);

	let mut mnemonic = String::new();
	formatter.format_mnemonic(instruction, &mut mnemonic);
	let op_count = formatter.operand_count(instruction);
	let mut operands: Vec<String> = Vec::with_capacity(op_count as usize);
	for i in 0..op_count {
		let mut output = String::new();
		formatter.format_operand(instruction, &mut output, i);
		operands.push(output);
	}
	let mut output = String::new();
	output.push_str(&mnemonic);
	if !operands.is_empty() {
		output.push(' ');
		for (i, operand) in operands.iter().enumerate() {
			if i > 0 {
				formatter.format_operand_separator(instruction, &mut output);
			}
			output.push_str(operand);
		}
	}
	assert_eq!(formatted_string, output);

	let mut all_operands = String::new();
	formatter.format_all_operands(instruction, &mut all_operands);
	let actual_formatted_string = if all_operands.is_empty() { mnemonic } else { format!("{} {}", mnemonic, all_operands) };
	assert_eq!(formatted_string, actual_formatted_string);
}

fn simple_format_test<F: Fn(&mut Decoder)>(
	bitness: u32, hex_bytes: &str, code: Code, decoder_options: u32, formatted_string: &str, formatter: &mut Formatter, init_decoder: F,
) {
	let bytes = to_vec_u8(hex_bytes).unwrap();
	let mut decoder = create_decoder(bitness, &bytes, decoder_options).0;
	(init_decoder)(&mut decoder);
	let mut next_rip = decoder.ip();
	let instruction = decoder.decode();
	assert_eq!(code, instruction.code());
	assert_eq!(next_rip as u16, instruction.ip16());
	assert_eq!(next_rip as u32, instruction.ip32());
	assert_eq!(next_rip, instruction.ip());
	next_rip = next_rip.wrapping_add(instruction.len() as u64);
	assert_eq!(next_rip, decoder.ip());
	assert_eq!(next_rip as u16, instruction.next_ip16());
	assert_eq!(next_rip as u32, instruction.next_ip32());
	assert_eq!(next_rip, instruction.next_ip());

	let mut output = String::new();
	formatter.format(&instruction, &mut output);
	assert_eq!(formatted_string, output);
}
<commit_msg>Add Instruction Display trait test<commit_after>/*
Copyright (C) 2018-2019 de4dot@gmail.com

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

pub(crate) mod enums;
mod instr_infos;
pub(super) mod misc;
pub(super) mod mnemonic_opts_parser;
pub(super) mod number;
pub(super) mod opt_value;
pub(super) mod options;
mod options_parser;
pub(super) mod options_test_case_parser;
pub(super) mod opts_info;
mod opts_infos;
pub(super) mod registers;
pub(super) mod sym_res;
pub(super) mod sym_res_test_case;
pub(super) mod sym_res_test_parser;

use self::instr_infos::*;
#[cfg(feature = "encoder")]
use super::super::encoder::tests::non_decoded_tests;
use super::super::test_utils::create_decoder;
use super::super::test_utils::from_str_conv::to_vec_u8;
use super::super::{Code, Decoder, DecoderOptions, Instruction};
use super::Formatter;
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
#[cfg(not(feature = "std"))]
use alloc::string::String;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::Path;

fn get_lines_ignore_comments(filename: &Path) -> Vec<String> {
	let display_filename = filename.display().to_string();
	let file = File::open(filename).unwrap_or_else(|_| panic!("Couldn't open file {}", display_filename));
	BufReader::new(file)
		.lines()
		.map(|r| r.unwrap_or_else(|e| panic!(e.to_string())))
		.filter(|line| !line.is_empty() && !line.starts_with('#'))
		.collect()
}

pub(super) fn formatter_test(bitness: u32, dir: &str, filename: &str, is_misc: bool, fmt_factory: fn() -> Box<Formatter>) {
	let infos = get_infos(bitness, is_misc);
	let lines = get_formatted_lines(bitness, dir, filename);
	if infos.len() != lines.len() {
		panic!("Infos len ({}) != fmt len ({}); dir={}, filename: {}, is_misc: {}", infos.len(), lines.len(), dir, filename, is_misc);
	}
	for i in infos.iter().zip(lines.iter().map(|x| x.as_str())) {
		format_test_info(i.0, i.1, fmt_factory());
	}
}

#[cfg(feature = "encoder")]
pub(super) fn formatter_test_nondec(bitness: u32, dir: &str, filename: &str, fmt_factory: fn() -> Box<Formatter>) {
	let instrs = non_decoded_tests::get_infos(bitness);
	let lines = get_formatted_lines(bitness, dir, filename);
	if instrs.len() != instrs.len() {
		panic!("Instrs len ({}) != fmt len ({}); dir={}, filename: {}", instrs.len(), lines.len(), dir, filename);
	}
	for i in instrs.iter().zip(lines.iter().map(|x| x.as_str())) {
		format_test_instruction(&(i.0).1, i.1, fmt_factory());
	}
}

fn format_test_info(info: &InstructionInfo, formatted_string: &str, formatter: Box<Formatter>) {
	format_test(info.bitness, &info.hex_bytes, info.code, info.options, formatted_string, formatter);
}

#[cfg(feature = "encoder")]
fn format_test_instruction(instruction: &Instruction, formatted_string: &str, formatter: Box<Formatter>) {
	format_test_instruction_core(instruction, formatted_string, formatter);
}

fn format_test(bitness: u32, hex_bytes: &str, code: Code, options: u32, formatted_string: &str, formatter: Box<Formatter>) {
	let bytes = to_vec_u8(hex_bytes).unwrap();
	let mut decoder = create_decoder(bitness, &bytes, options).0;
	let mut ip = decoder.ip();
	let instr = decoder.decode();
	assert_eq!(code, instr.code());
	assert_eq!(ip as u16, instr.ip16());
	assert_eq!(ip as u32, instr.ip32());
	assert_eq!(ip, instr.ip());
	ip += instr.len() as u64;
	assert_eq!(ip, decoder.ip());
	assert_eq!(ip as u16, instr.next_ip16());
	assert_eq!(ip as u32, instr.next_ip32());
	assert_eq!(ip, instr.next_ip());
	format_test_instruction_core(&instr, formatted_string, formatter);
}

fn format_test_instruction_core(instruction: &Instruction, formatted_string: &str, mut formatter: Box<Formatter>) {
	let mut actual_formatted_string = String::new();
	formatter.format(instruction, &mut actual_formatted_string);
	assert_eq!(formatted_string, actual_formatted_string);

	let mut mnemonic = String::new();
	formatter.format_mnemonic(instruction, &mut mnemonic);
	let op_count = formatter.operand_count(instruction);
	let mut operands: Vec<String> = Vec::with_capacity(op_count as usize);
	for i in 0..op_count {
		let mut output = String::new();
		formatter.format_operand(instruction, &mut output, i);
		operands.push(output);
	}
	let mut output = String::new();
	output.push_str(&mnemonic);
	if !operands.is_empty() {
		output.push(' ');
		for (i, operand) in operands.iter().enumerate() {
			if i > 0 {
				formatter.format_operand_separator(instruction, &mut output);
			}
			output.push_str(operand);
		}
	}
	assert_eq!(formatted_string, output);

	let mut all_operands = String::new();
	formatter.format_all_operands(instruction, &mut all_operands);
	let actual_formatted_string = if all_operands.is_empty() { mnemonic } else { format!("{} {}", mnemonic, all_operands) };
	assert_eq!(formatted_string, actual_formatted_string);
}

fn simple_format_test<F: Fn(&mut Decoder)>(
	bitness: u32, hex_bytes: &str, code: Code, decoder_options: u32, formatted_string: &str, formatter: &mut Formatter, init_decoder: F,
) {
	let bytes = to_vec_u8(hex_bytes).unwrap();
	let mut decoder = create_decoder(bitness, &bytes, decoder_options).0;
	(init_decoder)(&mut decoder);
	let mut next_rip = decoder.ip();
	let instruction = decoder.decode();
	assert_eq!(code, instruction.code());
	assert_eq!(next_rip as u16, instruction.ip16());
	assert_eq!(next_rip as u32, instruction.ip32());
	assert_eq!(next_rip, instruction.ip());
	next_rip = next_rip.wrapping_add(instruction.len() as u64);
	assert_eq!(next_rip, decoder.ip());
	assert_eq!(next_rip as u16, instruction.next_ip16());
	assert_eq!(next_rip as u32, instruction.next_ip32());
	assert_eq!(next_rip, instruction.next_ip());

	let mut output = String::new();
	formatter.format(&instruction, &mut output);
	assert_eq!(formatted_string, output);
}

#[test]
#[cfg_attr(feature = "cargo-clippy", allow(clippy::same_functions_in_if_condition))]
#[cfg_attr(feature = "cargo-clippy", allow(clippy::if_same_then_else))]
fn display_trait() {
	let bytes = b"\x00\xCE";
	let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
	let instr = decoder.decode();
	let expected = if cfg!(feature = "masm") {
		"add dh,cl"
	} else if cfg!(feature = "nasm") {
		"add dh,cl"
	} else if cfg!(feature = "intel") {
		"add dh,cl"
	} else if cfg!(feature = "gas") {
		"add %cl,%dh"
	} else {
		unreachable!()
	};
	let actual = format!("{}", instr);
	assert_eq!(expected, actual);
	let actual = instr.to_string();
	assert_eq!(expected, actual);
}
<|endoftext|>