<commit_before>extern crate regex;

use std::io::{self, BufRead};
use std::collections::HashMap;
use std::fmt;

pub struct Entry {
    num: i32,
    index_x: i32,
    index_y: i32,
    width: i32,
    height: i32
}

impl fmt::Display for Entry {
    fn fmt(&self,fmt:  &mut fmt::Formatter) -> fmt::Result {
        let str_num = "num=".to_string()+&self.num.to_string();
        let str_index_x = "index_x=".to_string() + &self.index_x.to_string();
        let str_index_y = "index_y=".to_string() + &self.index_y.to_string();
        let str_w = "w=".to_string() + &self.width.to_string();
        let str_h = "h=".to_string() + &self.height.to_string();
        let parsed = str_num + " " + str_index_x.as_str() + " " +  str_index_y.as_str() + " " +  str_w.as_str() + " " +  str_h.as_str();
        fmt.write_str(parsed.as_str())?;
        Ok(())
    }
}

fn code1() {
    let stdin = io::stdin();

    let mut lines = stdin.lock().lines().fuse();
    let input = match lines.next()  {
        Some(Ok(a))  => a,
        _ => panic!("Couldn t read input.")
    };

    let info = input.trim();
    let splitted = info.split(",");
    let iter = splitted.map(|a| a.to_string().parse().unwrap_or(0));

    let mut result  = 0;
    for num in iter {
        result += num;
    }
    println!("{:?}", result);
}

fn code2() {
    let mut threes = 0;
    let mut two = 0;
    let mut vec: Vec<String> = Vec::new();

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let str_line = line.unwrap().trim().to_string();
        if str_line == "0" {
            println!("exit!");
            break;
        }
        vec.push(str_line);
    }

    let mut saved_characters: HashMap<String, i32> = HashMap::new();
    for info in &vec {
        for charact in info.to_string().chars()  {
            let value = saved_characters.entry(charact.to_string()).or_insert(0);
            *value += 1;
        }

        let temp_threes = saved_characters.values().filter(|val| **val == 3).count();
        let temp_two = saved_characters.values().filter(|val| **val == 2).count();

        threes += temp_threes;
        two += temp_two;
    }
    println!("------------------------------");
    println!("threes: {}", threes);
    println!("twos: {}", two);
}

static DEFAULT: i32 = 0;
static MULTIPLE:  i32 = -1;

fn paint_matrix(matrix: &mut [[i32; 10]; 10]) {
    for (i, row) in  matrix.iter_mut().enumerate() {
        for (y, col) in row.iter_mut().enumerate() {
             if *col == 0 as i32 {
                print!(".");
             } else if *col == -1 as i32 {
                print!("X");
             } else {
                print!("{}", col);
             }
        }
        println!();
    }
}

fn fill_matrix(matrix: &mut [[i32; 10]; 10], entry: &mut Entry) {
    for x in entry.index_x..entry.width{
        for y in entry.index_y..entry.height {
            let current_value = matrix[x as usize][y as usize];
            if current_value == DEFAULT {
                 matrix[x as usize][y as usize] = entry.num;
                 //matrix[x as usize][y as usize] = "1";
            } else {
                if current_value != MULTIPLE {
                    matrix[x as usize][y as usize] = MULTIPLE;
                }
            }
        }
    }
}

fn code3() {
    use regex::Regex;
    let re = Regex::new(r"^#(\d) @ (\d),(\d): (\d)x(\d)").unwrap();
    let mut vec: Vec<String> = Vec::new();

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let str_line = line.unwrap().trim().to_string();
        if str_line == "0" {
            println!("exit!");
            break;
        }
        vec.push(str_line);
    }
    // check input
    let mut entries: Vec<Entry> = Vec::new();
    for line in vec {
        println!("{:?}", re.is_match(line.as_str()));
        for cap in re.captures_iter(line.as_str()) {
            let num: i32 = cap[1].parse::<i32>().unwrap();
            let index_x: i32 = cap[2].parse::<i32>().unwrap();
            let index_y: i32 = cap[3].parse::<i32>().unwrap();
            let width: i32 = cap[4].parse::<i32>().unwrap();
            let height: i32 = cap[5].parse::<i32>().unwrap();
            let entry = Entry{num, index_x, index_y, width, height};
            entries.push(entry);
        }
    }

    let mut matrix = [[DEFAULT; 10];10];

    for mut ent in entries {
        println!("{}",ent);
        fill_matrix(&mut matrix, &mut ent);
    }

    paint_matrix(&mut matrix);

}

fn main() {
    //code1();
    //code2();
    code3();
}
<commit_msg>Added first part for code day 4<commit_after>extern crate regex;

use std::io::{self, BufRead};
use std::collections::HashMap;
use std::fmt;

fn code1() {
    let stdin = io::stdin();

    let mut lines = stdin.lock().lines().fuse();
    let input = match lines.next()  {
        Some(Ok(a))  => a,
        _ => panic!("Couldn t read input.")
    };

    let info = input.trim();
    let splitted = info.split(",");
    let iter = splitted.map(|a| a.to_string().parse().unwrap_or(0));

    let mut result  = 0;
    for num in iter {
        result += num;
    }
    println!("{:?}", result);
}

fn code2() {
    let mut threes = 0;
    let mut two = 0;
    let mut vec: Vec<String> = Vec::new();

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let str_line = line.unwrap().trim().to_string();
        if str_line == "0" {
            println!("exit!");
            break;
        }
        vec.push(str_line);
    }

    let mut saved_characters: HashMap<String, i32> = HashMap::new();
    for info in &vec {
        for charact in info.to_string().chars()  {
            let value = saved_characters.entry(charact.to_string()).or_insert(0);
            *value += 1;
        }

        let temp_threes = saved_characters.values().filter(|val| **val == 3).count();
        let temp_two = saved_characters.values().filter(|val| **val == 2).count();

        threes += temp_threes;
        two += temp_two;
    }
    println!("------------------------------");
    println!("threes: {}", threes);
    println!("twos: {}", two);
}

static DEFAULT: i32 = 0;
static MULTIPLE:  i32 = -1;

fn paint_matrix(matrix: &mut [[i32; 10]; 10]) {
    for (i, row) in  matrix.iter_mut().enumerate() {
        for (y, col) in row.iter_mut().enumerate() {
             if *col == 0 as i32 {
                print!(".");
             } else if *col == -1 as i32 {
                print!("X");
             } else {
                print!("{}", col);
             }
        }
        println!();
    }
}

fn fill_matrix(matrix: &mut [[i32; 10]; 10], entry: &mut Entry) {
    for x in entry.index_x..entry.width{
        for y in entry.index_y..entry.height {
            let current_value = matrix[x as usize][y as usize];
            if current_value == DEFAULT {
                 matrix[x as usize][y as usize] = entry.num;
                 //matrix[x as usize][y as usize] = "1";
            } else {
                if current_value != MULTIPLE {
                    matrix[x as usize][y as usize] = MULTIPLE;
                }
            }
        }
    }
}

pub struct Entry {
    num: i32,
    index_x: i32,
    index_y: i32,
    width: i32,
    height: i32
}

impl fmt::Display for Entry {
    fn fmt(&self,fmt:  &mut fmt::Formatter) -> fmt::Result {
        let str_num = "num=".to_string()+&self.num.to_string();
        let str_index_x = "index_x=".to_string() + &self.index_x.to_string();
        let str_index_y = "index_y=".to_string() + &self.index_y.to_string();
        let str_w = "w=".to_string() + &self.width.to_string();
        let str_h = "h=".to_string() + &self.height.to_string();
        let parsed = str_num + " " + str_index_x.as_str() + " " +  str_index_y.as_str() + " " +  str_w.as_str() + " " +  str_h.as_str();
        fmt.write_str(parsed.as_str())?;
        Ok(())
    }
}

fn code3() {
    use regex::Regex;
    let re = Regex::new(r"^#(\d) @ (\d),(\d): (\d)x(\d)").unwrap();
    let mut vec: Vec<String> = Vec::new();

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let str_line = line.unwrap().trim().to_string();
        if str_line == "0" {
            println!("exit!");
            break;
        }
        vec.push(str_line);
    }
    // check input
    let mut entries: Vec<Entry> = Vec::new();
    for line in vec {
        println!("{:?}", re.is_match(line.as_str()));
        for cap in re.captures_iter(line.as_str()) {
            let num: i32 = cap[1].parse::<i32>().unwrap();
            let index_x: i32 = cap[2].parse::<i32>().unwrap();
            let index_y: i32 = cap[3].parse::<i32>().unwrap();
            let width: i32 = cap[4].parse::<i32>().unwrap();
            let height: i32 = cap[5].parse::<i32>().unwrap();
            let entry = Entry{num, index_x, index_y, width, height};
            entries.push(entry);
        }
    }

    let mut matrix = [[DEFAULT; 10];10];

    for mut ent in entries {
        println!("{}",ent);
        fill_matrix(&mut matrix, &mut ent);
    }

    paint_matrix(&mut matrix);

}

#[derive(PartialEq, Clone)]
enum Event {
    Shift,
    Asleep,
    Wakeup
}

pub struct SoldierEvent {
    event: Event,
    num_worker: i32,
    year: i32,
    month: i32,
    day: i32,
    hour: i32,
    minutes: i32

}
impl SoldierEvent  {
    fn new( event: Event, num_worker: i32, year: i32, month: i32, day: i32, hour: i32, minutes: i32) -> SoldierEvent {
        SoldierEvent {event: event, num_worker: num_worker, year: year, month: month, day: day, hour: hour, minutes: minutes}
    }

}

