<commit_before>//! This is a binary running in both local and server environment
//!
//! You have to provide all needed configuration attributes via command line parameters,
//! or you could specify a configuration file. The format of configuration file is defined
//! in mod `config`.
//!
//! *It should be notice that the extended configuration file is not suitable for the server
//! side.*

use std::{env, path::Path};

use clap::{App, AppSettings};
use shadowsocks_rust::service::{local, manager, server};

fn main() {
    let app = App::new("shadowsocks")
        .version(shadowsocks_rust::VERSION)
        .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)");

    // Allow running `ssservice` as symlink of `sslocal`, `ssserver` and `ssmanager`
    if let Some(program_path) = env::args().next() {
        if let Some(program_name) = Path::new(&program_path).file_name() {
            match program_name.to_str() {
                Some("sslocal") => return local::main(&local::define_command_line_options(app).get_matches()),
                Some("ssserver") => return server::main(&local::define_command_line_options(app).get_matches()),
                Some("ssmanager") => return manager::main(&local::define_command_line_options(app).get_matches()),
                _ => {}
            }
        }
    }

    let matches = app
        .setting(AppSettings::SubcommandRequired)
        .subcommand(local::define_command_line_options(App::new("local")).about("Shadowsocks Local service"))
        .subcommand(server::define_command_line_options(App::new("server")).about("Shadowsocks Server service"))
        .subcommand(
            manager::define_command_line_options(App::new("manager")).about("Shadowsocks Server Manager service"),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("local", matches)) => local::main(matches),
        Some(("server", matches)) => server::main(matches),
        Some(("manager", matches)) => manager::main(matches),
        _ => unreachable!("expecting a subcommand"),
    }
}
<commit_msg>fix(ssservice): fixed command line option when running as symlink of ssserver/ssmanager<commit_after>//! This is a binary running in both local and server environment
//!
//! You have to provide all needed configuration attributes via command line parameters,
//! or you could specify a configuration file. The format of configuration file is defined
//! in mod `config`.
//!
//! *It should be notice that the extended configuration file is not suitable for the server
//! side.*

use std::{env, path::Path};

use clap::{App, AppSettings};
use shadowsocks_rust::service::{local, manager, server};

fn main() {
    let app = App::new("shadowsocks")
        .version(shadowsocks_rust::VERSION)
        .about("A fast tunnel proxy that helps you bypass firewalls. (https://shadowsocks.org)");

    // Allow running `ssservice` as symlink of `sslocal`, `ssserver` and `ssmanager`
    if let Some(program_path) = env::args().next() {
        if let Some(program_name) = Path::new(&program_path).file_name() {
            match program_name.to_str() {
                Some("sslocal") => return local::main(&local::define_command_line_options(app).get_matches()),
                Some("ssserver") => return server::main(&server::define_command_line_options(app).get_matches()),
                Some("ssmanager") => return manager::main(&manager::define_command_line_options(app).get_matches()),
                _ => {}
            }
        }
    }

    let matches = app
        .setting(AppSettings::SubcommandRequired)
        .subcommand(local::define_command_line_options(App::new("local")).about("Shadowsocks Local service"))
        .subcommand(server::define_command_line_options(App::new("server")).about("Shadowsocks Server service"))
        .subcommand(
            manager::define_command_line_options(App::new("manager")).about("Shadowsocks Server Manager service"),
        )
        .get_matches();

    match matches.subcommand() {
        Some(("local", matches)) => local::main(matches),
        Some(("server", matches)) => server::main(matches),
        Some(("manager", matches)) => manager::main(matches),
        _ => unreachable!("expecting a subcommand"),
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate serde_derive;
extern crate serde_xml_rs;

#[derive(Debug, Deserialize)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

fn default_pose() -> Pose {
    Pose {
        xyz: empty_vec3(),
        rpy: empty_vec3(),
    }
}

fn default_mass() -> Mass {
    Mass { value: 0.0 }
}

fn default_inertia() -> Inertia {
    Inertia {
        ixx: 0.0,
        ixy: 0.0,
        ixz: 0.0,
        iyy: 0.0,
        iyz: 0.0,
        izz: 0.0,
    }
}

fn default_inertial() -> Inertial {
    Inertial {
        origin: default_pose(),
        mass: default_mass(),
        inertia: default_inertia(),
    }
}

#[derive(Debug, Deserialize)]
pub struct Inertial {
    #[serde(default = "default_pose")]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize)]
pub enum Geometry {
    #[serde(rename = "box")]
    Box { size: String },
    #[serde(rename = "cylinder")]
    Cylinder { radius: f64, length: f64 },
    #[serde(rename = "sphere")]
    Sphere { radius: f64 },
    #[serde(rename = "mesh")]
    Mesh { filename: String, scale: f64 },
}

#[derive(Debug, Deserialize)]
pub struct Color {
    #[serde(default)]
    pub rgba: String,
}

#[derive(Debug, Deserialize)]
pub struct Texture {
    #[serde(default)]
    pub filename: String,
}

#[derive(Debug, Deserialize)]
pub struct Material {
    #[serde(default)]
    pub name: String,
    #[serde(default = "default_color")]
    pub color: Color,
    #[serde(default = "default_texture")]
    pub texture: Texture,
}

fn default_geometry() -> Geometry {
    Geometry::Box { size: "0 0 0".to_string() }
}

fn default_visual() -> Visual {
    Visual {
        name: "".to_string(),
        origin: default_pose(),
        geometry: default_geometry(),
        material: default_material(),
    }
}

fn default_texture() -> Texture {
    Texture { filename: "".to_string() }
}

fn default_color() -> Color {
    Color { rgba: "0 0 0 0".to_string() }
}

fn default_material() -> Material {
    Material {
        name: "".to_string(),
        color: default_color(),
        texture: default_texture(),
    }
}

#[derive(Debug, Deserialize)]
pub struct Visual {
    #[serde(default)]
    pub name: String,
    #[serde(default = "default_pose")]
    pub origin: Pose,
    pub geometry: Geometry,
    #[serde(default = "default_material")]
    pub material: Material,
}

fn default_collision() -> Collision {
    Collision {
        name: "".to_string(),
        origin: default_pose(),
        geometry: default_geometry(),
    }
}

#[derive(Debug, Deserialize)]
pub struct Collision {
    #[serde(default)]
    pub name: String,
    pub origin: Pose,
    pub geometry: Geometry,
}

#[derive(Debug, Deserialize)]
pub struct Link {
    pub name: String,
    #[serde(default = "default_inertial")]
    pub inertial: Inertial,
    #[serde(default = "default_visual")]
    pub visual: Visual,
    #[serde(default = "default_collision")]
    pub collision: Collision,
}

#[derive(Debug, Deserialize)]
pub struct Axis {
    pub xyz: String,
}

fn parse_array_from_string(string: &str) -> [f64; 3] {
    let vec = string.split(" ").filter_map(|x| x.parse::<f64>().ok()).collect::<Vec<_>>();
    let mut arr = [0.0f64; 3];
    for i in 0..3 {
        arr[i] = vec[i];
    }
    arr
}

impl Axis {
    pub fn xyz_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.xyz)
    }
}

fn default_axis() -> Axis {
    Axis { xyz: "1 0 0".to_string() }
}

fn empty_vec3() -> String {
    "0 0 0".to_string()
}

#[derive(Debug, Deserialize)]
pub struct Pose {
    #[serde(default = "empty_vec3")]
    pub xyz: String,
    #[serde(default = "empty_vec3")]
    pub rpy: String,
}

impl Pose {
    pub fn xyz_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.xyz)
    }
    pub fn rpy_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.rpy)
    }
}

#[derive(Debug, Deserialize)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: String,
    #[serde(default = "default_pose")]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default = "default_axis")]
    pub axis: Axis,
}

#[derive(Debug, Deserialize)]
pub struct Robot {
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,
}

#[test]
fn it_works() {
    use serde_xml_rs::deserialize;
    let s = r##"
        <robot name="robo">
            <link name="shoulder1">
                <inertial>
                    <origin xyz="0 0 0.5" rpy="0 0 0"/>
                    <mass value="1"/>
                    <inertia ixx="100"  ixy="0"  ixz="0" iyy="100" iyz="0" izz="100" />
                </inertial>
                <visual>
                    <origin xyz="0.1 0.2 0.3" rpy="-0.1 -0.2  -0.3" />
                    <geometry>
                        <box size="1 1 1" />
                    </geometry>
                    <material name="Cyan">
                        <color rgba="0 1.0 1.0 1.0"/>
                    </material>
                </visual>
                <collision>
                    <origin xyz="0 0 0" rpy="0 0 0"/>
                    <geometry>
                        <cylinder radius="1" length="0.5"/>
                    </geometry>
                </collision>
            </link>
            <link name="elbow1" />
            <link name="wrist1" />
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0 0.0 0.1" />
                <parent link="shoulder1" />
                <child link="elbow1" />
                <axis xyz="0 1 -1" />
            </joint>
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0, 0.0, 0.0" />
                <parent link="elbow1" />
                <child link="wrist1" />
                <axis xyz="0 1 0" />
            </joint>
        </robot>
    "##;
    let robo: Robot = deserialize(s.as_bytes()).unwrap();
    assert_eq!(robo.name, "robo");
    assert_eq!(robo.links.len(), 3);
    assert_eq!(robo.joints.len(), 2);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[0], 0.1);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[1], 0.2);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[2], 0.3);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[0], -0.1);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[1], -0.2);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[2], -0.3);

    assert_eq!(robo.joints[0].name, "shoulder_pitch");
    assert_eq!(robo.joints[0].axis.xyz, "0 1 -1");
    assert_eq!(robo.joints[0].axis.xyz_as_array()[0], 0.0f64);
    assert_eq!(robo.joints[0].axis.xyz_as_array()[1], 1.0f64);
    assert_eq!(robo.joints[0].axis.xyz_as_array()[2], -1.0f64);
    assert_eq!(robo.joints[0].origin.xyz, "0.0 0.0 0.1");
}
<commit_msg>Use Default trait<commit_after>#[macro_use]
extern crate serde_derive;
extern crate serde_xml_rs;