fn code4 () {
    use regex::Regex;
    let mut re_shift = Regex::new(r"^\[(\d{4})\-(\d{2})\-(\d{2}) (\d{2}):(\d{2})\] Guard #(\d{2}) begins shift").unwrap();
    let mut re_fall_sleeps = Regex::new(r"^\[(\d{4})\-(\d{2})\-(\d{2}) (\d{2}):(\d{2})\] falls asleep").unwrap();
    let mut re_wakes_up = Regex::new(r"^\[(\d{4})\-(\d{2})\-(\d{2}) (\d{2}):(\d{2})\] wakes up").unwrap();

    let mut vec: Vec<String> = Vec::new();

    let stdin = io::stdin();
    for line in stdin.lock().lines() {
        let str_line = line.unwrap().trim().to_string();
        if str_line == "0" {
            println!("exit!");
            break;
        }
        vec.push(str_line);
    }
    // check input
    let mut entries: Vec<SoldierEvent> = Vec::new();
    for line in vec {
        let mut current_soldier = -1;
        let typ: Event;
        let re;
        if (re_shift.is_match(line.as_str())) {
           re = re_shift.clone();
           typ = Event::Shift;
        } else if (re_fall_sleeps.is_match(line.as_str())) {
           re = re_fall_sleeps.clone();
           typ = Event::Asleep;
        } else {
           re = re_wakes_up.clone();
           typ = Event::Wakeup;
        }

        for cap in re.captures_iter(line.as_str()) {
            let year: i32 = cap[1].parse::<i32>().unwrap();
            let month: i32 = cap[2].parse::<i32>().unwrap();
            let day: i32 = cap[3].parse::<i32>().unwrap();
            let hour: i32 = cap[4].parse::<i32>().unwrap();
            let minutes: i32 = cap[5].parse::<i32>().unwrap();
            if(typ == Event::Shift) {
                current_soldier = cap[6].parse::<i32>().unwrap();
            }
            entries.push(SoldierEvent::new(typ.clone(), current_soldier, year, month, day, hour, minutes));
        }
    }
    println!("events {:}", entries.len());

    //TODO Finish code to search best sentynel
}

fn main() {
    //code1();
    //code2();
    //code3();
    code4();
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// 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.

mod handlers;

use std::collections::HashMap;

use hab_net::{ErrCode, NetError};
use hab_net::time;
use protocol::message::{Message, Protocol};
use protocol::routesrv::PING_INTERVAL_MS;
use protocol::sharding::{ShardId, SHARD_COUNT};
use rand::{self, Rng};
use zmq;

use config::Config;
use conn::{ConnErr, ConnEvent, SrvConn};
use error::{Error, Result};

const SERVER_TTL: i64 = PING_INTERVAL_MS + 2_000;

pub struct Server {
    /// Server's configuration.
    config: Config,
    /// ZeroMQ socket Context. Use this when creating new sockets if you wish them to be able to
    /// participate in the server's main thread.
    context: zmq::Context,
    /// Random seed used in calculating shard destinations.
    rng: rand::ThreadRng,
    /// Map of all registered servers and, if applicable, the shards they are hosting.
    servers: ServerMap,
}

impl Server {
    fn new(config: Config) -> Self {
        Server {
            config: config,
            context: zmq::Context::new(),
            rng: rand::thread_rng(),
            servers: ServerMap::default(),
        }
    }

    /// Forward a protocol message containing a transaction reply to the originator.
    fn forward_reply(&self, conn: &SrvConn, message: &mut Message) {
        message.identities.remove(0);
        trace!("route-message, transaction reply, {:?}", message);
        if let Err(err) = conn.forward_reply(message) {
            error!("{}", err);
        }
    }

    /// Handle a protocol message intended for this RouteSrv.
    fn handle_message(&mut self, conn: &SrvConn, message: &mut Message) -> Result<()> {
        debug!("handle-message, {}", message);
        let handler = match message.message_id() {
            "Disconnect" => handlers::on_disconnect,
            "Heartbeat" => handlers::on_heartbeat,
            "Registration" => handlers::on_registration,
            message_id => {
                warn!("handle-message, recv unknown message, {}", message_id);
                return Ok(());
            }
        };
        handler(conn, message, &mut self.servers)
    }

    /// Handle routing of a protocol message to a connected service or delegate to `handle_message`
    /// if the message was intended for this RouteSrv.
    fn route_message(&mut self, conn: &SrvConn, message: &mut Message) {
        match message.route_info().map(|r| r.protocol()) {
            Some(Protocol::RouteSrv) => {
                if let Err(err) = self.handle_message(&conn, message) {
                    error!("{}", err);
                }
            }
            Some(Protocol::Net) => warn!("route-message, unroutable message, {}", message),
            Some(_) => {
                if let Some(identity) = self.select_shard(message) {
                    if let Err(err) = conn.forward(message, identity.to_vec()) {
                        error!("{}", err);
                    }
                    return;
                }
                let err = NetError::new(ErrCode::NO_SHARD, "rt:route:2");
                error!("{}", err);
                message.populate_reply(&*err).unwrap();
                if let Err(err) = conn.forward_reply(message) {
                    error!("{}", err);
                }
            }
            None => warn!("route-message, no route-info, {}", message),
        }
    }

    /// Run the server blocking the calling thread until the server shuts down.
    fn run(&mut self) -> Result<()> {
        let mut conn = SrvConn::new(&mut self.context, &self.config)?;
        let mut message = Message::default();
        conn.bind(&self.config.addr())?;
        println!("Listening on ({})", self.config.addr());
        info!("builder-router is ready to go.");
        loop {
            message.reset();
            trace!("waiting for message");
            match conn.wait_recv(&mut message, self.wait_timeout()) {
                Ok(ConnEvent::OnMessage) => {
                    debug!("OnMessage, {}", message);
                    if message.completed_txn() {
                        self.forward_reply(&conn, &mut message);
                    } else {
                        self.route_message(&conn, &mut message);
                    }
                }
                Ok(ConnEvent::OnConnect) => debug!("OnConnect, {}", message.sender_str().unwrap()),
                Err(ConnErr::Shutdown(signal)) => {
                    info!("received shutdown signal ({}), shutting down...", signal);
                    break;
                }
                Err(err @ ConnErr::Socket(_)) => {
                    return Err(Error::from(err));
                }
                Err(ConnErr::Timeout) => (),
                Err(err) => error!("{}", err),
            }
            self.servers.expire();
        }
        Ok(())
    }

    /// Returns `Some` with the net identity of the server registered for the given protocol
    /// hosting the shard for which the given protocol message was intended for. Returns `None`
    /// if there is no server hosting the shard for the given protocol.
    fn select_shard(&mut self, message: &Message) -> Option<&[u8]> {
        let shard_id = match message.route_info().and_then(|m| m.hash()) {
            Some(hash) => (hash % SHARD_COUNT as u64) as u32,
            None => (self.rng.gen::<u64>() % SHARD_COUNT as u64) as u32,
        };
        self.servers.get(
            &message.route_info().unwrap().protocol(),
            &shard_id,
        )
    }

    /// A tickless timer for determining how long to wait between each server tick. This value is
    /// variable depending upon when the next registration expiration would occur. The default
    /// wait time is `30_000` milliseconds.
    fn wait_timeout(&self) -> i64 {
        self.servers.next_expiration().unwrap_or(30_000)
    }
}

#[derive(Debug, Default)]
pub struct ServerMap {
    reg: HashMap<Protocol, HashMap<ShardId, Vec<u8>>>,
    timestamps: HashMap<Vec<u8>, i64>,
}

impl ServerMap {
    pub fn add(&mut self, protocol: Protocol, net_ident: Vec<u8>, shards: Vec<ShardId>) -> bool {
        if !self.reg.contains_key(&protocol) {
            self.reg.insert(protocol, HashMap::default());
        }
        let registrations = self.reg.get_mut(&protocol).unwrap();
        for shard in shards.iter() {
            if let Some(reg) = registrations.get(&shard) {
                if reg != &net_ident {
                    return false;
                }
            }
        }
        for shard in shards {
            registrations.insert(shard, net_ident.clone());
        }
        self.timestamps.insert(net_ident, time::clock_time());
        true
    }

    pub fn drop(&mut self, target: &[u8]) {
        for map in self.reg.values_mut() {
            map.retain(|_, net_ident| net_ident.as_slice() != target);
        }
        self.timestamps.retain(
            |net_ident, _| net_ident.as_slice() != target,
        );
    }

    pub fn expire(&mut self) {
        let now = time::clock_time();
        let mut expired = vec![];
        self.timestamps.retain(
            |id, last| if (*last + SERVER_TTL) <= now {
                info!(
                    "expiring server registration, {:?}",
                    String::from_utf8_lossy(&id)
                );
                expired.push(id.clone());
                false
            } else {
                true
            },
        );
        for net_ident in expired.iter() {
            self.drop(net_ident);
        }
    }

    pub fn get(&self, protocol: &Protocol, shard: &ShardId) -> Option<&[u8]> {
        self.reg
            .get(protocol)
            .and_then(|shards| shards.get(shard))
            .and_then(|s| Some(s.as_slice()))
    }

    pub fn next_expiration(&self) -> Option<i64> {
        let mut timestamps = self.timestamps.values().collect::<Vec<&i64>>();
        timestamps.sort_by(|av, bv| bv.cmp(av));
        timestamps.first().map(|v| **v)
    }

    pub fn renew(&mut self, target: &[u8]) -> bool {
        if let Some(time) = self.timestamps.get_mut(target) {
            trace!("registration renew, {}", String::from_utf8_lossy(target));
            *time = time::clock_time() + SERVER_TTL;
            return true;
        }
        false
    }
}

pub fn run(config: Config) -> Result<()> {
    Server::new(config).run()
}
<commit_msg>Bump RouteSrv TTL from 32s to 35s<commit_after>// Copyright (c) 2016 Chef Software Inc. and/or applicable contributors
//
// 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.

mod handlers;

use std::collections::HashMap;

use hab_net::{ErrCode, NetError};
use hab_net::time;
use protocol::message::{Message, Protocol};
use protocol::routesrv::PING_INTERVAL_MS;
use protocol::sharding::{ShardId, SHARD_COUNT};
use rand::{self, Rng};
use zmq;

use config::Config;
use conn::{ConnErr, ConnEvent, SrvConn};
use error::{Error, Result};

const SERVER_TTL: i64 = PING_INTERVAL_MS + 5_000;

pub struct Server {
    /// Server's configuration.
    config: Config,
    /// ZeroMQ socket Context. Use this when creating new sockets if you wish them to be able to
    /// participate in the server's main thread.
    context: zmq::Context,
    /// Random seed used in calculating shard destinations.
    rng: rand::ThreadRng,
    /// Map of all registered servers and, if applicable, the shards they are hosting.
    servers: ServerMap,
}

impl Server {
    fn new(config: Config) -> Self {
        Server {
            config: config,
            context: zmq::Context::new(),
            rng: rand::thread_rng(),
            servers: ServerMap::default(),
        }
    }

    /// Forward a protocol message containing a transaction reply to the originator.
    fn forward_reply(&self, conn: &SrvConn, message: &mut Message) {
        message.identities.remove(0);
        trace!("route-message, transaction reply, {:?}", message);
        if let Err(err) = conn.forward_reply(message) {
            error!("{}", err);
        }
    }

    /// Handle a protocol message intended for this RouteSrv.
    fn handle_message(&mut self, conn: &SrvConn, message: &mut Message) -> Result<()> {
        debug!("handle-message, {}", message);
        let handler = match message.message_id() {
            "Disconnect" => handlers::on_disconnect,
            "Heartbeat" => handlers::on_heartbeat,
            "Registration" => handlers::on_registration,
            message_id => {
                warn!("handle-message, recv unknown message, {}", message_id);
                return Ok(());
            }
        };
        handler(conn, message, &mut self.servers)
    }

    /// Handle routing of a protocol message to a connected service or delegate to `handle_message`
    /// if the message was intended for this RouteSrv.
    fn route_message(&mut self, conn: &SrvConn, message: &mut Message) {
        match message.route_info().map(|r| r.protocol()) {
            Some(Protocol::RouteSrv) => {
                if let Err(err) = self.handle_message(&conn, message) {
                    error!("{}", err);
                }
            }
            Some(Protocol::Net) => warn!("route-message, unroutable message, {}", message),
            Some(_) => {
                if let Some(identity) = self.select_shard(message) {
                    if let Err(err) = conn.forward(message, identity.to_vec()) {
                        error!("{}", err);
                    }
                    return;
                }
                let err = NetError::new(ErrCode::NO_SHARD, "rt:route:2");
                error!("{}", err);
                message.populate_reply(&*err).unwrap();
                if let Err(err) = conn.forward_reply(message) {
                    error!("{}", err);
                }
            }
            None => warn!("route-message, no route-info, {}", message),
        }
    }

    /// Run the server blocking the calling thread until the server shuts down.
    fn run(&mut self) -> Result<()> {
        let mut conn = SrvConn::new(&mut self.context, &self.config)?;
        let mut message = Message::default();
        conn.bind(&self.config.addr())?;
        println!("Listening on ({})", self.config.addr());
        info!("builder-router is ready to go.");
        loop {
            message.reset();
            trace!("waiting for message");
            match conn.wait_recv(&mut message, self.wait_timeout()) {
                Ok(ConnEvent::OnMessage) => {
                    debug!("OnMessage, {}", message);
                    if message.completed_txn() {
                        self.forward_reply(&conn, &mut message);
                    } else {
                        self.route_message(&conn, &mut message);
                    }
                }
                Ok(ConnEvent::OnConnect) => debug!("OnConnect, {}", message.sender_str().unwrap()),
                Err(ConnErr::Shutdown(signal)) => {
                    info!("received shutdown signal ({}), shutting down...", signal);
                    break;
                }
                Err(err @ ConnErr::Socket(_)) => {
                    return Err(Error::from(err));
                }
                Err(ConnErr::Timeout) => (),
                Err(err) => error!("{}", err),
            }
            self.servers.expire();
        }
        Ok(())
    }

    /// Returns `Some` with the net identity of the server registered for the given protocol
    /// hosting the shard for which the given protocol message was intended for. Returns `None`
    /// if there is no server hosting the shard for the given protocol.
    fn select_shard(&mut self, message: &Message) -> Option<&[u8]> {
        let shard_id = match message.route_info().and_then(|m| m.hash()) {
            Some(hash) => (hash % SHARD_COUNT as u64) as u32,
            None => (self.rng.gen::<u64>() % SHARD_COUNT as u64) as u32,
        };
        self.servers.get(
            &message.route_info().unwrap().protocol(),
            &shard_id,
        )
    }

    /// A tickless timer for determining how long to wait between each server tick. This value is
    /// variable depending upon when the next registration expiration would occur. The default
    /// wait time is `30_000` milliseconds.
    fn wait_timeout(&self) -> i64 {
        self.servers.next_expiration().unwrap_or(30_000)
    }
}

#[derive(Debug, Default)]
pub struct ServerMap {
    reg: HashMap<Protocol, HashMap<ShardId, Vec<u8>>>,
    timestamps: HashMap<Vec<u8>, i64>,
}

impl ServerMap {
    pub fn add(&mut self, protocol: Protocol, net_ident: Vec<u8>, shards: Vec<ShardId>) -> bool {
        if !self.reg.contains_key(&protocol) {
            self.reg.insert(protocol, HashMap::default());
        }
        let registrations = self.reg.get_mut(&protocol).unwrap();
        for shard in shards.iter() {
            if let Some(reg) = registrations.get(&shard) {
                if reg != &net_ident {
                    return false;
                }
            }
        }
        for shard in shards {
            registrations.insert(shard, net_ident.clone());
        }
        self.timestamps.insert(net_ident, time::clock_time());
        true
    }

    pub fn drop(&mut self, target: &[u8]) {
        for map in self.reg.values_mut() {
            map.retain(|_, net_ident| net_ident.as_slice() != target);
        }
        self.timestamps.retain(
            |net_ident, _| net_ident.as_slice() != target,
        );
    }

    pub fn expire(&mut self) {
        let now = time::clock_time();
        let mut expired = vec![];
        self.timestamps.retain(
            |id, last| if (*last + SERVER_TTL) <= now {
                info!(
                    "expiring server registration, {:?}",
                    String::from_utf8_lossy(&id)
                );
                expired.push(id.clone());
                false
            } else {
                true
            },
        );
        for net_ident in expired.iter() {
            self.drop(net_ident);
        }
    }

    pub fn get(&self, protocol: &Protocol, shard: &ShardId) -> Option<&[u8]> {
        self.reg
            .get(protocol)
            .and_then(|shards| shards.get(shard))
            .and_then(|s| Some(s.as_slice()))
    }

    pub fn next_expiration(&self) -> Option<i64> {
        let mut timestamps = self.timestamps.values().collect::<Vec<&i64>>();
        timestamps.sort_by(|av, bv| bv.cmp(av));
        timestamps.first().map(|v| **v)
    }

    pub fn renew(&mut self, target: &[u8]) -> bool {
        if let Some(time) = self.timestamps.get_mut(target) {
            trace!("registration renew, {}", String::from_utf8_lossy(target));
            *time = time::clock_time() + SERVER_TTL;
            return true;
        }
        false
    }
}

pub fn run(config: Config) -> Result<()> {
    Server::new(config).run()
}
<|endoftext|>


<commit_before>use crate::assist_ctx::{Assist, AssistCtx};
use hir::db::HirDatabase;

pub(crate) fn add_missing_impl_members(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
    unimplemented!()
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::helpers::{ check_assist };

    #[test]
    fn test_add_missing_impl_members() {
        check_assist(
            add_missing_impl_members,
            "
trait Foo {
    fn foo(&self);
}

struct S;

impl Foo for S {
    <|>
}",
            "
trait Foo {
    fn foo(&self);
}

struct S;

impl Foo for S {
    fn foo(&self) {
        <|>
    }
}",
        );
    }
}
<commit_msg>Calculate missing functions from impl body<commit_after>use std::collections::HashSet;

use crate::assist_ctx::{Assist, AssistCtx};

use hir::Resolver;
use hir::db::HirDatabase;
use ra_syntax::{SmolStr, SyntaxKind, SyntaxNode, TreeArc};
use ra_syntax::ast::{self, AstNode, FnDef, ImplItem, ImplItemKind, NameOwner};
use ra_db::FilePosition;

/// Given an `ast::ImplBlock`, resolves the target trait (the one being
/// implemented) to a `ast::TraitDef`.
pub(crate) fn resolve_target_trait_def(
    db: &impl HirDatabase,
    resolver: &Resolver,
    impl_block: &ast::ImplBlock,
) -> Option<TreeArc<ast::TraitDef>> {
    let ast_path = impl_block.target_trait().map(AstNode::syntax).and_then(ast::PathType::cast)?;
    let hir_path = ast_path.path().and_then(hir::Path::from_ast)?;

    match resolver.resolve_path(db, &hir_path).take_types() {
        Some(hir::Resolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).1),
        _ => None,
    }
}