#[derive(Debug, Deserialize, Default)]
pub struct Mass {
    pub value: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct Inertia {
    pub ixx: f64,
    pub ixy: f64,
    pub ixz: f64,
    pub iyy: f64,
    pub iyz: f64,
    pub izz: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct Inertial {
    #[serde(default)]
    pub origin: Pose,
    pub mass: Mass,
    pub inertia: Inertia,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Geometry {
    Box { size: String },
    Cylinder { radius: f64, length: f64 },
    Sphere { radius: f64 },
    Mesh { filename: String, scale: f64 },
}

impl Default for Geometry {
    fn default() -> Geometry {
        Geometry::Box { size: "0 0 0".to_string() }
    }
}

#[derive(Debug, Deserialize)]
pub struct Color {
    pub rgba: String,
}

impl Default for Color {
    fn default() -> Color {
        Color { rgba: "0 0 0 0".to_string() }
    }
}

#[derive(Debug, Deserialize)]
pub struct Texture {
    pub filename: String,
}

impl Default for Texture {
    fn default() -> Texture {
        Texture { filename: "".to_string() }
    }
}

#[derive(Debug, Deserialize, Default)]
pub struct Material {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub color: Color,
    #[serde(default)]
    pub texture: Texture,
}

#[derive(Debug, Deserialize, Default)]
pub struct Visual {
    #[serde(default)]
    pub name: String,
    #[serde(default)]
    pub origin: Pose,
    pub geometry: Geometry,
    #[serde(default)]
    pub material: Material,
}

#[derive(Debug, Deserialize, Default)]
pub struct Collision {
    #[serde(default)]
    pub name: String,
    pub origin: Pose,
    pub geometry: Geometry,
}

#[derive(Debug, Deserialize)]
pub struct Link {
    pub name: String,
    #[serde(default)]
    pub inertial: Inertial,
    #[serde(default)]
    pub visual: Visual,
    #[serde(default)]
    pub collision: Collision,
}

#[derive(Debug, Deserialize)]
pub struct Axis {
    pub xyz: String,
}

fn parse_array_from_string(string: &str) -> [f64; 3] {
    let vec = string.split(" ").filter_map(|x| x.parse::<f64>().ok()).collect::<Vec<_>>();
    assert!(vec.len() == 3);
    let mut arr = [0.0f64; 3];
    for i in 0..3 {
        arr[i] = vec[i];
    }
    arr
}

impl Axis {
    pub fn xyz_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.xyz)
    }
}

impl Default for Axis {
    fn default() -> Axis {
        Axis { xyz: "1 0 0".to_string() }
    }
}

#[derive(Debug, Deserialize)]
pub struct Pose {
    #[serde(default)]
    pub xyz: String,
    #[serde(default)]
    pub rpy: String,
}

impl Pose {
    pub fn xyz_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.xyz)
    }
    pub fn rpy_as_array(&self) -> [f64; 3] {
        parse_array_from_string(&self.rpy)
    }
}

impl Default for Pose {
    fn default() -> Pose {
        Pose {
            xyz: "0 0 0".to_string(),
            rpy: "0 0 0".to_string(),
        }
    }
}

#[derive(Debug, Deserialize)]
pub struct LinkName {
    pub link: String,
}

#[derive(Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum JointType {
    Revolute,
    Continuous,
    Prismatic,
    Fixed,
    Floating,
    Planar,
}

#[derive(Debug, Deserialize)]
pub struct JointLimit {
    #[serde(default)]
    pub lower: f64,
    #[serde(default)]
    pub upper: f64,
    pub effort: f64,
    pub velocity: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct Mimic {
    joint: String,
    multiplier: f64,
    offset: f64,
}

#[derive(Debug, Deserialize, Default)]
pub struct SafetyController {
    soft_lower_limit: f64,
    soft_upper_limit: f64,
    k_position: f64,
    k_velocity: f64,
}

#[derive(Debug, Deserialize)]
pub struct Joint {
    pub name: String,
    #[serde(rename = "type")]
    pub joint_type: String,
    #[serde(default)]
    pub origin: Pose,
    pub parent: LinkName,
    pub child: LinkName,
    #[serde(default)]
    pub axis: Axis,
    pub limit: JointLimit,
    #[serde(default)]
    pub dynamics: Dynamics,
    #[serde(default)]
    pub mimic: Mimic,
    #[serde(default)]
    pub safety_controller: SafetyController,
}

#[derive(Debug, Deserialize, Default)]
pub struct Dynamics {
    damping: f64,
    friction: f64,
}

#[derive(Debug, Deserialize)]
pub struct Robot {
    pub name: String,

    #[serde(rename = "link", default)]
    pub links: Vec<Link>,

    #[serde(rename = "joint", default)]
    pub joints: Vec<Joint>,
}

pub fn deserialize(string: &str) -> Result<Robot, serde_xml_rs::Error> {
    serde_xml_rs::deserialize(string.as_bytes())
}

#[test]
fn it_works() {
    let s = r##"
        <robot name="robo">
            <link name="shoulder1">
                <inertial>
                    <origin xyz="0 0 0.5" rpy="0 0 0"/>
                    <mass value="1"/>
                    <inertia ixx="100"  ixy="0"  ixz="0" iyy="100" iyz="0" izz="100" />
                </inertial>
                <visual>
                    <origin xyz="0.1 0.2 0.3" rpy="-0.1 -0.2  -0.3" />
                    <geometry>
                        <box size="1 1 1" />
                    </geometry>
                    <material name="Cyan">
                        <color rgba="0 1.0 1.0 1.0"/>
                    </material>
                </visual>
                <collision>
                    <origin xyz="0 0 0" rpy="0 0 0"/>
                    <geometry>
                        <cylinder radius="1" length="0.5"/>
                    </geometry>
                </collision>
            </link>
            <link name="elbow1" />
            <link name="wrist1" />
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0 0.0 0.1" />
                <parent link="shoulder1" />
                <child link="elbow1" />
                <axis xyz="0 1 -1" />
                <limit lower="-1" upper="1.0" effort="0" velocity="1.0"/>
            </joint>
            <joint name="shoulder_pitch" type="revolute">
                <origin xyz="0.0, 0.0, 0.0" />
                <parent link="elbow1" />
                <child link="wrist1" />
                <axis xyz="0 1 0" />
                <limit lower="-2" upper="1.0" effort="0" velocity="1.0"/>
            </joint>
        </robot>
    "##;
    let robo = deserialize(s).unwrap();

    assert_eq!(robo.name, "robo");
    assert_eq!(robo.links.len(), 3);
    assert_eq!(robo.joints.len(), 2);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[0], 0.1);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[1], 0.2);
    assert_eq!(robo.links[0].visual.origin.xyz_as_array()[2], 0.3);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[0], -0.1);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[1], -0.2);
    assert_eq!(robo.links[0].visual.origin.rpy_as_array()[2], -0.3);

    assert_eq!(robo.joints[0].name, "shoulder_pitch");
    assert_eq!(robo.joints[0].axis.xyz, "0 1 -1");
    assert_eq!(robo.joints[0].axis.xyz_as_array()[0], 0.0f64);
    assert_eq!(robo.joints[0].axis.xyz_as_array()[1], 1.0f64);
    assert_eq!(robo.joints[0].axis.xyz_as_array()[2], -1.0f64);
    assert_eq!(robo.joints[0].origin.xyz, "0.0 0.0 0.1");
}
<|endoftext|>


<commit_before>// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Main interface for callers into cuckoo-miner. Provides functionality
//! to load a mining plugin, send it a Cuckoo Cycle POW problem, and
//! return any result solutions that may be found.
//!
//! #Example
//! ```
//!  let mut config = CuckooMinerConfig::new();
//!  config.plugin_full_path = caps[0].full_path.clone();
//!
//!  //set the number of threads for the miner to use
//!  config.num_threads=2;
//!
//!  //set the number of trimes, 0 lets the plugin decide
//!  config.num_trims=0;
//!
//!  //Build a new miner with this info, which will load
//!  //the associated plugin and
//!
//!  let mut miner = CuckooMiner::new(config).expect("");
//!
//!  //Keep a structure to hold the solution.. this will be
//!  //filled out by the plugin
//!  let mut solution = CuckooMinerSolution::new();
//!
//!  //Mine with given header and check for result
//!  let result = miner.mine(&test_header, &mut solution).unwrap();
//!
//!  if result == true {
//!      println!("Solution found: {}", solution);
//!  } else {
//!      println!("No Solution found");
//!  }
/// ```

use std::{fmt,cmp};
use std::collections::HashMap;

use cuckoo_sys::{call_cuckoo,
                 load_cuckoo_lib,
                 call_cuckoo_set_parameter};

use error::CuckooMinerError;

// Hardcoed assumption for now that the solution size will be 42 will be
// maintained, to avoid having to allocate memory within the called C functions

const CUCKOO_SOLUTION_SIZE:usize = 42;

/// A simple struct to hold a cuckoo miner solution. Currently,
/// it's assumed that a solution will be 42 bytes. The `solution_nonces`
/// member is statically allocated here, and will be filled in
/// by a plugin upon finding a solution.
///

pub struct CuckooMinerSolution {
    /// An array allocated in rust that will be filled
    /// by the called plugin upon successfully finding
    /// a solution

    pub solution_nonces:[u32; CUCKOO_SOLUTION_SIZE],
}

impl Default for CuckooMinerSolution {
	fn default() -> CuckooMinerSolution {
        CuckooMinerSolution {
		    solution_nonces: [0; CUCKOO_SOLUTION_SIZE],
        }
	}
}

impl CuckooMinerSolution{

    /// Creates a new cuckoo miner solution
    /// with nonces set to a u32 array of size
    /// 42 filled with zeroes.

    pub fn new()->CuckooMinerSolution{
        CuckooMinerSolution::default()
    }

    /// Sets the solution, mostly for testing
    pub fn set_solution(&mut self, nonces:[u32; CUCKOO_SOLUTION_SIZE]){
        self.solution_nonces = nonces;
    }
}

impl fmt::Display for CuckooMinerSolution {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,"{:?}", &self.solution_nonces[..])
    }
}

impl fmt::Debug for CuckooMinerSolution {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,"{:?}", &self.solution_nonces[..])
    }
}

impl cmp::PartialEq for CuckooMinerSolution {
    fn eq(&self, other: &CuckooMinerSolution) -> bool {
        for i in 0..CUCKOO_SOLUTION_SIZE {
            if self.solution_nonces[i]!=other.solution_nonces[i]{
                return false;
            }
        }
        return true;
    }
}

/// Structure containing the configuration values to pass into an
/// instance of a miner

pub struct CuckooMinerConfig {

    /// The full path to the plugin to load and use to find a solution
    /// to a POW problem. Defaults to empty string, so must be filled
    /// before use.
    pub plugin_full_path: String,

    /// A parameter list, which differs depending on which
    /// plugin is being called
    pub parameter_list: HashMap<String, u32>,

}

impl Default for CuckooMinerConfig {
	fn default() -> CuckooMinerConfig {
		CuckooMinerConfig{
            plugin_full_path: String::from(""),
            parameter_list: HashMap::new(),
		}
	}
}

impl CuckooMinerConfig{

    /// Returns a new instance of CuckooMinerConfig

    pub fn new()->CuckooMinerConfig{
        CuckooMinerConfig::default()
    }
}

/// An instance of a miner, which loads a cuckoo-miner plugin
/// and calls it's mine function according to the provided configuration
///

pub struct CuckooMiner{
    /// The internal Configuration object
    pub config: CuckooMinerConfig,
}

impl Default for CuckooMiner {
	fn default() -> CuckooMiner {
		CuckooMiner {
            config: CuckooMinerConfig::default(),
		}
	}
}

impl CuckooMiner {

    /// #Description
    ///
    /// Creates a new instance of a CuckooMiner with the given configuration.
    ///
    /// #Arguments
    ///
    /// * `config` an instance of [CuckooMinerConfig](struct.CuckooMinerConfig.html), that
    /// must be filled with the full path name of a valid mining plugin. It may also contain
    /// values in its `parameter_list` field, which will be automatically set in the plugin
    ///
    /// #Returns
    ///
    /// If successful, Ok() is returned and the specified plugin has been loaded internally.
    /// Otherwise a [CuckooMinerError](../../error/error/enum.CuckooMinerError.html)
    /// with specific detail is returned.
    ///

    pub fn new(config:CuckooMinerConfig)->Result<CuckooMiner, CuckooMinerError>{
        let mut return_val=CuckooMiner{
            config: config,
        };
        return_val.init()?;
        //set any parameters provided in the config
        for (name, value) in return_val.config.parameter_list.clone() {
           return_val.set_parameter(name.clone(), value.clone())?;
        }

        Ok(return_val)
    }

    /// Internal function to perform tha actual library loading

    fn init(&mut self) -> Result<(), CuckooMinerError> {
        load_cuckoo_lib(&self.config.plugin_full_path)
    }

    /// #Description
    ///
    /// Sets a parameter in the currently loaded plugin
    ///
    /// #Arguments
    ///
    /// * `name` The name of the parameter to set
    ///
    /// * `value` The value to set the parameter to
    ///
    /// #Returns
    ///
    /// If successful, Ok() is returned and the parameter has been set.
    /// Otherwise a [CuckooMinerError](../../error/error/enum.CuckooMinerError.html)
    /// with specific detail is returned.
    ///

    pub fn set_parameter(&mut self, name: String, value:u32) -> Result<(), CuckooMinerError>{
        let return_code = call_cuckoo_set_parameter(name.as_bytes(), value)?;
        if return_code != 0 {

            let reason = match return_code {
                1 => "Property doesn't exist for this plugin",
                2 => "Property outside allowed range",
                _ => "Unknown Error"
            };

            return Err(CuckooMinerError::ParameterError(String::from(
                format!("Error setting parameter: {} to {} - {}", name, value, reason)
                )));
        }
        Ok(())
    }

    /// #Description
    ///
    /// Call to the cuckoo_call function of the currently loaded plugin, which will perform
    /// a Cuckoo Cycle on the given seed, filling the first solution (a length 42 cycle)
    /// that is found in the provided [CuckooMinerSolution](struct.CuckooMinerSolution.html) structure.
    /// The implementation details are dependent on particular loaded plugin. Values provided
    /// to the loaded plugin are contained in the internal [CuckooMinerConfig](struct.CuckooMinerConfig.html)
    ///
    /// #Arguments
    ///
    /// * `header` (IN) A reference to a block of [u8] bytes to use for the seed to the
    ///    internal SIPHASH function which generates edge locations in the graph. In practice,
    ///    this is a SHA3 hash of a Grin blockheader, but from the plugin's perspective this
    ///    can be anything.
    ///
    /// * `solution` (OUT) An empty [CuckooMinerSolution](struct.CuckooMinerSolution.html).
    ///    If a solution is found, this structure will contain a list of solution nonces,
    ///    otherwise, it will remain untouched.
    ///
    /// #Returns
    ///
    /// * Ok(true) if a solution is found, with the 42 solution nonces contained within
    /// the provided [CuckooMinerSolution](struct.CuckooMinerSolution.html).
    /// * Ok(false) if no solution is found and `solution` remains untouched.
    /// * A [CuckooMinerError](../../error/error/enum.CuckooMinerError.html)
    /// if there is no plugin loaded, or if there is an error calling the function.
    ///

    pub fn mine(&self, header: &[u8], solution:&mut CuckooMinerSolution)
        -> Result<bool, CuckooMinerError> {
            match call_cuckoo(header,
                              &mut solution.solution_nonces) {
                Ok(result) => {
                    match result {
                        1 => {
                            debug!("Solution found.");
                            Ok(true)
                        }
                        0 => Ok(false),
                        _ => Err(CuckooMinerError::UnexpectedResultError(result))
                    }
                },
                Err(_) => Err(CuckooMinerError::PluginNotLoadedError(
                    String::from("Please call init to load a miner plug-in"))),
            }
    }
}<commit_msg>Making cuckoo miner configuration clonable<commit_after>// Copyright 2017 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Main interface for callers into cuckoo-miner. Provides functionality
//! to load a mining plugin, send it a Cuckoo Cycle POW problem, and
//! return any result solutions that may be found.
//!
//! #Example
//! ```
//!  let mut config = CuckooMinerConfig::new();
//!  config.plugin_full_path = caps[0].full_path.clone();
//!
//!  //set the number of threads for the miner to use
//!  config.num_threads=2;
//!
//!  //set the number of trimes, 0 lets the plugin decide
//!  config.num_trims=0;
//!
//!  //Build a new miner with this info, which will load
//!  //the associated plugin and
//!
//!  let mut miner = CuckooMiner::new(config).expect("");
//!
//!  //Keep a structure to hold the solution.. this will be
//!  //filled out by the plugin
//!  let mut solution = CuckooMinerSolution::new();
//!
//!  //Mine with given header and check for result
//!  let result = miner.mine(&test_header, &mut solution).unwrap();
//!
//!  if result == true {
//!      println!("Solution found: {}", solution);
//!  } else {
//!      println!("No Solution found");
//!  }
/// ```