pub(crate) fn add_missing_impl_members(ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
    use SyntaxKind::{IMPL_BLOCK, ITEM_LIST, WHITESPACE};

    let node = ctx.covering_node();
    let kinds = node.ancestors().take(3).map(SyntaxNode::kind);
    // Only suggest this in `impl Foo for S { [Item...] <|> }` cursor position
    if !Iterator::eq(kinds, [WHITESPACE, ITEM_LIST, IMPL_BLOCK].iter().cloned()) {
        return None;
    }

    let impl_node = node.ancestors().find_map(ast::ImplBlock::cast)?;

    let trait_def = {
        let db = ctx.db;
        // TODO: Can we get the position of cursor itself rather than supplied range?
        let range = ctx.frange;
        let position = FilePosition { file_id: range.file_id, offset: range.range.start() };
        let resolver = hir::source_binder::resolver_for_position(db, position);

        resolve_target_trait_def(db, &resolver, impl_node)?
    };

    let fn_def_opt = |kind| if let ImplItemKind::FnDef(def) = kind { Some(def) } else { None };
    let def_name = |&def| -> Option<&SmolStr> { FnDef::name(def).map(ast::Name::text) };

    let trait_items = trait_def.syntax().descendants().find_map(ast::ItemList::cast)?.impl_items();
    let impl_items = impl_node.item_list()?.impl_items();

    let trait_fns = trait_items.map(ImplItem::kind).filter_map(fn_def_opt).collect::<Vec<_>>();
    let impl_fns = impl_items.map(ImplItem::kind).filter_map(fn_def_opt).collect::<Vec<_>>();

    let trait_fn_names = trait_fns.iter().filter_map(def_name).collect::<HashSet<_>>();
    let impl_fn_names = impl_fns.iter().filter_map(def_name).collect::<HashSet<_>>();

    let missing_fn_names = trait_fn_names.difference(&impl_fn_names).collect::<HashSet<_>>();
    let missing_fns = trait_fns
        .iter()
        .filter(|&t| def_name(t).map(|n| missing_fn_names.contains(&n)).unwrap_or(false));

    unimplemented!()
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::helpers::{ check_assist };

    #[test]
    fn test_add_missing_impl_members() {
        check_assist(
            add_missing_impl_members,
            "
trait Foo {
    fn foo(&self);
}

struct S;

impl Foo for S {
    <|>
}",
            "
trait Foo {
    fn foo(&self);
}

struct S;

impl Foo for S {
    fn foo(&self) {
        <|>
    }
}",
        );
    }
}
<|endoftext|>


<commit_before>//! This module provides a microfacet model for transmission (a BTDF), see
//! [Walter et al. 07](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)
//! for details.

use std::f32;
use enum_set::EnumSet;

use linalg::{self, Vector};
use film::Colorf;
use bxdf::{self, BxDF, BxDFType};
use bxdf::fresnel::{Dielectric, Fresnel};
use bxdf::microfacet::{MicrofacetDistribution};