use std::{fmt,cmp};
use std::collections::HashMap;

use cuckoo_sys::{call_cuckoo,
                 load_cuckoo_lib,
                 call_cuckoo_set_parameter};

use error::CuckooMinerError;

// Hardcoed assumption for now that the solution size will be 42 will be
// maintained, to avoid having to allocate memory within the called C functions

const CUCKOO_SOLUTION_SIZE:usize = 42;

/// A simple struct to hold a cuckoo miner solution. Currently,
/// it's assumed that a solution will be 42 bytes. The `solution_nonces`
/// member is statically allocated here, and will be filled in
/// by a plugin upon finding a solution.
///

pub struct CuckooMinerSolution {
    /// An array allocated in rust that will be filled
    /// by the called plugin upon successfully finding
    /// a solution

    pub solution_nonces:[u32; CUCKOO_SOLUTION_SIZE],
}

impl Default for CuckooMinerSolution {
	fn default() -> CuckooMinerSolution {
        CuckooMinerSolution {
		    solution_nonces: [0; CUCKOO_SOLUTION_SIZE],
        }
	}
}

impl CuckooMinerSolution{

    /// Creates a new cuckoo miner solution
    /// with nonces set to a u32 array of size
    /// 42 filled with zeroes.

    pub fn new()->CuckooMinerSolution{
        CuckooMinerSolution::default()
    }

    /// Sets the solution, mostly for testing
    pub fn set_solution(&mut self, nonces:[u32; CUCKOO_SOLUTION_SIZE]){
        self.solution_nonces = nonces;
    }
}

impl fmt::Display for CuckooMinerSolution {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,"{:?}", &self.solution_nonces[..])
    }
}

impl fmt::Debug for CuckooMinerSolution {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,"{:?}", &self.solution_nonces[..])
    }
}

impl cmp::PartialEq for CuckooMinerSolution {
    fn eq(&self, other: &CuckooMinerSolution) -> bool {
        for i in 0..CUCKOO_SOLUTION_SIZE {
            if self.solution_nonces[i]!=other.solution_nonces[i]{
                return false;
            }
        }
        return true;
    }
}

/// Structure containing the configuration values to pass into an
/// instance of a miner
#[derive(Debug, Clone)]
pub struct CuckooMinerConfig {

    /// The full path to the plugin to load and use to find a solution
    /// to a POW problem. Defaults to empty string, so must be filled
    /// before use.
    pub plugin_full_path: String,

    /// A parameter list, which differs depending on which
    /// plugin is being called
    pub parameter_list: HashMap<String, u32>,

}

impl Default for CuckooMinerConfig {
	fn default() -> CuckooMinerConfig {
		CuckooMinerConfig{
            plugin_full_path: String::from(""),
            parameter_list: HashMap::new(),
		}
	}
}

impl CuckooMinerConfig{

    /// Returns a new instance of CuckooMinerConfig

    pub fn new()->CuckooMinerConfig{
        CuckooMinerConfig::default()
    }
}

/// An instance of a miner, which loads a cuckoo-miner plugin
/// and calls it's mine function according to the provided configuration
///

pub struct CuckooMiner{
    /// The internal Configuration object
    pub config: CuckooMinerConfig,
}

impl Default for CuckooMiner {
	fn default() -> CuckooMiner {
		CuckooMiner {
            config: CuckooMinerConfig::default(),
		}
	}
}

impl CuckooMiner {

    /// #Description
    ///
    /// Creates a new instance of a CuckooMiner with the given configuration.
    ///
    /// #Arguments
    ///
    /// * `config` an instance of [CuckooMinerConfig](struct.CuckooMinerConfig.html), that
    /// must be filled with the full path name of a valid mining plugin. It may also contain
    /// values in its `parameter_list` field, which will be automatically set in the plugin
    ///
    /// #Returns
    ///
    /// If successful, Ok() is returned and the specified plugin has been loaded internally.
    /// Otherwise a [CuckooMinerError](../../error/error/enum.CuckooMinerError.html)
    /// with specific detail is returned.
    ///

    pub fn new(config:CuckooMinerConfig)->Result<CuckooMiner, CuckooMinerError>{
        let mut return_val=CuckooMiner{
            config: config,
        };
        return_val.init()?;
        //set any parameters provided in the config
        for (name, value) in return_val.config.parameter_list.clone() {
           return_val.set_parameter(name.clone(), value.clone())?;
        }

        Ok(return_val)
    }

    /// Internal function to perform tha actual library loading

    fn init(&mut self) -> Result<(), CuckooMinerError> {
        load_cuckoo_lib(&self.config.plugin_full_path)
    }

    /// #Description
    ///
    /// Sets a parameter in the currently loaded plugin
    ///
    /// #Arguments
    ///
    /// * `name` The name of the parameter to set
    ///
    /// * `value` The value to set the parameter to
    ///
    /// #Returns
    ///
    /// If successful, Ok() is returned and the parameter has been set.
    /// Otherwise a [CuckooMinerError](../../error/error/enum.CuckooMinerError.html)
    /// with specific detail is returned.
    ///

    pub fn set_parameter(&mut self, name: String, value:u32) -> Result<(), CuckooMinerError>{
        let return_code = call_cuckoo_set_parameter(name.as_bytes(), value)?;
        if return_code != 0 {

            let reason = match return_code {
                1 => "Property doesn't exist for this plugin",
                2 => "Property outside allowed range",
                _ => "Unknown Error"
            };

            return Err(CuckooMinerError::ParameterError(String::from(
                format!("Error setting parameter: {} to {} - {}", name, value, reason)
                )));
        }
        Ok(())
    }

    /// #Description
    ///
    /// Call to the cuckoo_call function of the currently loaded plugin, which will perform
    /// a Cuckoo Cycle on the given seed, filling the first solution (a length 42 cycle)
    /// that is found in the provided [CuckooMinerSolution](struct.CuckooMinerSolution.html) structure.
    /// The implementation details are dependent on particular loaded plugin. Values provided
    /// to the loaded plugin are contained in the internal [CuckooMinerConfig](struct.CuckooMinerConfig.html)
    ///
    /// #Arguments
    ///
    /// * `header` (IN) A reference to a block of [u8] bytes to use for the seed to the
    ///    internal SIPHASH function which generates edge locations in the graph. In practice,
    ///    this is a SHA3 hash of a Grin blockheader, but from the plugin's perspective this
    ///    can be anything.
    ///
    /// * `solution` (OUT) An empty [CuckooMinerSolution](struct.CuckooMinerSolution.html).
    ///    If a solution is found, this structure will contain a list of solution nonces,
    ///    otherwise, it will remain untouched.
    ///
    /// #Returns
    ///
    /// * Ok(true) if a solution is found, with the 42 solution nonces contained within
    /// the provided [CuckooMinerSolution](struct.CuckooMinerSolution.html).
    /// * Ok(false) if no solution is found and `solution` remains untouched.
    /// * A [CuckooMinerError](../../error/error/enum.CuckooMinerError.html)
    /// if there is no plugin loaded, or if there is an error calling the function.
    ///

    pub fn mine(&self, header: &[u8], solution:&mut CuckooMinerSolution)
        -> Result<bool, CuckooMinerError> {
            match call_cuckoo(header,
                              &mut solution.solution_nonces) {
                Ok(result) => {
                    match result {
                        1 => {
                            debug!("Solution found.");
                            Ok(true)
                        }
                        0 => Ok(false),
                        _ => Err(CuckooMinerError::UnexpectedResultError(result))
                    }
                },
                Err(_) => Err(CuckooMinerError::PluginNotLoadedError(
                    String::from("Please call init to load a miner plug-in"))),
            }
    }
}<|endoftext|>


<commit_before>use std::sync::Arc;
use std::fmt::Write;
use std::path::{PathBuf, Path};
use std::fs;

use salsa::Database;

use ra_db::SyntaxDatabase;
use ra_syntax::ast::{self, AstNode};
use test_utils::{project_dir, assert_eq_text, read_text};

use crate::{
    source_binder,
    mock::MockDatabase,
};

// These tests compare the inference results for all expressions in a file
// against snapshots of the current results. If you change something and these
// tests fail expectedly, you can update the comparison files by deleting them
// and running the tests again. Similarly, to add a new test, just write the
// test here in the same pattern and it will automatically write the snapshot.

#[test]
fn infer_basics() {
    check_inference(
        r#"
fn test(a: u32, b: isize, c: !, d: &str) {
    a;
    b;
    c;
    d;
    1usize;
    1isize;
    "test";
    1.0f32;
}"#,
        "basics.txt",
    );
}

#[test]
fn infer_let() {
    check_inference(
        r#"
fn test() {
    let a = 1isize;
    let b: usize = 1;
    let c = b;
}
}"#,
        "let.txt",
    );
}

#[test]
fn infer_paths() {
    check_inference(
        r#"
fn a() -> u32 { 1 }

mod b {
    fn c() -> u32 { 1 }
}

fn test() {
    a();
    b::c();
}
}"#,
        "paths.txt",
    );
}

#[test]
fn infer_struct() {
    check_inference(
        r#"
struct A {
    b: B,
    c: C,
}
struct B;
struct C(usize);

fn test() {
    let c = C(1);
    B;
    let a: A = A { b: B, c: C(1) };
    a.b;
    a.c;
}
"#,
        "struct.txt",
    );
}

#[test]
fn infer_refs_and_ptrs() {
    check_inference(
        r#"
fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
    a;
    *a;
    &a;
    &mut a;
    b;
    *b;
    &b;
    c;
    *c;
    d;
    *d;
}
"#,
        "refs_and_ptrs.txt",
    );
}

#[test]
fn infer_backwards() {
    check_inference(
        r#"
fn takes_u32(x: u32) {}

struct S { i32_field: i32 }

fn test() -> &mut &f64 {
    let a = unknown_function();
    takes_u32(a);
    let b = unknown_function();
    S { i32_field: b };
    let c = unknown_function();
    &mut &c
}
"#,
        "backwards.txt",
    );
}

#[test]
fn infer_self() {
    check_inference(
        r#"
struct S;

impl S {
    fn test(&self) {
        self;
    }
    fn test2(self: &Self) {
        self;
    }
}
"#,
        "self.txt",
    );
}

#[test]
fn infer_boolean_op() {
    check_inference(
        r#"
fn f(x: bool) -> i32 {
    0i32
}

fn test() {
    let x = a && b;
    let y = true || false;
    let z = x == y;
    let h = CONST_1 <= CONST_2;
    let c = f(z || y) + 5;
    let d = b;
    let e = 3i32 && "hello world";

    10 < 3
}
"#,
        "boolean_op.txt",
    );
}

fn infer(content: &str) -> String {
    let (db, _, file_id) = MockDatabase::with_single_file(content);
    let source_file = db.source_file(file_id);
    let mut acc = String::new();
    for fn_def in source_file
        .syntax()
        .descendants()
        .filter_map(ast::FnDef::cast)
    {
        let func = source_binder::function_from_source(&db, file_id, fn_def)
            .unwrap()
            .unwrap();
        let inference_result = func.infer(&db).unwrap();
        let body_syntax_mapping = func.body_syntax_mapping(&db).unwrap();
        let mut types = Vec::new();
        for (pat, ty) in inference_result.type_of_pat.iter() {
            let syntax_ptr = if let Some(sp) = body_syntax_mapping.pat_syntax(pat) {
                sp
            } else {
                continue;
            };
            types.push((syntax_ptr, ty));
        }
        for (expr, ty) in inference_result.type_of_expr.iter() {
            let syntax_ptr = if let Some(sp) = body_syntax_mapping.expr_syntax(expr) {
                sp
            } else {
                continue;
            };
            types.push((syntax_ptr, ty));
        }
        // sort ranges for consistency
        types.sort_by_key(|(ptr, _)| (ptr.range().start(), ptr.range().end()));
        for (syntax_ptr, ty) in &types {
            let node = syntax_ptr.resolve(&source_file);
            write!(
                acc,
                "{} '{}': {}\n",
                syntax_ptr.range(),
                ellipsize(node.text().to_string().replace("\n", " "), 15),
                ty
            )
            .unwrap();
        }
    }
    acc
}

fn check_inference(content: &str, data_file: impl AsRef<Path>) {
    let data_file_path = test_data_dir().join(data_file);
    let result = infer(content);

    if !data_file_path.exists() {
        println!("File with expected result doesn't exist, creating...\n");
        println!("{}\n{}", content, result);
        fs::write(&data_file_path, &result).unwrap();
        panic!("File {:?} with expected result was created", data_file_path);
    }

    let expected = read_text(&data_file_path);
    assert_eq_text!(&expected, &result);
}

fn ellipsize(mut text: String, max_len: usize) -> String {
    if text.len() <= max_len {
        return text;
    }
    let ellipsis = "...";
    let e_len = ellipsis.len();
    let mut prefix_len = (max_len - e_len) / 2;
    while !text.is_char_boundary(prefix_len) {
        prefix_len += 1;
    }
    let mut suffix_len = max_len - e_len - prefix_len;
    while !text.is_char_boundary(text.len() - suffix_len) {
        suffix_len += 1;
    }
    text.replace_range(prefix_len..text.len() - suffix_len, ellipsis);
    text
}

fn test_data_dir() -> PathBuf {
    project_dir().join("crates/ra_hir/src/ty/tests/data")
}

#[test]
fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
    let (mut db, pos) = MockDatabase::with_position(
        "
        //- /lib.rs
        fn foo() -> i32 {
            <|>1 + 1
        }
    ",
    );
    let func = source_binder::function_from_position(&db, pos)
        .unwrap()
        .unwrap();
    {
        let events = db.log_executed(|| {
            func.infer(&db).unwrap();
        });
        assert!(format!("{:?}", events).contains("infer"))
    }

    let new_text = "
        fn foo() -> i32 {
            1
            +
            1
        }
    "
    .to_string();

    db.query_mut(ra_db::FileTextQuery)
        .set(pos.file_id, Arc::new(new_text));

    {
        let events = db.log_executed(|| {
            func.infer(&db).unwrap();
        });
        assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events)
    }
}
<commit_msg>if let -> match<commit_after>use std::sync::Arc;
use std::fmt::Write;
use std::path::{PathBuf, Path};
use std::fs;

use salsa::Database;

use ra_db::SyntaxDatabase;
use ra_syntax::ast::{self, AstNode};
use test_utils::{project_dir, assert_eq_text, read_text};

use crate::{
    source_binder,
    mock::MockDatabase,
};

// These tests compare the inference results for all expressions in a file
// against snapshots of the current results. If you change something and these
// tests fail expectedly, you can update the comparison files by deleting them
// and running the tests again. Similarly, to add a new test, just write the
// test here in the same pattern and it will automatically write the snapshot.

#[test]
fn infer_basics() {
    check_inference(
        r#"
fn test(a: u32, b: isize, c: !, d: &str) {
    a;
    b;
    c;
    d;
    1usize;
    1isize;
    "test";
    1.0f32;
}"#,
        "basics.txt",
    );
}

#[test]
fn infer_let() {
    check_inference(
        r#"
fn test() {
    let a = 1isize;
    let b: usize = 1;
    let c = b;
}
}"#,
        "let.txt",
    );
}

#[test]
fn infer_paths() {
    check_inference(
        r#"
fn a() -> u32 { 1 }

mod b {
    fn c() -> u32 { 1 }
}

fn test() {
    a();
    b::c();
}
}"#,
        "paths.txt",
    );
}

#[test]
fn infer_struct() {
    check_inference(
        r#"
struct A {
    b: B,
    c: C,
}
struct B;
struct C(usize);

fn test() {
    let c = C(1);
    B;
    let a: A = A { b: B, c: C(1) };
    a.b;
    a.c;
}
"#,
        "struct.txt",
    );
}

#[test]
fn infer_refs_and_ptrs() {
    check_inference(
        r#"
fn test(a: &u32, b: &mut u32, c: *const u32, d: *mut u32) {
    a;
    *a;
    &a;
    &mut a;
    b;
    *b;
    &b;
    c;
    *c;
    d;
    *d;
}
"#,
        "refs_and_ptrs.txt",
    );
}

#[test]
fn infer_backwards() {
    check_inference(
        r#"
fn takes_u32(x: u32) {}

struct S { i32_field: i32 }

fn test() -> &mut &f64 {
    let a = unknown_function();
    takes_u32(a);
    let b = unknown_function();
    S { i32_field: b };
    let c = unknown_function();
    &mut &c
}
"#,
        "backwards.txt",
    );
}

#[test]
fn infer_self() {
    check_inference(
        r#"
struct S;

impl S {
    fn test(&self) {
        self;
    }
    fn test2(self: &Self) {
        self;
    }
}
"#,
        "self.txt",
    );
}

#[test]
fn infer_boolean_op() {
    check_inference(
        r#"
fn f(x: bool) -> i32 {
    0i32
}

fn test() {
    let x = a && b;
    let y = true || false;
    let z = x == y;
    let h = CONST_1 <= CONST_2;
    let c = f(z || y) + 5;
    let d = b;
    let e = 3i32 && "hello world";

    10 < 3
}
"#,
        "boolean_op.txt",
    );
}

fn infer(content: &str) -> String {
    let (db, _, file_id) = MockDatabase::with_single_file(content);
    let source_file = db.source_file(file_id);
    let mut acc = String::new();
    for fn_def in source_file
        .syntax()
        .descendants()
        .filter_map(ast::FnDef::cast)
    {
        let func = source_binder::function_from_source(&db, file_id, fn_def)
            .unwrap()
            .unwrap();
        let inference_result = func.infer(&db).unwrap();
        let body_syntax_mapping = func.body_syntax_mapping(&db).unwrap();
        let mut types = Vec::new();
        for (pat, ty) in inference_result.type_of_pat.iter() {
            let syntax_ptr = match body_syntax_mapping.pat_syntax(pat) {
                Some(sp) => sp,
                None => continue,
            };
            types.push((syntax_ptr, ty));
        }
        for (expr, ty) in inference_result.type_of_expr.iter() {
            let syntax_ptr = match body_syntax_mapping.expr_syntax(expr) {
                Some(sp) => sp,
                None => continue,
            };
            types.push((syntax_ptr, ty));
        }
        // sort ranges for consistency
        types.sort_by_key(|(ptr, _)| (ptr.range().start(), ptr.range().end()));
        for (syntax_ptr, ty) in &types {
            let node = syntax_ptr.resolve(&source_file);
            write!(
                acc,
                "{} '{}': {}\n",
                syntax_ptr.range(),
                ellipsize(node.text().to_string().replace("\n", " "), 15),
                ty
            )
            .unwrap();
        }
    }
    acc
}