/// Struct providing the microfacet BTDF, implemented as described in
/// [Walter et al. 07](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)
pub struct MicrofacetTransmission {
    reflectance: Colorf,
    fresnel: Dielectric,
    /// Microfacet distribution describing the structure of the microfacets of
    /// the material
    microfacet: Box<MicrofacetDistribution + Send + Sync>,
}

impl MicrofacetTransmission {
    /// Create a new transmissive microfacet BRDF
    pub fn new(c: &Colorf, fresnel: Dielectric,
               microfacet: Box<MicrofacetDistribution + Send + Sync>) -> MicrofacetTransmission {
        MicrofacetTransmission { reflectance: *c, fresnel: fresnel, microfacet: microfacet }
    }
    /// Convenience method for getting `eta_i` and `eta_t` in the right order for if
    /// we're entering or exiting this material based on the direction of the outgoing
    /// ray.
    fn eta_for_interaction(&self, w_o: &Vector) -> (f32, f32) {
        if w_o.z > 0.0 {
            (self.fresnel.eta_i, self.fresnel.eta_t)
        } else {
            (self.fresnel.eta_t, self.fresnel.eta_i)
        }
    }
}

impl BxDF for MicrofacetTransmission {
    fn bxdf_type(&self) -> EnumSet<BxDFType> {
        let mut e = EnumSet::new();
        e.insert(BxDFType::Glossy);
        e.insert(BxDFType::Transmission);
        e
    }
    fn eval(&self, w_o: &Vector, w_i: &Vector) -> Colorf {
        let cos_to = f32::abs(bxdf::cos_theta(w_o));
        let cos_ti = f32::abs(bxdf::cos_theta(w_i));
        if cos_to == 0.0 || cos_ti == 0.0 {
            return Colorf::new(0.0, 0.0, 0.0)
        }
        let mut w_h = *w_i + *w_o;
        if w_h.x == 0.0 && w_h.y == 0.0 && w_h.z == 0.0 {
            return Colorf::new(0.0, 0.0, 0.0)
        }
        w_h = w_h.normalized();
        let eta = self.eta_for_interaction(w_o);
        let d = self.microfacet.normal_distribution(&w_h);
        let f = Colorf::broadcast(1.0) - self.fresnel.fresnel(linalg::dot(w_i, &w_h));
        let g = self.microfacet.shadowing_masking(w_i, w_o, &w_h);
        let wi_dot_h = linalg::dot(w_i, &w_h);
        let wo_dot_h = linalg::dot(w_o, &w_h);
        self.reflectance
            * (f32::abs(wi_dot_h) * f32::abs(wo_dot_h)) / (f32::abs(w_i.z) * f32::abs(w_o.z))
            * (f32::powf(eta.1, 2.0) * f * g * d) / f32::powf(eta.0 * wi_dot_h + eta.1 * wo_dot_h, 2.0)
    }
    fn sample(&self, w_o: &Vector, samples: &(f32, f32)) -> (Colorf, Vector, f32) {
        let w_h = match self.microfacet.sample(w_o, samples) {
            h if !bxdf::same_hemisphere(w_o, &h) => -h,
            h => h
        };
        let eta = self.eta_for_interaction(w_o);
        let w_i = match linalg::refract(w_o, &w_h, eta.0, eta.1) {
            Some(v) => v,
            None => return (Colorf::black(), Vector::broadcast(0.0), 0.0),
        };
        if bxdf::same_hemisphere(w_o, &w_i) {
            (Colorf::black(), Vector::broadcast(0.0), 0.0)
        } else {
            // This term is p_o(o) in eq. 38 of Walter et al's 07 paper and is for reflection so
            // we use the Jacobian for reflection, eq. 17
            let wi_dot_h = linalg::dot(&w_i, &w_h);
            let wo_dot_h = linalg::dot(w_o, &w_h);
            let jacobian = eta.1 * f32::abs(linalg::dot(w_o, &w_h))
                / f32::powf(eta.1 * wi_dot_h + eta.0 * wo_dot_h, 2.0);
            let pdf = self.microfacet.pdf(&w_h) * jacobian;
            (self.eval(w_o, &w_i), w_i, pdf)
        }
    }
    fn pdf(&self, w_o: &Vector, w_i: &Vector) -> f32 {
        if bxdf::same_hemisphere(w_o, w_i) {
            0.0
        } else {
            let w_h = *w_o + *w_i;
            if w_h.x == 0.0 && w_h.y == 0.0 && w_h.z == 0.0 {
                0.0
            } else {
                let eta = self.eta_for_interaction(w_o);
                let wi_dot_h = linalg::dot(w_i, &w_h);
                let wo_dot_h = linalg::dot(w_o, &w_h);
                // This term is p_o(o) in eq. 38 of Walter et al's 07 paper and is for reflection so
                // we use the Jacobian for reflection, eq. 17
                let jacobian = eta.1 * f32::abs(linalg::dot(w_o, &w_h))
                    / f32::powf(eta.1 * wi_dot_h + eta.0 * wo_dot_h, 2.0);
                self.microfacet.pdf(&w_h.normalized()) * jacobian
            }
        }
    }
}

<commit_msg>Rough glass almost right, not quite Blender but could be some other dif?<commit_after>//! This module provides a microfacet model for transmission (a BTDF), see
//! [Walter et al. 07](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)
//! for details.

use std::f32;
use enum_set::EnumSet;

use linalg::{self, Vector};
use film::Colorf;
use bxdf::{self, BxDF, BxDFType};
use bxdf::fresnel::{Dielectric, Fresnel};
use bxdf::microfacet::{MicrofacetDistribution};

/// Struct providing the microfacet BTDF, implemented as described in
/// [Walter et al. 07](https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.pdf)
pub struct MicrofacetTransmission {
    reflectance: Colorf,
    fresnel: Dielectric,
    /// Microfacet distribution describing the structure of the microfacets of
    /// the material
    microfacet: Box<MicrofacetDistribution + Send + Sync>,
}

impl MicrofacetTransmission {
    /// Create a new transmissive microfacet BRDF
    pub fn new(c: &Colorf, fresnel: Dielectric,
               microfacet: Box<MicrofacetDistribution + Send + Sync>) -> MicrofacetTransmission {
        MicrofacetTransmission { reflectance: *c, fresnel: fresnel, microfacet: microfacet }
    }
    /// Convenience method for getting `eta_i` and `eta_t` in the right order for if
    /// we're entering or exiting this material based on the direction of the outgoing
    /// ray.
    fn eta_for_interaction(&self, w_o: &Vector) -> (f32, f32) {
        if bxdf::cos_theta(w_o) > 0.0 {
            (self.fresnel.eta_i, self.fresnel.eta_t)
        } else {
            (self.fresnel.eta_t, self.fresnel.eta_i)
        }
    }
    /// Compute the Jacobian for the change of variables (see [Walter et al 07] section 4.2),
    /// here we compute equation 17 in that section.
    fn jacobian(w_o: &Vector, w_i: &Vector, w_h: &Vector, eta: (f32, f32)) -> f32 {
        let wi_dot_h = linalg::dot(w_i, w_h);
        let wo_dot_h = linalg::dot(w_o, w_h);
        f32::powf(eta.1, 2.0) * f32::abs(wo_dot_h) / f32::powf(eta.0 * wi_dot_h + eta.1 * wo_dot_h, 2.0)
    }
    fn half_vector(w_o: &Vector, w_i: &Vector, eta: (f32, f32)) -> Option<Vector> {
        let mut w_h = -eta.0 * *w_o - eta.1 * *w_i;
        if w_h.x == 0.0 && w_h.y == 0.0 && w_h.z == 0.0 {
            None
        } else {
            Some(w_h.normalized())
        }
    }
}

impl BxDF for MicrofacetTransmission {
    fn bxdf_type(&self) -> EnumSet<BxDFType> {
        let mut e = EnumSet::new();
        e.insert(BxDFType::Glossy);
        e.insert(BxDFType::Transmission);
        e
    }
    // etaA is on the outside, etaB is on the inside
    // so etaA = eta.0, etaB = eta.1
    // in walter eta al eta_i is incident side, eta_o/eta_t is transmitted side
    // so eta_i = eta.0, eta_o & eta_t = eta.1
    fn eval(&self, w_o: &Vector, w_i: &Vector) -> Colorf {
        if bxdf::same_hemisphere(w_o, w_i) {
            return Colorf::black();
        }
        let cos_to = bxdf::cos_theta(w_o);
        let cos_ti = bxdf::cos_theta(w_i);
        if cos_to == 0.0 || cos_ti == 0.0 {
            return Colorf::black();
        }
        let eta = self.eta_for_interaction(w_o);
        if let Some(w_h) = MicrofacetTransmission::half_vector(w_o, w_i, eta) {
            let d = self.microfacet.normal_distribution(&w_h);
            let f = Colorf::broadcast(1.0) - self.fresnel.fresnel(linalg::dot(w_o, &w_h));
            let g = self.microfacet.shadowing_masking(w_i, w_o, &w_h);
            let wi_dot_h = linalg::dot(w_i, &w_h);
            let jacobian = MicrofacetTransmission::jacobian(w_o, w_i, &w_h, eta);
            self.reflectance * (f32::abs(wi_dot_h) / (f32::abs(w_i.z) * f32::abs(w_o.z)))
                * (f * g * d) * jacobian
        } else {
            Colorf::black()
        }
    }
    // NOTE: w_o is in the material we're coming from, w_i is in the material we're entering
    fn sample(&self, w_o: &Vector, samples: &(f32, f32)) -> (Colorf, Vector, f32) {
        let mut w_h = self.microfacet.sample(w_o, samples);
        if !bxdf::same_hemisphere(w_o, &w_h) {
            w_h = -w_h;
        }
        let eta = self.eta_for_interaction(w_o);
        if let Some(w_i) = linalg::refract(w_o, &w_h, eta.0, eta.1) {
            if bxdf::same_hemisphere(w_o, &w_i) {
                (Colorf::black(), Vector::broadcast(0.0), 0.0)
            } else {
                let pdf = self.microfacet.pdf(&w_h)
                    * MicrofacetTransmission::jacobian(w_o, &w_i, &w_h, eta);
                (self.eval(w_o, &w_i), w_i, pdf)
            }
        } else {
            (Colorf::black(), Vector::broadcast(0.0), 0.0)
        }
    }
    fn pdf(&self, w_o: &Vector, w_i: &Vector) -> f32 {
        if bxdf::same_hemisphere(w_o, w_i) {
            0.0
        } else {
            let eta = self.eta_for_interaction(w_o);
            if let Some(w_h) = MicrofacetTransmission::half_vector(w_o, w_i, eta) {
                self.microfacet.pdf(&w_h) * MicrofacetTransmission::jacobian(w_o, w_i, &w_h, eta)
            } else {
                0.0
            }
        }
    }
}