fn check_inference(content: &str, data_file: impl AsRef<Path>) {
    let data_file_path = test_data_dir().join(data_file);
    let result = infer(content);

    if !data_file_path.exists() {
        println!("File with expected result doesn't exist, creating...\n");
        println!("{}\n{}", content, result);
        fs::write(&data_file_path, &result).unwrap();
        panic!("File {:?} with expected result was created", data_file_path);
    }

    let expected = read_text(&data_file_path);
    assert_eq_text!(&expected, &result);
}

fn ellipsize(mut text: String, max_len: usize) -> String {
    if text.len() <= max_len {
        return text;
    }
    let ellipsis = "...";
    let e_len = ellipsis.len();
    let mut prefix_len = (max_len - e_len) / 2;
    while !text.is_char_boundary(prefix_len) {
        prefix_len += 1;
    }
    let mut suffix_len = max_len - e_len - prefix_len;
    while !text.is_char_boundary(text.len() - suffix_len) {
        suffix_len += 1;
    }
    text.replace_range(prefix_len..text.len() - suffix_len, ellipsis);
    text
}

fn test_data_dir() -> PathBuf {
    project_dir().join("crates/ra_hir/src/ty/tests/data")
}

#[test]
fn typing_whitespace_inside_a_function_should_not_invalidate_types() {
    let (mut db, pos) = MockDatabase::with_position(
        "
        //- /lib.rs
        fn foo() -> i32 {
            <|>1 + 1
        }
    ",
    );
    let func = source_binder::function_from_position(&db, pos)
        .unwrap()
        .unwrap();
    {
        let events = db.log_executed(|| {
            func.infer(&db).unwrap();
        });
        assert!(format!("{:?}", events).contains("infer"))
    }

    let new_text = "
        fn foo() -> i32 {
            1
            +
            1
        }
    "
    .to_string();

    db.query_mut(ra_db::FileTextQuery)
        .set(pos.file_id, Arc::new(new_text));

    {
        let events = db.log_executed(|| {
            func.infer(&db).unwrap();
        });
        assert!(!format!("{:?}", events).contains("infer"), "{:#?}", events)
    }
}
<|endoftext|>


<commit_before>//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
mod lower_use;

use std::{iter, sync::Arc};

use either::Either;
use hir_expand::{
    hygiene::Hygiene,
    name::{self, AsName, Name},
};
use ra_db::CrateId;
use ra_syntax::{
    ast::{self, TypeAscriptionOwner},
    AstNode,
};

use crate::{type_ref::TypeRef, InFile};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path {
    pub kind: PathKind,
    pub segments: Vec<PathSegment>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PathSegment {
    pub name: Name,
    pub args_and_bindings: Option<Arc<GenericArgs>>,
}

/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
/// can (in the future) also include bindings of associated types, like in
/// `Iterator<Item = Foo>`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct GenericArgs {
    pub args: Vec<GenericArg>,
    /// This specifies whether the args contain a Self type as the first
    /// element. This is the case for path segments like `<T as Trait>`, where
    /// `T` is actually a type parameter for the path `Trait` specifying the
    /// Self type. Otherwise, when we have a path `Trait<X, Y>`, the Self type
    /// is left out.
    pub has_self_type: bool,
    /// Associated type bindings like in `Iterator<Item = T>`.
    pub bindings: Vec<(Name, TypeRef)>,
}

/// A single generic argument.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum GenericArg {
    Type(TypeRef),
    // or lifetime...
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum PathKind {
    Plain,
    Self_,
    Super,
    Crate,
    // Absolute path
    Abs,
    // Type based path like `<T>::foo`
    Type(Box<TypeRef>),
    // `$crate` from macro expansion
    DollarCrate(CrateId),
}

impl Path {
    /// Calls `cb` with all paths, represented by this use item.
    pub(crate) fn expand_use_item(
        item_src: InFile<ast::UseItem>,
        hygiene: &Hygiene,
        mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
    ) {
        if let Some(tree) = item_src.value.use_tree() {
            lower_use::lower_use_tree(None, tree, hygiene, &mut cb);
        }
    }

    pub(crate) fn from_simple_segments(
        kind: PathKind,
        segments: impl IntoIterator<Item = Name>,
    ) -> Path {
        Path {
            kind,
            segments: segments
                .into_iter()
                .map(|name| PathSegment { name, args_and_bindings: None })
                .collect(),
        }
    }

    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// DEPRECATED: It does not handle `$crate` from macro call.
    pub fn from_ast(path: ast::Path) -> Option<Path> {
        Path::from_src(path, &Hygiene::new_unhygienic())
    }

    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// It correctly handles `$crate` based path from macro call.
    pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
        let mut kind = PathKind::Plain;
        let mut segments = Vec::new();
        loop {
            let segment = path.segment()?;

            if segment.has_colon_colon() {
                kind = PathKind::Abs;
            }

            match segment.kind()? {
                ast::PathSegmentKind::Name(name_ref) => {
                    // FIXME: this should just return name
                    match hygiene.name_ref_to_name(name_ref) {
                        Either::Left(name) => {
                            let args = segment
                                .type_arg_list()
                                .and_then(GenericArgs::from_ast)
                                .or_else(|| {
                                    GenericArgs::from_fn_like_path_ast(
                                        segment.param_list(),
                                        segment.ret_type(),
                                    )
                                })
                                .map(Arc::new);
                            let segment = PathSegment { name, args_and_bindings: args };
                            segments.push(segment);
                        }
                        Either::Right(crate_id) => {
                            kind = PathKind::DollarCrate(crate_id);
                            break;
                        }
                    }
                }
                ast::PathSegmentKind::Type { type_ref, trait_ref } => {
                    assert!(path.qualifier().is_none()); // this can only occur at the first segment

                    let self_type = TypeRef::from_ast(type_ref?);

                    match trait_ref {
                        // <T>::foo
                        None => {
                            kind = PathKind::Type(Box::new(self_type));
                        }
                        // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
                        Some(trait_ref) => {
                            let path = Path::from_src(trait_ref.path()?, hygiene)?;
                            kind = path.kind;
                            let mut prefix_segments = path.segments;
                            prefix_segments.reverse();
                            segments.extend(prefix_segments);
                            // Insert the type reference (T in the above example) as Self parameter for the trait
                            let mut last_segment = segments.last_mut()?;
                            if last_segment.args_and_bindings.is_none() {
                                last_segment.args_and_bindings =
                                    Some(Arc::new(GenericArgs::empty()));
                            };
                            let args = last_segment.args_and_bindings.as_mut().unwrap();
                            let mut args_inner = Arc::make_mut(args);
                            args_inner.has_self_type = true;
                            args_inner.args.insert(0, GenericArg::Type(self_type));
                        }
                    }
                }
                ast::PathSegmentKind::CrateKw => {
                    kind = PathKind::Crate;
                    break;
                }
                ast::PathSegmentKind::SelfKw => {
                    kind = PathKind::Self_;
                    break;
                }
                ast::PathSegmentKind::SuperKw => {
                    kind = PathKind::Super;
                    break;
                }
            }
            path = match qualifier(&path) {
                Some(it) => it,
                None => break,
            };
        }
        segments.reverse();
        return Some(Path { kind, segments });

        fn qualifier(path: &ast::Path) -> Option<ast::Path> {
            if let Some(q) = path.qualifier() {
                return Some(q);
            }
            // FIXME: this bottom up traversal is not too precise.
            // Should we handle do a top-down analysis, recording results?
            let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
            let use_tree = use_tree_list.parent_use_tree();
            use_tree.path()
        }
    }

    /// Converts an `ast::NameRef` into a single-identifier `Path`.
    pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
        name_ref.as_name().into()
    }

    /// Converts an `tt::Ident` into a single-identifier `Path`.
    pub(crate) fn from_tt_ident(ident: &tt::Ident) -> Path {
        ident.as_name().into()
    }

    /// `true` is this path is a single identifier, like `foo`
    pub fn is_ident(&self) -> bool {
        self.kind == PathKind::Plain && self.segments.len() == 1
    }

    /// `true` if this path is just a standalone `self`
    pub fn is_self(&self) -> bool {
        self.kind == PathKind::Self_ && self.segments.is_empty()
    }

    /// If this path is a single identifier, like `foo`, return its name.
    pub fn as_ident(&self) -> Option<&Name> {
        if self.kind != PathKind::Plain || self.segments.len() > 1 {
            return None;
        }
        self.segments.first().map(|s| &s.name)
    }

    pub fn expand_macro_expr(&self) -> Option<Name> {
        self.as_ident().and_then(|name| Some(name.clone()))
    }

    pub fn is_type_relative(&self) -> bool {
        match self.kind {
            PathKind::Type(_) => true,
            _ => false,
        }
    }
}

impl GenericArgs {
    pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> {
        let mut args = Vec::new();
        for type_arg in node.type_args() {
            let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());
            args.push(GenericArg::Type(type_ref));
        }
        // lifetimes ignored for now
        let mut bindings = Vec::new();
        for assoc_type_arg in node.assoc_type_args() {
            if let Some(name_ref) = assoc_type_arg.name_ref() {
                let name = name_ref.as_name();
                let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref());
                bindings.push((name, type_ref));
            }
        }
        if args.is_empty() && bindings.is_empty() {
            None
        } else {
            Some(GenericArgs { args, has_self_type: false, bindings })
        }
    }

    /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
    /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
    pub(crate) fn from_fn_like_path_ast(
        params: Option<ast::ParamList>,
        ret_type: Option<ast::RetType>,
    ) -> Option<GenericArgs> {
        let mut args = Vec::new();
        let mut bindings = Vec::new();
        if let Some(params) = params {
            let mut param_types = Vec::new();
            for param in params.params() {
                let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
                param_types.push(type_ref);
            }
            let arg = GenericArg::Type(TypeRef::Tuple(param_types));
            args.push(arg);
        }
        if let Some(ret_type) = ret_type {
            let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
            bindings.push((name::OUTPUT_TYPE, type_ref))
        }
        if args.is_empty() && bindings.is_empty() {
            None
        } else {
            Some(GenericArgs { args, has_self_type: false, bindings })
        }
    }

    pub(crate) fn empty() -> GenericArgs {
        GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() }
    }
}

impl From<Name> for Path {
    fn from(name: Name) -> Path {
        Path::from_simple_segments(PathKind::Plain, iter::once(name))
    }
}

pub mod known {
    use hir_expand::name;

    use super::{Path, PathKind};

    pub fn std_iter_into_iterator() -> Path {
        Path::from_simple_segments(
            PathKind::Abs,
            vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE],
        )
    }

    pub fn std_ops_try() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE])
    }

    pub fn std_ops_range() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TYPE])
    }

    pub fn std_ops_range_from() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FROM_TYPE])
    }

    pub fn std_ops_range_full() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FULL_TYPE])
    }

    pub fn std_ops_range_inclusive() -> Path {
        Path::from_simple_segments(
            PathKind::Abs,
            vec![name::STD, name::OPS, name::RANGE_INCLUSIVE_TYPE],
        )
    }

    pub fn std_ops_range_to() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TO_TYPE])
    }

    pub fn std_ops_range_to_inclusive() -> Path {
        Path::from_simple_segments(
            PathKind::Abs,
            vec![name::STD, name::OPS, name::RANGE_TO_INCLUSIVE_TYPE],
        )
    }

    pub fn std_result_result() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE])
    }

    pub fn std_future_future() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE])
    }

    pub fn std_boxed_box() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE])
    }
}
<commit_msg>Correct obsolete comment<commit_after>//! A desugared representation of paths like `crate::foo` or `<Type as Trait>::bar`.
mod lower_use;

use std::{iter, sync::Arc};

use either::Either;
use hir_expand::{
    hygiene::Hygiene,
    name::{self, AsName, Name},
};
use ra_db::CrateId;
use ra_syntax::{
    ast::{self, TypeAscriptionOwner},
    AstNode,
};

use crate::{type_ref::TypeRef, InFile};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Path {
    pub kind: PathKind,
    pub segments: Vec<PathSegment>,
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct PathSegment {
    pub name: Name,
    pub args_and_bindings: Option<Arc<GenericArgs>>,
}

/// Generic arguments to a path segment (e.g. the `i32` in `Option<i32>`). This
/// also includes bindings of associated types, like in `Iterator<Item = Foo>`.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct GenericArgs {
    pub args: Vec<GenericArg>,
    /// This specifies whether the args contain a Self type as the first
    /// element. This is the case for path segments like `<T as Trait>`, where
    /// `T` is actually a type parameter for the path `Trait` specifying the
    /// Self type. Otherwise, when we have a path `Trait<X, Y>`, the Self type
    /// is left out.
    pub has_self_type: bool,
    /// Associated type bindings like in `Iterator<Item = T>`.
    pub bindings: Vec<(Name, TypeRef)>,
}

/// A single generic argument.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum GenericArg {
    Type(TypeRef),
    // or lifetime...
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum PathKind {
    Plain,
    Self_,
    Super,
    Crate,
    // Absolute path
    Abs,
    // Type based path like `<T>::foo`
    Type(Box<TypeRef>),
    // `$crate` from macro expansion
    DollarCrate(CrateId),
}

impl Path {
    /// Calls `cb` with all paths, represented by this use item.
    pub(crate) fn expand_use_item(
        item_src: InFile<ast::UseItem>,
        hygiene: &Hygiene,
        mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
    ) {
        if let Some(tree) = item_src.value.use_tree() {
            lower_use::lower_use_tree(None, tree, hygiene, &mut cb);
        }
    }

    pub(crate) fn from_simple_segments(
        kind: PathKind,
        segments: impl IntoIterator<Item = Name>,
    ) -> Path {
        Path {
            kind,
            segments: segments
                .into_iter()
                .map(|name| PathSegment { name, args_and_bindings: None })
                .collect(),
        }
    }

    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// DEPRECATED: It does not handle `$crate` from macro call.
    pub fn from_ast(path: ast::Path) -> Option<Path> {
        Path::from_src(path, &Hygiene::new_unhygienic())
    }

    /// Converts an `ast::Path` to `Path`. Works with use trees.
    /// It correctly handles `$crate` based path from macro call.
    pub fn from_src(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> {
        let mut kind = PathKind::Plain;
        let mut segments = Vec::new();
        loop {
            let segment = path.segment()?;

            if segment.has_colon_colon() {
                kind = PathKind::Abs;
            }

            match segment.kind()? {
                ast::PathSegmentKind::Name(name_ref) => {
                    // FIXME: this should just return name
                    match hygiene.name_ref_to_name(name_ref) {
                        Either::Left(name) => {
                            let args = segment
                                .type_arg_list()
                                .and_then(GenericArgs::from_ast)
                                .or_else(|| {
                                    GenericArgs::from_fn_like_path_ast(
                                        segment.param_list(),
                                        segment.ret_type(),
                                    )
                                })
                                .map(Arc::new);
                            let segment = PathSegment { name, args_and_bindings: args };
                            segments.push(segment);
                        }
                        Either::Right(crate_id) => {
                            kind = PathKind::DollarCrate(crate_id);
                            break;
                        }
                    }
                }
                ast::PathSegmentKind::Type { type_ref, trait_ref } => {
                    assert!(path.qualifier().is_none()); // this can only occur at the first segment

                    let self_type = TypeRef::from_ast(type_ref?);

                    match trait_ref {
                        // <T>::foo
                        None => {
                            kind = PathKind::Type(Box::new(self_type));
                        }
                        // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo
                        Some(trait_ref) => {
                            let path = Path::from_src(trait_ref.path()?, hygiene)?;
                            kind = path.kind;
                            let mut prefix_segments = path.segments;
                            prefix_segments.reverse();
                            segments.extend(prefix_segments);
                            // Insert the type reference (T in the above example) as Self parameter for the trait
                            let mut last_segment = segments.last_mut()?;
                            if last_segment.args_and_bindings.is_none() {
                                last_segment.args_and_bindings =
                                    Some(Arc::new(GenericArgs::empty()));
                            };
                            let args = last_segment.args_and_bindings.as_mut().unwrap();
                            let mut args_inner = Arc::make_mut(args);
                            args_inner.has_self_type = true;
                            args_inner.args.insert(0, GenericArg::Type(self_type));
                        }
                    }
                }
                ast::PathSegmentKind::CrateKw => {
                    kind = PathKind::Crate;
                    break;
                }
                ast::PathSegmentKind::SelfKw => {
                    kind = PathKind::Self_;
                    break;
                }
                ast::PathSegmentKind::SuperKw => {
                    kind = PathKind::Super;
                    break;
                }
            }
            path = match qualifier(&path) {
                Some(it) => it,
                None => break,
            };
        }
        segments.reverse();
        return Some(Path { kind, segments });

        fn qualifier(path: &ast::Path) -> Option<ast::Path> {
            if let Some(q) = path.qualifier() {
                return Some(q);
            }
            // FIXME: this bottom up traversal is not too precise.
            // Should we handle do a top-down analysis, recording results?
            let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
            let use_tree = use_tree_list.parent_use_tree();
            use_tree.path()
        }
    }

    /// Converts an `ast::NameRef` into a single-identifier `Path`.
    pub(crate) fn from_name_ref(name_ref: &ast::NameRef) -> Path {
        name_ref.as_name().into()
    }

    /// Converts an `tt::Ident` into a single-identifier `Path`.
    pub(crate) fn from_tt_ident(ident: &tt::Ident) -> Path {
        ident.as_name().into()
    }

    /// `true` is this path is a single identifier, like `foo`
    pub fn is_ident(&self) -> bool {
        self.kind == PathKind::Plain && self.segments.len() == 1
    }

    /// `true` if this path is just a standalone `self`
    pub fn is_self(&self) -> bool {
        self.kind == PathKind::Self_ && self.segments.is_empty()
    }

    /// If this path is a single identifier, like `foo`, return its name.
    pub fn as_ident(&self) -> Option<&Name> {
        if self.kind != PathKind::Plain || self.segments.len() > 1 {
            return None;
        }
        self.segments.first().map(|s| &s.name)
    }

    pub fn expand_macro_expr(&self) -> Option<Name> {
        self.as_ident().and_then(|name| Some(name.clone()))
    }

    pub fn is_type_relative(&self) -> bool {
        match self.kind {
            PathKind::Type(_) => true,
            _ => false,
        }
    }
}

impl GenericArgs {
    pub(crate) fn from_ast(node: ast::TypeArgList) -> Option<GenericArgs> {
        let mut args = Vec::new();
        for type_arg in node.type_args() {
            let type_ref = TypeRef::from_ast_opt(type_arg.type_ref());
            args.push(GenericArg::Type(type_ref));
        }
        // lifetimes ignored for now
        let mut bindings = Vec::new();
        for assoc_type_arg in node.assoc_type_args() {
            if let Some(name_ref) = assoc_type_arg.name_ref() {
                let name = name_ref.as_name();
                let type_ref = TypeRef::from_ast_opt(assoc_type_arg.type_ref());
                bindings.push((name, type_ref));
            }
        }
        if args.is_empty() && bindings.is_empty() {
            None
        } else {
            Some(GenericArgs { args, has_self_type: false, bindings })
        }
    }