<|endoftext|>


<commit_before>extern crate libc;
use self::libc::{uint32_t, c_void, c_int};

extern crate errno;
use self::errno::errno;

use std::str;

// this extern block links to the libproc library
#[link(name="proc", kind="dylib")]
extern {
    // Original signature from http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c
    // int proc_pidpath(int pid, void * buffer, uint32_t  buffersize)
    fn proc_pidpath(pid: c_int, buffer: *mut c_void, buffersize : uint32_t) -> c_int;
}

// Since we cannot access C macros for constants from Rust - I have had to redefine this, based on Apple's source code
// See http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c
// buffersize must be more than PROC_PIDPATHINFO_SIZE
// buffersize must be less than PROC_PIDPATHINFO_MAXSIZE
//
// See http://opensource.apple.com//source/xnu/xnu-1456.1.26/bsd/sys/proc_info.h
// #define PROC_PIDPATHINFO_SIZE		(MAXPATHLEN)
// #define PROC_PIDPATHINFO_MAXSIZE	(4*MAXPATHLEN)
// in http://opensource.apple.com//source/xnu/xnu-1504.7.4/bsd/sys/param.h
// #define	MAXPATHLEN	PATH_MAX
// in https://opensource.apple.com/source/xnu/xnu-792.25.20/bsd/sys/syslimits.h
// #define	PATH_MAX		 1024
const MAXPATHLEN : usize = 1024;
const PROC_PIDPATHINFO_MAXSIZE : usize = 4 * MAXPATHLEN;

pub fn pidpath(pid : i32) -> Result<String, String> {
    let pathbuf : Vec<u8>= Vec::with_capacity(PROC_PIDPATHINFO_MAXSIZE - 1);

    let buffer_ptr = pathbuf.as_ptr() as *mut c_void;
    let buffer_size = pathbuf.capacity() as u32;

    let ret;
    let rebuilt : Vec<u8>;

    unsafe {
        ret = proc_pidpath(pid, buffer_ptr, buffer_size);
        rebuilt = Vec::from_raw_parts(buffer_ptr as *mut u8, ret as usize, buffer_size as usize);
    };

    if ret <= 0 {
        let e = errno();
        let code = e.0 as i32;
        Err(format!("proc_pidpath() returned {}, errno = {}, '{}'", ret, code, e))
    } else {
        match String::from_utf8(rebuilt) {
            Ok(path) => Ok(path),
            Err(e) => Err(format!("Invalid UTF-8 sequence: {}", e))
        }
    }
}<commit_msg>Implemented proc_libversion() with a unit test<commit_after>extern crate libc;
use self::libc::{uint32_t, c_void, c_int};

extern crate errno;
use self::errno::errno;

use std::str;

// Since we cannot access C macros for constants from Rust - I have had to redefine this, based on Apple's source code
// See http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c
// buffersize must be more than PROC_PIDPATHINFO_SIZE
// buffersize must be less than PROC_PIDPATHINFO_MAXSIZE
//
// See http://opensource.apple.com//source/xnu/xnu-1456.1.26/bsd/sys/proc_info.h
// #define PROC_PIDPATHINFO_SIZE		(MAXPATHLEN)
// #define PROC_PIDPATHINFO_MAXSIZE	(4*MAXPATHLEN)
// in http://opensource.apple.com//source/xnu/xnu-1504.7.4/bsd/sys/param.h
// #define	MAXPATHLEN	PATH_MAX
// in https://opensource.apple.com/source/xnu/xnu-792.25.20/bsd/sys/syslimits.h
// #define	PATH_MAX		 1024
const MAXPATHLEN : usize = 1024;
const PROC_PIDPATHINFO_MAXSIZE : usize = 4 * MAXPATHLEN;

// this extern block links to the libproc library
#[link(name="proc", kind="dylib")]
extern {
    // Original signatures from http://opensource.apple.com/source/Libc/Libc-594.9.4/darwin/libproc.c

    // int proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize)

    // int proc_pidinfo(int pid, int flavor, uint64_t arg,  void *buffer, int buffersize)

    // int proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize)

    // int proc_name(int pid, void * buffer, uint32_t buffersize)

    // int proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize)

    // int proc_kmsgbuf(void * buffer, uint32_t  buffersize)

    // int proc_pidpath(int pid, void * buffer, uint32_t  buffersize)
    fn proc_pidpath(pid: c_int, buffer: *mut c_void, buffersize : uint32_t) -> c_int;

    // int proc_libversion(int *major, int * minor)
    // return value of 0 indicates success (inconsistent :-( )
    fn proc_libversion(major : *mut c_int, minor : * mut c_int) -> c_int;
}

fn get_errno_with_message(ret : i32) -> String {
    let e = errno();
    let code = e.0 as i32;
    format!("return code = {}, errno = {}, message = '{}'", ret, code, e)
}

pub fn pidpath(pid : i32) -> Result<String, String> {
    let pathbuf : Vec<u8>= Vec::with_capacity(PROC_PIDPATHINFO_MAXSIZE - 1);

    let buffer_ptr = pathbuf.as_ptr() as *mut c_void;
    let buffer_size = pathbuf.capacity() as u32;

    let ret : i32;
    let rebuilt : Vec<u8>;

    unsafe {
        ret = proc_pidpath(pid, buffer_ptr, buffer_size);
        rebuilt = Vec::from_raw_parts(buffer_ptr as *mut u8, ret as usize, buffer_size as usize);
    };

    if ret <= 0 {
        Err(get_errno_with_message(ret))
    } else {
        match String::from_utf8(rebuilt) {
            Ok(path) => Ok(path),
            Err(e) => Err(format!("Invalid UTF-8 sequence: {}", e))
        }
    }
}

pub fn libversion() -> Result<(i32, i32), String> {
    let mut major = 0;
    let mut minor = 0;
    let ret : i32;

    unsafe {
        ret = proc_libversion(&mut major, &mut minor);
    };

    if ret == 0 {
        Ok((major, minor))
    } else {
        Err(get_errno_with_message(ret))
    }
}

#[test]
fn libversion_test() {
    match libversion() {
        Ok((major, minor)) => {
            // run tests with 'cargo test -- --nocapture' to see the test output
            println!("Major = {}, Minor = {}", major, minor);
        },
        Err(message) => assert!(false, message)
    }
}<|endoftext|>


<commit_before>enum ast {
    num(uint),
    add(&ast, &ast)
}

fn mk_add_bad1(x: &a/ast, y: &b/ast) -> ast/&a {
    add(x, y) //~ ERROR mismatched types: expected `&a.ast/&a` but found `&b.ast/&b`
}

fn main() {
}<commit_msg>repair error msg<commit_after>enum ast {
    num(uint),
    add(&ast, &ast)
}

fn mk_add_bad1(x: &a/ast, y: &b/ast) -> ast/&a {
    add(x, y) //~ ERROR mismatched types: expected `&a/ast/&a` but found `&b/ast/&b`
}

fn main() {
}<|endoftext|>


<commit_before>use hir::StructKind;
use syntax::ast;

pub fn use_trivial_constructor(
    db: &crate::RootDatabase,
    path: ast::Path,
    ty: &hir::Type,
) -> Option<ast::Expr> {
    match ty.as_adt() {
        Some(hir::Adt::Enum(x)) => {
            if let &[variant] = &*x.variants(db) {
                if variant.kind(db) == hir::StructKind::Unit {
                    let path = ast::make::path_qualified(
                        path,
                        syntax::ast::make::path_segment(ast::make::name_ref(
                            &variant.name(db).to_smol_str(),
                        )),
                    );

                    return Some(syntax::ast::make::expr_path(path));
                }
            }
        }
        Some(hir::Adt::Struct(x)) if x.kind(db) == StructKind::Unit => {
            return Some(syntax::ast::make::expr_path(path));
        }
        _ => {}
    }

    None
}
<commit_msg>add doc strings to use_trivial_contructor.rs<commit_after>//! Functionality for generating trivial contructors

use hir::StructKind;
use syntax::ast;

/// given a type return the trivial contructor (if one exists)
pub fn use_trivial_constructor(
    db: &crate::RootDatabase,
    path: ast::Path,
    ty: &hir::Type,
) -> Option<ast::Expr> {
    match ty.as_adt() {
        Some(hir::Adt::Enum(x)) => {
            if let &[variant] = &*x.variants(db) {
                if variant.kind(db) == hir::StructKind::Unit {
                    let path = ast::make::path_qualified(
                        path,
                        syntax::ast::make::path_segment(ast::make::name_ref(
                            &variant.name(db).to_smol_str(),
                        )),
                    );

                    return Some(syntax::ast::make::expr_path(path));
                }
            }
        }
        Some(hir::Adt::Struct(x)) if x.kind(db) == StructKind::Unit => {
            return Some(syntax::ast::make::expr_path(path));
        }
        _ => {}
    }

    None
}
<|endoftext|>


<commit_before>//! See [`CargoWorkspace`].

use std::convert::TryInto;
use std::iter;
use std::path::PathBuf;
use std::{ops, process::Command};

use anyhow::{Context, Result};
use base_db::Edition;
use cargo_metadata::{CargoOpt, MetadataCommand};
use la_arena::{Arena, Idx};
use paths::{AbsPath, AbsPathBuf};
use rustc_hash::FxHashMap;
use serde::Deserialize;
use serde_json::from_value;

use crate::CfgOverrides;
use crate::{utf8_stdout, ManifestPath};

/// [`CargoWorkspace`] represents the logical structure of, well, a Cargo
/// workspace. It pretty closely mirrors `cargo metadata` output.
///
/// Note that internally, rust analyzer uses a different structure:
/// `CrateGraph`. `CrateGraph` is lower-level: it knows only about the crates,
/// while this knows about `Packages` & `Targets`: purely cargo-related
/// concepts.
///
/// We use absolute paths here, `cargo metadata` guarantees to always produce
/// abs paths.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct CargoWorkspace {
    packages: Arena<PackageData>,
    targets: Arena<TargetData>,
    workspace_root: AbsPathBuf,
}

impl ops::Index<Package> for CargoWorkspace {
    type Output = PackageData;
    fn index(&self, index: Package) -> &PackageData {
        &self.packages[index]
    }
}

impl ops::Index<Target> for CargoWorkspace {
    type Output = TargetData;
    fn index(&self, index: Target) -> &TargetData {
        &self.targets[index]
    }
}

/// Describes how to set the rustc source directory.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RustcSource {
    /// Explicit path for the rustc source directory.
    Path(AbsPathBuf),
    /// Try to automatically detect where the rustc source directory is.
    Discover,
}

#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct CargoConfig {
    /// Do not activate the `default` feature.
    pub no_default_features: bool,

    /// Activate all available features
    pub all_features: bool,

    /// List of features to activate.
    /// This will be ignored if `cargo_all_features` is true.
    pub features: Vec<String>,

    /// rustc target
    pub target: Option<String>,

    /// Don't load sysroot crates (`std`, `core` & friends). Might be useful
    /// when debugging isolated issues.
    pub no_sysroot: bool,

    /// rustc private crate source
    pub rustc_source: Option<RustcSource>,

    /// crates to disable `#[cfg(test)]` on
    pub unset_test_crates: Vec<String>,

    pub wrap_rustc_in_build_scripts: bool,
}

impl CargoConfig {
    pub fn cfg_overrides(&self) -> CfgOverrides {
        self.unset_test_crates
            .iter()
            .cloned()
            .zip(iter::repeat_with(|| {
                cfg::CfgDiff::new(Vec::new(), vec![cfg::CfgAtom::Flag("test".into())]).unwrap()
            }))
            .collect()
    }
}

pub type Package = Idx<PackageData>;

pub type Target = Idx<TargetData>;

/// Information associated with a cargo crate
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PackageData {
    /// Version given in the `Cargo.toml`
    pub version: semver::Version,
    /// Name as given in the `Cargo.toml`
    pub name: String,
    /// Path containing the `Cargo.toml`
    pub manifest: ManifestPath,
    /// Targets provided by the crate (lib, bin, example, test, ...)
    pub targets: Vec<Target>,
    /// Is this package a member of the current workspace
    pub is_member: bool,
    /// List of packages this package depends on
    pub dependencies: Vec<PackageDependency>,
    /// Rust edition for this package
    pub edition: Edition,
    /// Features provided by the crate, mapped to the features required by that feature.
    pub features: FxHashMap<String, Vec<String>>,
    /// List of features enabled on this package
    pub active_features: Vec<String>,
    // String representation of package id
    pub id: String,
    // The contents of [package.metadata.rust-analyzer]
    pub metadata: RustAnalyzerPackageMetaData,
}

#[derive(Deserialize, Default, Debug, Clone, Eq, PartialEq)]
pub struct RustAnalyzerPackageMetaData {
    pub rustc_private: bool,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PackageDependency {
    pub pkg: Package,
    pub name: String,
    pub kind: DepKind,
}

#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub enum DepKind {
    /// Available to the library, binary, and dev targets in the package (but not the build script).
    Normal,
    /// Available only to test and bench targets (and the library target, when built with `cfg(test)`).
    Dev,
    /// Available only to the build script target.
    Build,
}

impl DepKind {
    fn iter(list: &[cargo_metadata::DepKindInfo]) -> impl Iterator<Item = Self> + '_ {
        let mut dep_kinds = Vec::new();
        if list.is_empty() {
            dep_kinds.push(Self::Normal);
        }
        for info in list {
            let kind = match info.kind {
                cargo_metadata::DependencyKind::Normal => Self::Normal,
                cargo_metadata::DependencyKind::Development => Self::Dev,
                cargo_metadata::DependencyKind::Build => Self::Build,
                cargo_metadata::DependencyKind::Unknown => continue,
            };
            dep_kinds.push(kind);
        }
        dep_kinds.sort_unstable();
        dep_kinds.dedup();
        dep_kinds.into_iter()
    }
}

/// Information associated with a package's target
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct TargetData {
    /// Package that provided this target
    pub package: Package,
    /// Name as given in the `Cargo.toml` or generated from the file name
    pub name: String,
    /// Path to the main source file of the target
    pub root: AbsPathBuf,
    /// Kind of target
    pub kind: TargetKind,
    /// Is this target a proc-macro
    pub is_proc_macro: bool,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TargetKind {
    Bin,
    /// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
    Lib,
    Example,
    Test,
    Bench,
    BuildScript,
    Other,
}

impl TargetKind {
    fn new(kinds: &[String]) -> TargetKind {
        for kind in kinds {
            return match kind.as_str() {
                "bin" => TargetKind::Bin,
                "test" => TargetKind::Test,
                "bench" => TargetKind::Bench,
                "example" => TargetKind::Example,
                "custom-build" => TargetKind::BuildScript,
                "proc-macro" => TargetKind::Lib,
                _ if kind.contains("lib") => TargetKind::Lib,
                _ => continue,
            };
        }
        TargetKind::Other
    }
}

#[derive(Deserialize, Default)]
// Deserialise helper for the cargo metadata
struct PackageMetadata {
    #[serde(rename = "rust-analyzer")]
    rust_analyzer: Option<RustAnalyzerPackageMetaData>,
}

impl CargoWorkspace {
    pub fn fetch_metadata(
        cargo_toml: &ManifestPath,
        config: &CargoConfig,
        progress: &dyn Fn(String),
    ) -> Result<cargo_metadata::Metadata> {
        let target = config
            .target
            .clone()
            .or_else(|| cargo_config_build_target(cargo_toml))
            .or_else(|| rustc_discover_host_triple(cargo_toml));

        let mut meta = MetadataCommand::new();
        meta.cargo_path(toolchain::cargo());
        meta.manifest_path(cargo_toml.to_path_buf());
        if config.all_features {
            meta.features(CargoOpt::AllFeatures);
        } else {
            if config.no_default_features {
                // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures`
                // https://github.com/oli-obk/cargo_metadata/issues/79
                meta.features(CargoOpt::NoDefaultFeatures);
            }
            if !config.features.is_empty() {
                meta.features(CargoOpt::SomeFeatures(config.features.clone()));
            }
        }
        meta.current_dir(cargo_toml.parent().as_os_str());

        if let Some(target) = target {
            meta.other_options(vec![String::from("--filter-platform"), target]);
        }

        // FIXME: Fetching metadata is a slow process, as it might require
        // calling crates.io. We should be reporting progress here, but it's
        // unclear whether cargo itself supports it.
        progress("metadata".to_string());

        let meta = meta.exec().with_context(|| {
            format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display(),)
        })?;

        Ok(meta)
    }

    pub fn new(mut meta: cargo_metadata::Metadata) -> CargoWorkspace {
        let mut pkg_by_id = FxHashMap::default();
        let mut packages = Arena::default();
        let mut targets = Arena::default();

        let ws_members = &meta.workspace_members;

        meta.packages.sort_by(|a, b| a.id.cmp(&b.id));
        for meta_pkg in &meta.packages {
            let cargo_metadata::Package {
                id, edition, name, manifest_path, version, metadata, ..
            } = meta_pkg;
            let meta = from_value::<PackageMetadata>(metadata.clone()).unwrap_or_default();
            let is_member = ws_members.contains(id);
            let edition = edition.parse::<Edition>().unwrap_or_else(|err| {
                log::error!("Failed to parse edition {}", err);
                Edition::CURRENT
            });

            let pkg = packages.alloc(PackageData {
                id: id.repr.clone(),
                name: name.clone(),
                version: version.clone(),
                manifest: AbsPathBuf::assert(PathBuf::from(&manifest_path)).try_into().unwrap(),
                targets: Vec::new(),
                is_member,
                edition,
                dependencies: Vec::new(),
                features: meta_pkg.features.clone().into_iter().collect(),
                active_features: Vec::new(),
                metadata: meta.rust_analyzer.unwrap_or_default(),
            });
            let pkg_data = &mut packages[pkg];
            pkg_by_id.insert(id, pkg);
            for meta_tgt in &meta_pkg.targets {
                let is_proc_macro = meta_tgt.kind.as_slice() == ["proc-macro"];
                let tgt = targets.alloc(TargetData {
                    package: pkg,
                    name: meta_tgt.name.clone(),
                    root: AbsPathBuf::assert(PathBuf::from(&meta_tgt.src_path)),
                    kind: TargetKind::new(meta_tgt.kind.as_slice()),
                    is_proc_macro,
                });
                pkg_data.targets.push(tgt);
            }
        }
        let resolve = meta.resolve.expect("metadata executed with deps");
        for mut node in resolve.nodes {
            let source = match pkg_by_id.get(&node.id) {
                Some(&src) => src,
                // FIXME: replace this and a similar branch below with `.unwrap`, once
                // https://github.com/rust-lang/cargo/issues/7841
                // is fixed and hits stable (around 1.43-is probably?).
                None => {
                    log::error!("Node id do not match in cargo metadata, ignoring {}", node.id);
                    continue;
                }
            };
            node.deps.sort_by(|a, b| a.pkg.cmp(&b.pkg));
            for (dep_node, kind) in node
                .deps
                .iter()
                .flat_map(|dep| DepKind::iter(&dep.dep_kinds).map(move |kind| (dep, kind)))
            {
                let pkg = match pkg_by_id.get(&dep_node.pkg) {
                    Some(&pkg) => pkg,
                    None => {
                        log::error!(
                            "Dep node id do not match in cargo metadata, ignoring {}",
                            dep_node.pkg
                        );
                        continue;
                    }
                };
                let dep = PackageDependency { name: dep_node.name.clone(), pkg, kind };
                packages[source].dependencies.push(dep);
            }
            packages[source].active_features.extend(node.features);
        }

        let workspace_root =
            AbsPathBuf::assert(PathBuf::from(meta.workspace_root.into_os_string()));

        CargoWorkspace { packages, targets, workspace_root }
    }

    pub fn from_cargo_metadata3(
        cargo_toml: &ManifestPath,
        config: &CargoConfig,
        progress: &dyn Fn(String),
    ) -> Result<CargoWorkspace> {
        let meta = CargoWorkspace::fetch_metadata(cargo_toml, config, progress)?;
        Ok(CargoWorkspace::new(meta))
    }

    pub fn packages<'a>(&'a self) -> impl Iterator<Item = Package> + ExactSizeIterator + 'a {
        self.packages.iter().map(|(id, _pkg)| id)
    }

    pub fn target_by_root(&self, root: &AbsPath) -> Option<Target> {
        self.packages()
            .filter_map(|pkg| self[pkg].targets.iter().find(|&&it| &self[it].root == root))
            .next()
            .copied()
    }

    pub fn workspace_root(&self) -> &AbsPath {
        &self.workspace_root
    }

    pub fn package_flag(&self, package: &PackageData) -> String {
        if self.is_unique(&*package.name) {
            package.name.clone()
        } else {
            format!("{}:{}", package.name, package.version)
        }
    }

    fn is_unique(&self, name: &str) -> bool {
        self.packages.iter().filter(|(_, v)| v.name == name).count() == 1
    }
}