    /// Collect `GenericArgs` from the parts of a fn-like path, i.e. `Fn(X, Y)
    /// -> Z` (which desugars to `Fn<(X, Y), Output=Z>`).
    pub(crate) fn from_fn_like_path_ast(
        params: Option<ast::ParamList>,
        ret_type: Option<ast::RetType>,
    ) -> Option<GenericArgs> {
        let mut args = Vec::new();
        let mut bindings = Vec::new();
        if let Some(params) = params {
            let mut param_types = Vec::new();
            for param in params.params() {
                let type_ref = TypeRef::from_ast_opt(param.ascribed_type());
                param_types.push(type_ref);
            }
            let arg = GenericArg::Type(TypeRef::Tuple(param_types));
            args.push(arg);
        }
        if let Some(ret_type) = ret_type {
            let type_ref = TypeRef::from_ast_opt(ret_type.type_ref());
            bindings.push((name::OUTPUT_TYPE, type_ref))
        }
        if args.is_empty() && bindings.is_empty() {
            None
        } else {
            Some(GenericArgs { args, has_self_type: false, bindings })
        }
    }

    pub(crate) fn empty() -> GenericArgs {
        GenericArgs { args: Vec::new(), has_self_type: false, bindings: Vec::new() }
    }
}

impl From<Name> for Path {
    fn from(name: Name) -> Path {
        Path::from_simple_segments(PathKind::Plain, iter::once(name))
    }
}

pub mod known {
    use hir_expand::name;

    use super::{Path, PathKind};

    pub fn std_iter_into_iterator() -> Path {
        Path::from_simple_segments(
            PathKind::Abs,
            vec![name::STD, name::ITER, name::INTO_ITERATOR_TYPE],
        )
    }

    pub fn std_ops_try() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::TRY_TYPE])
    }

    pub fn std_ops_range() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TYPE])
    }

    pub fn std_ops_range_from() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FROM_TYPE])
    }

    pub fn std_ops_range_full() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_FULL_TYPE])
    }

    pub fn std_ops_range_inclusive() -> Path {
        Path::from_simple_segments(
            PathKind::Abs,
            vec![name::STD, name::OPS, name::RANGE_INCLUSIVE_TYPE],
        )
    }

    pub fn std_ops_range_to() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::OPS, name::RANGE_TO_TYPE])
    }

    pub fn std_ops_range_to_inclusive() -> Path {
        Path::from_simple_segments(
            PathKind::Abs,
            vec![name::STD, name::OPS, name::RANGE_TO_INCLUSIVE_TYPE],
        )
    }

    pub fn std_result_result() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::RESULT, name::RESULT_TYPE])
    }

    pub fn std_future_future() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::FUTURE, name::FUTURE_TYPE])
    }

    pub fn std_boxed_box() -> Path {
        Path::from_simple_segments(PathKind::Abs, vec![name::STD, name::BOXED, name::BOX_TYPE])
    }
}
<|endoftext|>


<commit_before>extern crate diesel;

use std::error::Error;
use diesel::prelude::*;
use schema::images;
use schema::tags;
use schema::images_tags;
use schema::images::dsl::*;
use super::super::models::{ImagesTag, NewImagesTag, Tag, Image, NewImage};
use super::super::db_manager;

pub fn create(new_image: &NewImage) -> Result<Image, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(diesel::insert(new_image)
                          .into(images::table)
                          .get_result(conn));
    Ok(result)
}

pub fn find(image: &Image) -> Result<Image, Box<Error>> {
    use schema::images::dsl::*;
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(images.find(image.id).first(conn));
    Ok(result)
}

pub fn find_range(size: i64, offset: i64) -> Result<Vec<Image>, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(images.limit(size).offset(offset).load(conn));
    Ok(result)
}

pub fn update(image: &Image) -> Result<Image, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(diesel::update(images.find(image.id))
                          .set((title.eq(image.title.clone()),
                                description.eq(image.description.clone()),
                                license.eq(image.license.clone()),
                                side_car_file.eq(image.side_car_file.clone()),
                                raw_image_id.eq(image.raw_image_id.clone())))
                          .get_result(conn));
    Ok(result)
}

pub fn add_tag_to_image(image: &Image, tag: &Tag) -> Result<ImagesTag, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let new_image_tag = NewImagesTag {
        image_id: image.id,
        tag_id: tag.id,
    };
    let result = try!(diesel::insert(&new_image_tag)
                          .into(images_tags::table)
                          .get_result(conn));
    Ok(result)
}

pub fn get_tags_of_image(image: &Image) -> Result<Vec<ImagesTag>, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let image_tags = try!(ImagesTag::belonging_to(image).load(conn));

    Ok(image_tags)
}
<commit_msg>Add get tags for images and get collections of image<commit_after>use std::error::Error;
use diesel::prelude::*;
use schema::{images, tags, images_tags, images_collections, collections};
use schema::images::dsl::*;
use super::super::models::{ImagesTag, NewImagesTag, Tag, Image, NewImage, Collection,
                           ImagesCollection};
use super::super::db_manager;
use super::super::diesel;

pub fn create(new_image: &NewImage) -> Result<Image, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(diesel::insert(new_image)
                          .into(images::table)
                          .get_result(conn));
    Ok(result)
}

pub fn find(image: &Image) -> Result<Image, Box<Error>> {
    use schema::images::dsl::*;
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(images.find(image.id).first(conn));
    Ok(result)
}

pub fn find_range(size: i64, offset: i64) -> Result<Vec<Image>, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(images.limit(size).offset(offset).load(conn));
    Ok(result)
}

pub fn update(image: &Image) -> Result<Image, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let result = try!(diesel::update(images.find(image.id))
                          .set((title.eq(image.title.clone()),
                                description.eq(image.description.clone()),
                                license.eq(image.license.clone()),
                                side_car_file.eq(image.side_car_file.clone()),
                                raw_image_id.eq(image.raw_image_id.clone())))
                          .get_result(conn));
    Ok(result)
}

pub fn add_tag_to_image(image: &Image, tag: &Tag) -> Result<ImagesTag, Box<Error>> {
    let ref conn = *try!(db_manager::POOL.get());
    let new_image_tag = NewImagesTag {
        image_id: image.id,
        tag_id: tag.id,
    };
    let result = try!(diesel::insert(&new_image_tag)
                          .into(images_tags::table)
                          .get_result(conn));
    Ok(result)
}

pub fn get_tags_of_image(image: &Image) -> Result<Vec<Tag>, Box<Error>> {
    use diesel::pg::expression::dsl::any;
    let ref conn = *try!(db_manager::POOL.get());
    let image_tag_ids = ImagesTag::belonging_to(image).select(images_tags::tag_id);
    Ok(try!(tags::table
                .filter(tags::id.eq(any(image_tag_ids)))
                .load::<Tag>(conn)))
}

pub fn get_collections_of_image(image: &Image) -> Result<Vec<Collection>, Box<Error>> {
    use diesel::pg::expression::dsl::any;
    let ref conn = *try!(db_manager::POOL.get());
    let image_collection_ids = ImagesCollection::belonging_to(image)
        .select(images_collections::collection_id);
    Ok(try!(collections::table
                .filter(collections::id.eq(any(image_collection_ids)))
                .load::<Collection>(conn)))
}
<|endoftext|>