fn rustc_discover_host_triple(cargo_toml: &ManifestPath) -> Option<String> {
    let mut rustc = Command::new(toolchain::rustc());
    rustc.current_dir(cargo_toml.parent()).arg("-vV");
    log::debug!("Discovering host platform by {:?}", rustc);
    match utf8_stdout(rustc) {
        Ok(stdout) => {
            let field = "host: ";
            let target = stdout.lines().find_map(|l| l.strip_prefix(field));
            if let Some(target) = target {
                Some(target.to_string())
            } else {
                // If we fail to resolve the host platform, it's not the end of the world.
                log::info!("rustc -vV did not report host platform, got:\n{}", stdout);
                None
            }
        }
        Err(e) => {
            log::warn!("Failed to discover host platform: {}", e);
            None
        }
    }
}

fn cargo_config_build_target(cargo_toml: &ManifestPath) -> Option<String> {
    let mut cargo_config = Command::new(toolchain::cargo());
    cargo_config
        .current_dir(cargo_toml.parent())
        .args(&["-Z", "unstable-options", "config", "get", "build.target"])
        .env("RUSTC_BOOTSTRAP", "1");
    // if successful we receive `build.target = "target-triple"`
    log::debug!("Discovering cargo config target by {:?}", cargo_config);
    match utf8_stdout(cargo_config) {
        Ok(stdout) => stdout
            .strip_prefix("build.target = \"")
            .and_then(|stdout| stdout.strip_suffix('"'))
            .map(ToOwned::to_owned),
        Err(_) => None,
    }
}
<commit_msg>minor: remove dead code<commit_after>//! See [`CargoWorkspace`].

use std::convert::TryInto;
use std::iter;
use std::path::PathBuf;
use std::{ops, process::Command};

use anyhow::{Context, Result};
use base_db::Edition;
use cargo_metadata::{CargoOpt, MetadataCommand};
use la_arena::{Arena, Idx};
use paths::{AbsPath, AbsPathBuf};
use rustc_hash::FxHashMap;
use serde::Deserialize;
use serde_json::from_value;

use crate::CfgOverrides;
use crate::{utf8_stdout, ManifestPath};

/// [`CargoWorkspace`] represents the logical structure of, well, a Cargo
/// workspace. It pretty closely mirrors `cargo metadata` output.
///
/// Note that internally, rust analyzer uses a different structure:
/// `CrateGraph`. `CrateGraph` is lower-level: it knows only about the crates,
/// while this knows about `Packages` & `Targets`: purely cargo-related
/// concepts.
///
/// We use absolute paths here, `cargo metadata` guarantees to always produce
/// abs paths.
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct CargoWorkspace {
    packages: Arena<PackageData>,
    targets: Arena<TargetData>,
    workspace_root: AbsPathBuf,
}

impl ops::Index<Package> for CargoWorkspace {
    type Output = PackageData;
    fn index(&self, index: Package) -> &PackageData {
        &self.packages[index]
    }
}

impl ops::Index<Target> for CargoWorkspace {
    type Output = TargetData;
    fn index(&self, index: Target) -> &TargetData {
        &self.targets[index]
    }
}

/// Describes how to set the rustc source directory.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum RustcSource {
    /// Explicit path for the rustc source directory.
    Path(AbsPathBuf),
    /// Try to automatically detect where the rustc source directory is.
    Discover,
}

#[derive(Default, Clone, Debug, PartialEq, Eq)]
pub struct CargoConfig {
    /// Do not activate the `default` feature.
    pub no_default_features: bool,

    /// Activate all available features
    pub all_features: bool,

    /// List of features to activate.
    /// This will be ignored if `cargo_all_features` is true.
    pub features: Vec<String>,

    /// rustc target
    pub target: Option<String>,

    /// Don't load sysroot crates (`std`, `core` & friends). Might be useful
    /// when debugging isolated issues.
    pub no_sysroot: bool,

    /// rustc private crate source
    pub rustc_source: Option<RustcSource>,

    /// crates to disable `#[cfg(test)]` on
    pub unset_test_crates: Vec<String>,

    pub wrap_rustc_in_build_scripts: bool,
}

impl CargoConfig {
    pub fn cfg_overrides(&self) -> CfgOverrides {
        self.unset_test_crates
            .iter()
            .cloned()
            .zip(iter::repeat_with(|| {
                cfg::CfgDiff::new(Vec::new(), vec![cfg::CfgAtom::Flag("test".into())]).unwrap()
            }))
            .collect()
    }
}

pub type Package = Idx<PackageData>;

pub type Target = Idx<TargetData>;

/// Information associated with a cargo crate
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PackageData {
    /// Version given in the `Cargo.toml`
    pub version: semver::Version,
    /// Name as given in the `Cargo.toml`
    pub name: String,
    /// Path containing the `Cargo.toml`
    pub manifest: ManifestPath,
    /// Targets provided by the crate (lib, bin, example, test, ...)
    pub targets: Vec<Target>,
    /// Is this package a member of the current workspace
    pub is_member: bool,
    /// List of packages this package depends on
    pub dependencies: Vec<PackageDependency>,
    /// Rust edition for this package
    pub edition: Edition,
    /// Features provided by the crate, mapped to the features required by that feature.
    pub features: FxHashMap<String, Vec<String>>,
    /// List of features enabled on this package
    pub active_features: Vec<String>,
    // String representation of package id
    pub id: String,
    // The contents of [package.metadata.rust-analyzer]
    pub metadata: RustAnalyzerPackageMetaData,
}

#[derive(Deserialize, Default, Debug, Clone, Eq, PartialEq)]
pub struct RustAnalyzerPackageMetaData {
    pub rustc_private: bool,
}

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct PackageDependency {
    pub pkg: Package,
    pub name: String,
    pub kind: DepKind,
}

#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Ord)]
pub enum DepKind {
    /// Available to the library, binary, and dev targets in the package (but not the build script).
    Normal,
    /// Available only to test and bench targets (and the library target, when built with `cfg(test)`).
    Dev,
    /// Available only to the build script target.
    Build,
}

impl DepKind {
    fn iter(list: &[cargo_metadata::DepKindInfo]) -> impl Iterator<Item = Self> + '_ {
        let mut dep_kinds = Vec::new();
        if list.is_empty() {
            dep_kinds.push(Self::Normal);
        }
        for info in list {
            let kind = match info.kind {
                cargo_metadata::DependencyKind::Normal => Self::Normal,
                cargo_metadata::DependencyKind::Development => Self::Dev,
                cargo_metadata::DependencyKind::Build => Self::Build,
                cargo_metadata::DependencyKind::Unknown => continue,
            };
            dep_kinds.push(kind);
        }
        dep_kinds.sort_unstable();
        dep_kinds.dedup();
        dep_kinds.into_iter()
    }
}

/// Information associated with a package's target
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct TargetData {
    /// Package that provided this target
    pub package: Package,
    /// Name as given in the `Cargo.toml` or generated from the file name
    pub name: String,
    /// Path to the main source file of the target
    pub root: AbsPathBuf,
    /// Kind of target
    pub kind: TargetKind,
    /// Is this target a proc-macro
    pub is_proc_macro: bool,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TargetKind {
    Bin,
    /// Any kind of Cargo lib crate-type (dylib, rlib, proc-macro, ...).
    Lib,
    Example,
    Test,
    Bench,
    BuildScript,
    Other,
}

impl TargetKind {
    fn new(kinds: &[String]) -> TargetKind {
        for kind in kinds {
            return match kind.as_str() {
                "bin" => TargetKind::Bin,
                "test" => TargetKind::Test,
                "bench" => TargetKind::Bench,
                "example" => TargetKind::Example,
                "custom-build" => TargetKind::BuildScript,
                "proc-macro" => TargetKind::Lib,
                _ if kind.contains("lib") => TargetKind::Lib,
                _ => continue,
            };
        }
        TargetKind::Other
    }
}

#[derive(Deserialize, Default)]
// Deserialise helper for the cargo metadata
struct PackageMetadata {
    #[serde(rename = "rust-analyzer")]
    rust_analyzer: Option<RustAnalyzerPackageMetaData>,
}

impl CargoWorkspace {
    pub fn fetch_metadata(
        cargo_toml: &ManifestPath,
        config: &CargoConfig,
        progress: &dyn Fn(String),
    ) -> Result<cargo_metadata::Metadata> {
        let target = config
            .target
            .clone()
            .or_else(|| cargo_config_build_target(cargo_toml))
            .or_else(|| rustc_discover_host_triple(cargo_toml));

        let mut meta = MetadataCommand::new();
        meta.cargo_path(toolchain::cargo());
        meta.manifest_path(cargo_toml.to_path_buf());
        if config.all_features {
            meta.features(CargoOpt::AllFeatures);
        } else {
            if config.no_default_features {
                // FIXME: `NoDefaultFeatures` is mutual exclusive with `SomeFeatures`
                // https://github.com/oli-obk/cargo_metadata/issues/79
                meta.features(CargoOpt::NoDefaultFeatures);
            }
            if !config.features.is_empty() {
                meta.features(CargoOpt::SomeFeatures(config.features.clone()));
            }
        }
        meta.current_dir(cargo_toml.parent().as_os_str());

        if let Some(target) = target {
            meta.other_options(vec![String::from("--filter-platform"), target]);
        }

        // FIXME: Fetching metadata is a slow process, as it might require
        // calling crates.io. We should be reporting progress here, but it's
        // unclear whether cargo itself supports it.
        progress("metadata".to_string());

        let meta = meta.exec().with_context(|| {
            format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display(),)
        })?;

        Ok(meta)
    }

    pub fn new(mut meta: cargo_metadata::Metadata) -> CargoWorkspace {
        let mut pkg_by_id = FxHashMap::default();
        let mut packages = Arena::default();
        let mut targets = Arena::default();

        let ws_members = &meta.workspace_members;

        meta.packages.sort_by(|a, b| a.id.cmp(&b.id));
        for meta_pkg in &meta.packages {
            let cargo_metadata::Package {
                id, edition, name, manifest_path, version, metadata, ..
            } = meta_pkg;
            let meta = from_value::<PackageMetadata>(metadata.clone()).unwrap_or_default();
            let is_member = ws_members.contains(id);
            let edition = edition.parse::<Edition>().unwrap_or_else(|err| {
                log::error!("Failed to parse edition {}", err);
                Edition::CURRENT
            });

            let pkg = packages.alloc(PackageData {
                id: id.repr.clone(),
                name: name.clone(),
                version: version.clone(),
                manifest: AbsPathBuf::assert(PathBuf::from(&manifest_path)).try_into().unwrap(),
                targets: Vec::new(),
                is_member,
                edition,
                dependencies: Vec::new(),
                features: meta_pkg.features.clone().into_iter().collect(),
                active_features: Vec::new(),
                metadata: meta.rust_analyzer.unwrap_or_default(),
            });
            let pkg_data = &mut packages[pkg];
            pkg_by_id.insert(id, pkg);
            for meta_tgt in &meta_pkg.targets {
                let is_proc_macro = meta_tgt.kind.as_slice() == ["proc-macro"];
                let tgt = targets.alloc(TargetData {
                    package: pkg,
                    name: meta_tgt.name.clone(),
                    root: AbsPathBuf::assert(PathBuf::from(&meta_tgt.src_path)),
                    kind: TargetKind::new(meta_tgt.kind.as_slice()),
                    is_proc_macro,
                });
                pkg_data.targets.push(tgt);
            }
        }
        let resolve = meta.resolve.expect("metadata executed with deps");
        for mut node in resolve.nodes {
            let source = match pkg_by_id.get(&node.id) {
                Some(&src) => src,
                // FIXME: replace this and a similar branch below with `.unwrap`, once
                // https://github.com/rust-lang/cargo/issues/7841
                // is fixed and hits stable (around 1.43-is probably?).
                None => {
                    log::error!("Node id do not match in cargo metadata, ignoring {}", node.id);
                    continue;
                }
            };
            node.deps.sort_by(|a, b| a.pkg.cmp(&b.pkg));
            for (dep_node, kind) in node
                .deps
                .iter()
                .flat_map(|dep| DepKind::iter(&dep.dep_kinds).map(move |kind| (dep, kind)))
            {
                let pkg = match pkg_by_id.get(&dep_node.pkg) {
                    Some(&pkg) => pkg,
                    None => {
                        log::error!(
                            "Dep node id do not match in cargo metadata, ignoring {}",
                            dep_node.pkg
                        );
                        continue;
                    }
                };
                let dep = PackageDependency { name: dep_node.name.clone(), pkg, kind };
                packages[source].dependencies.push(dep);
            }
            packages[source].active_features.extend(node.features);
        }

        let workspace_root =
            AbsPathBuf::assert(PathBuf::from(meta.workspace_root.into_os_string()));

        CargoWorkspace { packages, targets, workspace_root }
    }

    pub fn packages<'a>(&'a self) -> impl Iterator<Item = Package> + ExactSizeIterator + 'a {
        self.packages.iter().map(|(id, _pkg)| id)
    }

    pub fn target_by_root(&self, root: &AbsPath) -> Option<Target> {
        self.packages()
            .filter_map(|pkg| self[pkg].targets.iter().find(|&&it| &self[it].root == root))
            .next()
            .copied()
    }

    pub fn workspace_root(&self) -> &AbsPath {
        &self.workspace_root
    }

    pub fn package_flag(&self, package: &PackageData) -> String {
        if self.is_unique(&*package.name) {
            package.name.clone()
        } else {
            format!("{}:{}", package.name, package.version)
        }
    }

    fn is_unique(&self, name: &str) -> bool {
        self.packages.iter().filter(|(_, v)| v.name == name).count() == 1
    }
}

fn rustc_discover_host_triple(cargo_toml: &ManifestPath) -> Option<String> {
    let mut rustc = Command::new(toolchain::rustc());
    rustc.current_dir(cargo_toml.parent()).arg("-vV");
    log::debug!("Discovering host platform by {:?}", rustc);
    match utf8_stdout(rustc) {
        Ok(stdout) => {
            let field = "host: ";
            let target = stdout.lines().find_map(|l| l.strip_prefix(field));
            if let Some(target) = target {
                Some(target.to_string())
            } else {
                // If we fail to resolve the host platform, it's not the end of the world.
                log::info!("rustc -vV did not report host platform, got:\n{}", stdout);
                None
            }
        }
        Err(e) => {
            log::warn!("Failed to discover host platform: {}", e);
            None
        }
    }
}

fn cargo_config_build_target(cargo_toml: &ManifestPath) -> Option<String> {
    let mut cargo_config = Command::new(toolchain::cargo());
    cargo_config
        .current_dir(cargo_toml.parent())
        .args(&["-Z", "unstable-options", "config", "get", "build.target"])
        .env("RUSTC_BOOTSTRAP", "1");
    // if successful we receive `build.target = "target-triple"`
    log::debug!("Discovering cargo config target by {:?}", cargo_config);
    match utf8_stdout(cargo_config) {
        Ok(stdout) => stdout
            .strip_prefix("build.target = \"")
            .and_then(|stdout| stdout.strip_suffix('"'))
            .map(ToOwned::to_owned),
        Err(_) => None,
    }
}
<|endoftext|>


<commit_before>use std::env;
use std::path::PathBuf;

use clap::{App, Arg, ArgMatches, AppSettings};

use prelude::*;
use config::Config;
use utils::ArgExt;
use api::{Api, NewRelease};
use sourcemaputils::SourceMapProcessor;

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b> {
    app.about("uploads react-native projects from within a gradle build step")
        // we intentionally hide this command because for all intents and purposes
        // the user should not know it exists.  It's invoked exclusively by the
        // gradle build step in react-native.
        .setting(AppSettings::Hidden)
        .org_project_args()
        .arg(Arg::with_name("sourcemap")
             .long("sourcemap")
             .value_name("PATH")
             .required(true)
             .help("The path to the sourcemap that should be uploaded"))
        .arg(Arg::with_name("bundle")
             .long("bundle")
             .value_name("PATH")
             .required(true)
             .help("The path to the bundle that should be uploaded"))
        .arg(Arg::with_name("release")
             .long("release")
             .value_name("RELEASE")
             .required(true)
             .help("The name of the release to publish."))
        .arg(Arg::with_name("dist")
             .long("distribution")
             .value_name("DISTRIBUTION")
             .required(true)
             .multiple(true)
             .number_of_values(1)
             .help("The names of the distirbutions to publish. Can be supplied multiple times."))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> Result<()> {
    let (org, project) = config.get_org_and_project(matches)?;
    let api = Api::new(config);
    let base = env::current_dir()?;

    let sourcemap_path = PathBuf::from(matches.value_of("sourcemap").unwrap());
    let bundle_path = PathBuf::from(matches.value_of("bundle").unwrap());
    let sourcemap_url = format!("~/{}", sourcemap_path.file_name().unwrap().to_string_lossy());
    let bundle_url = format!("~/{}", bundle_path.file_name().unwrap().to_string_lossy());

    println!("Processing react-native sourcemaps for Sentry upload.");
    info!("  bundle path: {}", bundle_path.display());
    info!("  sourcemap path: {}", sourcemap_path.display());

    let mut processor = SourceMapProcessor::new(matches.is_present("verbose"));
    processor.add(&bundle_url, &bundle_path)?;
    processor.add(&sourcemap_url, &sourcemap_path)?;
    processor.rewrite(&vec![base.parent().unwrap().to_str().unwrap()])?;
    processor.add_sourcemap_references()?;

    let release = api.new_release(&org, &NewRelease {
        version: matches.value_of("release").unwrap().to_string(),
        projects: vec![project.to_string()],
        ..Default::default()
    })?;

    for dist in matches.values_of("dist").unwrap() {
        println!("Uploading sourcemaps for release {} distribution {}",
                 &release.version, dist);
        processor.upload(&api, &org, Some(&project), &release.version, Some(dist))?;
    }

    Ok(())
}
<commit_msg>distribution -> dist<commit_after>use std::env;
use std::path::PathBuf;

use clap::{App, Arg, ArgMatches, AppSettings};

use prelude::*;
use config::Config;
use utils::ArgExt;
use api::{Api, NewRelease};
use sourcemaputils::SourceMapProcessor;

pub fn make_app<'a, 'b: 'a>(app: App<'a, 'b>) -> App<'a, 'b> {
    app.about("uploads react-native projects from within a gradle build step")
        // we intentionally hide this command because for all intents and purposes
        // the user should not know it exists.  It's invoked exclusively by the
        // gradle build step in react-native.
        .setting(AppSettings::Hidden)
        .org_project_args()
        .arg(Arg::with_name("sourcemap")
             .long("sourcemap")
             .value_name("PATH")
             .required(true)
             .help("The path to the sourcemap that should be uploaded"))
        .arg(Arg::with_name("bundle")
             .long("bundle")
             .value_name("PATH")
             .required(true)
             .help("The path to the bundle that should be uploaded"))
        .arg(Arg::with_name("release")
             .long("release")
             .value_name("RELEASE")
             .required(true)
             .help("The name of the release to publish."))
        .arg(Arg::with_name("dist")
             .long("dist")
             .value_name("DISTRIBUTION")
             .required(true)
             .multiple(true)
             .number_of_values(1)
             .help("The names of the distirbutions to publish. Can be supplied multiple times."))
}

pub fn execute<'a>(matches: &ArgMatches<'a>, config: &Config) -> Result<()> {
    let (org, project) = config.get_org_and_project(matches)?;
    let api = Api::new(config);
    let base = env::current_dir()?;

    let sourcemap_path = PathBuf::from(matches.value_of("sourcemap").unwrap());
    let bundle_path = PathBuf::from(matches.value_of("bundle").unwrap());
    let sourcemap_url = format!("~/{}", sourcemap_path.file_name().unwrap().to_string_lossy());
    let bundle_url = format!("~/{}", bundle_path.file_name().unwrap().to_string_lossy());

    println!("Processing react-native sourcemaps for Sentry upload.");
    info!("  bundle path: {}", bundle_path.display());
    info!("  sourcemap path: {}", sourcemap_path.display());

    let mut processor = SourceMapProcessor::new(matches.is_present("verbose"));
    processor.add(&bundle_url, &bundle_path)?;
    processor.add(&sourcemap_url, &sourcemap_path)?;
    processor.rewrite(&vec![base.parent().unwrap().to_str().unwrap()])?;
    processor.add_sourcemap_references()?;

    let release = api.new_release(&org, &NewRelease {
        version: matches.value_of("release").unwrap().to_string(),
        projects: vec![project.to_string()],
        ..Default::default()
    })?;

    for dist in matches.values_of("dist").unwrap() {
        println!("Uploading sourcemaps for release {} distribution {}",
                 &release.version, dist);
        processor.upload(&api, &org, Some(&project), &release.version, Some(dist))?;
    }

    Ok(())
}
<|endoftext|>