<commit_before>#![allow(dead_code)]

use super::events::*;
use super::events::append_entries::{AppendEntriesReq, AppendEntriesRes};
use super::events::{VoteReq, VoteRes};
use super::follower::Follower;   // A trait with impl for RaftServerState
use super::candidate::Candidate; // A trait with impl for RaftServerState
use super::leader::Leader;       // A trait with impl for RaftServerState

use std::comm::*;
use std::io::timer::Timer;
use std::vec::Vec;

// Some kind of Idea for how the whole thing works:
//
// The Raft task in this diagram denotes the task started by
// RaftServer#run() - it contains the local raft state machine.
//
// Then it communicates with 3 other kinds of task via channels
//
// 1. the Raft Peer tasks - these are a set of tasks, one per other
//    peer, which specifically handle all messages relating to RPC
//    between the current peer and the other peer.
//
// 2. the Application State Machine task - This is the
//    strongly-consistent replicated state machine that is custom
//    per-application. It recieves messages as they are committed to
//    the log.
//
// 3. the Application Endpoint tasks- This is the set of tasks that
//    handle requests from Application clients, which have to go
//    through Raft to get to the Application State Machine.
//
//
//    +task-----------+
//    |  Application  |
//    |  Replicated   |
//    |     State     |
//    |    Machine    |
//    |       ^       |
//    +---------------+
//            |
//            |<-- RaftAppMsg<AppMsg>
//            |
//            |         RaftPeerRPC<AppMsg>
//    +task---+-------+    |         -------
//    |       v       |    |      --/       \--
//    |               |    v     /             \
//    |     Raft     <+----------+>   Peer     |
//    |               |          \    Tasks    /
//    |       ^       |           --\       /--
//    +-------+-------+              -------
//            |
//            |<-- RaftAppMsg<AppMsg>
//         ---+---
//      --/   v   \--
//     /  Endpoint   \
//     |    Tasks    |
//     \             /
//      --\   ^   /--
//         ---+---
//            |
//            |
//            v
//       Application
//         Clients
//

// TODO: Parameterise by <AppMsg>, the type of messages that the app
// uses
pub struct RaftServer {
    election_timeout:  u64,
    heartbeat_interval: u64,

    // TODO: store peers... somehow
    peer_configs: Vec<()>,
}

// static duplex to Application State Machine (from somewhere else)
// static reciever from Application Endpoint  (
// static reciever from Peer

// Some ideas of how to use with Application Tasks:
//
// let (to_app_send, to_app_rec) = channel();
// let (from_app_send, from_app_rec) = channel();
//
// spawn_app_task(to_app_rec, from_app_send);
//
// let (from_endpoint_send, from_endpoint_rec) = channel();
//
// spawn_main_app_endpoint_task(from_endpoint_send);
//
// rs = RaftServer::new(...opts...); // TODO
// rs.add_peer(...peercfg...); // TODO
// RaftServer::spawn(rs, to_app_send, from_app_rec, from_endpoint_rec);
//

impl RaftServer {
    pub fn new() -> RaftServer {
        let election_timeout = 150;

        RaftServer {
            election_timeout:  election_timeout,
            heartbeat_interval: (election_timeout/2),
            peer_configs:      Vec::new(),
        }
    }

    // TODO: Add Peers
    pub fn add_peer() -> bool {
        false
    }

    // TODO: Spawn Peers
    pub fn spawn_peer_tasks(&mut self, sender: Sender<RaftMsg>) -> Vec<()> {
        Vec::new()
    }

    pub fn spawn(&mut self,
                to_app_sm:         Sender<(ClientCmdReq, Sender<ClientCmdRes>)>,
                from_app_endpoint: Receiver<(ClientCmdReq, Sender<ClientCmdRes>)>) {

        let (from_peers_send, from_peers_rec) = channel();
        let peers = self.spawn_peer_tasks(from_peers_send);

        let heartbeat_interval = self.heartbeat_interval;

        spawn(proc() {

            let mut server_state = RaftServerState::new(RaftFollower,
                                                        to_app_sm,
                                                        peers);

            let mut timer = Timer::new().unwrap();
            let timer_rec : Receiver<()> = timer.periodic(heartbeat_interval);

            // some other way to encapsulate self?
            server_state.main_loop(&timer_rec,
                                   &from_peers_rec,
                                   &from_app_endpoint)
        });
    }
}

pub struct RaftServerState {
    current_state: RaftNextState,
    is_setup:      bool,

    to_app_sm:     Sender<(ClientCmdReq, Sender<ClientCmdRes>)>,

    peers:         Vec<()>,
}

#[deriving(Eq,Clone,Show)]
pub enum RaftNextState {
    RaftLeader,
    RaftCandidate,
    RaftFollower
}

#[deriving(Eq,Clone,Show)]
pub enum RaftStateTransition {
    NextState(RaftNextState),
    Continue,
    Stop
}

// Unfortunately Rust can't generate method names,
// so your code has to do it.
//
// Use this like so:
//
// state_proxy!(leader_handle_setup,
//              candidate_handle_setup,
//              follower_handle_setup);
//
// or:
//
// state_proxy!(leader_handle_setup,
//              candidate_handle_setup,
//              follower_handle_setup,
//              event);

macro_rules! state_proxy(
    ($l:ident, $c:ident, $f:ident) => {
        match self.current_state {
            RaftLeader => self.$l(),
            RaftCandidate => self.$c(),
            RaftFollower => self.$f(),
        }
    };
    ($l:ident, $c:ident, $f:ident, $e:ident) => {
        match self.current_state {
            RaftLeader => self.$l($e),
            RaftCandidate => self.$c($e),
            RaftFollower => self.$f($e),
        }
    };
    ($l:ident, $c:ident, $f:ident, $e:ident, $s:ident) => {
        match self.current_state {
            RaftLeader => self.$l($e, $s),
            RaftCandidate => self.$c($e, $s),
            RaftFollower => self.$f($e, $s),
        }
    };
)

impl RaftServerState {
    fn new(current_state: RaftNextState,
           to_app_sm: Sender<(ClientCmdReq, Sender<ClientCmdRes>)>,
           peers: Vec<()>) -> RaftServerState {
        RaftServerState {
            current_state: current_state,
            is_setup: false,
            to_app_sm: to_app_sm,
            peers: peers,
        }
    }

    fn new_state(&mut self, new_state: RaftNextState) {
        self.current_state = new_state;
        self.is_setup = false;
    }

    fn main_loop(&mut self,
                 timer_rec: &Receiver<()>,
                 peer_rec:  &Receiver<RaftMsg>,
                 endpoint_rec: &Receiver<(ClientCmdReq, Sender<ClientCmdRes>)>) {

        // Use every time an invocation may transition the state machine
        // Macro Guide: http://static.rust-lang.org/doc/master/guide-macros.html
        macro_rules! may_transition (
            ($e:expr) => (
                match $e {
                    NextState(new_state) => {
                        debug!("Trans {:?} ==> {:?}", self.current_state, new_state);

                        self.handle_teardown();

                        self.new_state(new_state);

                        continue;
                    },
                    Stop => {
                        debug!("Stop {:?} ==> ()", self.current_state);

                        self.handle_teardown();

                        break;
                    },
                    Continue => {}
                }
            )
        );

        let select   = Select::new();
        let mut timer_handle    = select.handle(timer_rec);
        let mut peer_handle     = select.handle(peer_rec);
        let mut endpoint_handle = select.handle(endpoint_rec);

        unsafe {
            timer_handle.add();
            peer_handle.add();
            endpoint_handle.add();
        }

        loop {
            may_transition!(self.handle_setup());

            let ready_id = select.wait();
            if timer_handle.id() == ready_id {
                timer_handle.recv();
                may_transition!(self.handle_heartbeat());
            }
            else if peer_handle.id() == ready_id {
                // An Event Message from a Peer
                let event: RaftMsg = peer_handle.recv();
                match event {
                    ARQ(ae_req, ae_chan) =>
                        may_transition!(self.handle_append_entries_req(ae_req, ae_chan)),
                    ARS(ae_res) =>
                        may_transition!(self.handle_append_entries_res(ae_res)),
                    VRQ(vote_req, vote_chan) =>
                        may_transition!(self.handle_vote_req(vote_req, vote_chan)),
                    VRS(vote_res) =>
                        may_transition!(self.handle_vote_res(vote_res)),
                    StopReq => {
                        may_transition!(Stop);
                    }
                }
            }
            else if endpoint_handle.id() == ready_id {
                // An Event Message from an Endpoint
                let (req, chan) = endpoint_handle.recv();
                may_transition!(self.handle_application_req(req, chan));
            }
        }

        unsafe {
            timer_handle.remove();
            peer_handle.remove();
            endpoint_handle.remove();
        }
    }

    //
    // Event handlers (called from main_loop(...))
    fn handle_setup(&mut self) -> RaftStateTransition {
        if !self.is_setup {
            let res = state_proxy!(leader_setup,
                                   candidate_setup,
                                   follower_setup);
            self.is_setup = true;
            res
        }
        else {
            Continue
        }
    }

    fn handle_teardown(&mut self) {
        state_proxy!(leader_teardown,
                     candidate_teardown,
                     follower_teardown)
    }

    // This is called every heartbeat_interval msecs. I believe it
    // should only be used by the leader, but I could be wrong.
    fn handle_heartbeat(&mut self) -> RaftStateTransition {
        if self.is_leader() {
            self.leader_heartbeat()
        }
        else {
            Continue
        }
    }

    fn handle_append_entries_req(&mut self, req: AppendEntriesReq, chan: Sender<AppendEntriesRes>) -> RaftStateTransition {
        state_proxy!(leader_append_entries_req,
                     candidate_append_entries_req,
                     follower_append_entries_req,
                     req, chan)
    }

    fn handle_append_entries_res(&mut self, res: AppendEntriesRes) -> RaftStateTransition {
        state_proxy!(leader_append_entries_res,
                     candidate_append_entries_res,
                     follower_append_entries_res,
                     res)
    }

    fn handle_vote_req(&mut self, req: VoteReq, chan: Sender<VoteRes>) -> RaftStateTransition {
        state_proxy!(leader_vote_req,
                     candidate_vote_req,
                     follower_vote_req,
                     req, chan)
    }

    fn handle_vote_res(&mut self, res: VoteRes) -> RaftStateTransition {
        state_proxy!(leader_vote_res,
                     candidate_vote_res,
                     follower_vote_res,
                     res)
    }

    // In these, it's probably just easier to call the functions
    // in the Leader trait directly.
    fn handle_application_req(&mut self, req: ClientCmdReq, chan: Sender<ClientCmdRes>) -> RaftStateTransition {
        Continue
        // if self.is_leader() {
        //     pass to application state machine
        // }
        // else {
        //     reply with info on how to talk to the leader
        // }
    }

    //
    // Generic Helper Methods
    //

    fn is_leader(&self) -> bool {
        self.current_state == RaftLeader
    }
}
<commit_msg>WIP locking state machine<commit_after>#![allow(dead_code)]

use super::events::*;
use super::events::append_entries::{AppendEntriesReq, AppendEntriesRes};
use super::events::{VoteReq, VoteRes};
use super::follower::Follower;   // A trait with impl for RaftServerState
use super::candidate::Candidate; // A trait with impl for RaftServerState
use super::leader::Leader;       // A trait with impl for RaftServerState

use std::comm::*;
use std::io::timer::Timer;
use std::vec::Vec;

// Some kind of Idea for how the whole thing works:
//
// The Raft task in this diagram denotes the task started by
// RaftServer#run() - it contains the local raft state machine.
//
// Then it communicates with 3 other kinds of task via channels
//
// 1. the Raft Peer tasks - these are a set of tasks, one per other
//    peer, which specifically handle all messages relating to RPC
//    between the current peer and the other peer.
//
// 2. the Application State Machine task - This is the
//    strongly-consistent replicated state machine that is custom
//    per-application. It recieves messages as they are committed to
//    the log.
//
// 3. the Application Endpoint tasks- This is the set of tasks that
//    handle requests from Application clients, which have to go
//    through Raft to get to the Application State Machine.
//
//
//    +task-----------+
//    |  Application  |
//    |  Replicated   |
//    |     State     |
//    |    Machine    |
//    |       ^       |
//    +---------------+
//            |
//            |<-- RaftAppMsg<AppMsg>
//            |
//            |         RaftPeerRPC<AppMsg>
//    +task---+-------+    |         -------
//    |       v       |    |      --/       \--
//    |               |    v     /             \
//    |     Raft     <+----------+>   Peer     |
//    |               |          \    Tasks    /
//    |       ^       |           --\       /--
//    +-------+-------+              -------
//            |
//            |<-- RaftAppMsg<AppMsg>
//         ---+---
//      --/   v   \--
//     /  Endpoint   \
//     |    Tasks    |
//     \             /
//      --\   ^   /--
//         ---+---
//            |
//            |
//            v
//       Application
//         Clients
//

// TODO: Parameterise by <AppMsg>, the type of messages that the app
// uses
pub struct RaftServer {
    election_timeout:  u64,
    heartbeat_interval: u64,

    // TODO: store peers... somehow
    peer_configs: Vec<()>,
}

// static duplex to Application State Machine (from somewhere else)
// static reciever from Application Endpoint  (
// static reciever from Peer

// Some ideas of how to use with Application Tasks:
//
// let (to_app_send, to_app_rec) = channel();
// let (from_app_send, from_app_rec) = channel();
//
// spawn_app_task(to_app_rec, from_app_send);
//
// let (from_endpoint_send, from_endpoint_rec) = channel();
//
// spawn_main_app_endpoint_task(from_endpoint_send);
//
// rs = RaftServer::new(...opts...); // TODO
// rs.add_peer(...peercfg...); // TODO
// RaftServer::spawn(rs, to_app_send, from_app_rec, from_endpoint_rec);
//

impl RaftServer {
    pub fn new() -> RaftServer {
        let election_timeout = 150;

        RaftServer {
            election_timeout:  election_timeout,
            heartbeat_interval: (election_timeout/2),
            peer_configs:      Vec::new(),
        }
    }

    // TODO: Add Peers
    pub fn add_peer() -> bool {
        false
    }

    // TODO: Spawn Peers
    pub fn spawn_peer_tasks(&mut self, sender: Sender<RaftMsg>) -> Vec<()> {
        Vec::new()
    }

    pub fn spawn(&mut self,
                to_app_sm:         Sender<(ClientCmdReq, Sender<ClientCmdRes>)>,
                from_app_endpoint: Receiver<(ClientCmdReq, Sender<ClientCmdRes>)>) {

        let (from_peers_send, from_peers_rec) = channel();
        let peers = self.spawn_peer_tasks(from_peers_send);

        let heartbeat_interval = self.heartbeat_interval;

        spawn(proc() {

            let mut server_state = RaftServerState::new(RaftFollower,
                                                        to_app_sm,
                                                        peers);

            let mut timer = Timer::new().unwrap();
            let timer_rec : Receiver<()> = timer.periodic(heartbeat_interval);

            // some other way to encapsulate self?
            server_state.main_loop(&timer_rec,
                                   &from_peers_rec,
                                   &from_app_endpoint)
        });
    }
}

pub struct RaftServerState {
    current_state: RaftNextState,
    is_setup:      bool,

    to_app_sm:     Sender<(ClientCmdReq, Sender<ClientCmdRes>)>,

    peers:         Vec<()>,
}

#[deriving(Eq,Clone,Show)]
pub enum RaftNextState {
    RaftLeader,
    RaftCandidate,
    RaftFollower
}

#[deriving(Eq,Clone,Show)]
pub enum RaftStateTransition {
    NextState(RaftNextState),
    Continue,
    Stop
}

// Unfortunately Rust can't generate method names,
// so your code has to do it.
//
// Use this like so:
//
// state_proxy!(leader_handle_setup,
//              candidate_handle_setup,
//              follower_handle_setup);
//
// or:
//
// state_proxy!(leader_handle_setup,
//              candidate_handle_setup,
//              follower_handle_setup,
//              event);

macro_rules! state_proxy(
    ($l:ident, $c:ident, $f:ident) => {
        match self.current_state {
            RaftLeader => self.$l(),
            RaftCandidate => self.$c(),
            RaftFollower => self.$f(),
        }
    };
    ($l:ident, $c:ident, $f:ident, $e:ident) => {
        match self.current_state {
            RaftLeader => self.$l($e),
            RaftCandidate => self.$c($e),
            RaftFollower => self.$f($e),
        }
    };
    ($l:ident, $c:ident, $f:ident, $e:ident, $s:ident) => {
        match self.current_state {
            RaftLeader => self.$l($e, $s),
            RaftCandidate => self.$c($e, $s),
            RaftFollower => self.$f($e, $s),
        }
    };
)

impl RaftServerState {
    fn new(current_state: RaftNextState,
           to_app_sm: Sender<(ClientCmdReq, Sender<ClientCmdRes>)>,
           peers: Vec<()>) -> RaftServerState {
        RaftServerState {
            current_state: current_state,
            is_setup: false,
            to_app_sm: to_app_sm,
            peers: peers,
        }
    }

    fn new_state(&mut self, new_state: RaftNextState) {
        self.current_state = new_state;
        self.is_setup = false;
    }

    fn main_loop(&mut self,
                 timer_rec: &Receiver<()>,
                 peer_rec:  &Receiver<RaftMsg>,
                 endpoint_rec: &Receiver<(ClientCmdReq, Sender<ClientCmdRes>)>) {

        // Use every time an invocation may transition the state machine
        // Macro Guide: http://static.rust-lang.org/doc/master/guide-macros.html
        macro_rules! may_transition (
            ($e:expr) => (
                match $e {
                    NextState(new_state) => {
                        debug!("Trans {:?} ==> {:?}", self.current_state, new_state);

                        self.handle_teardown();

                        self.new_state(new_state);

                        continue;
                    },
                    Stop => {
                        debug!("Stop {:?} ==> ()", self.current_state);

                        self.handle_teardown();

                        break;
                    },
                    Continue => {}
                }
            )
        );

        let select   = Select::new();
        let mut timer_handle    = select.handle(timer_rec);
        let mut peer_handle     = select.handle(peer_rec);
        let mut endpoint_handle = select.handle(endpoint_rec);

        unsafe {
            timer_handle.add();
            peer_handle.add();
            endpoint_handle.add();
        }

        loop {
            may_transition!(self.handle_setup());

            let ready_id = select.wait();
            if timer_handle.id() == ready_id {
                timer_handle.recv();
                may_transition!(self.handle_heartbeat());
            }
            else if peer_handle.id() == ready_id {
                // An Event Message from a Peer
                let event: RaftMsg = peer_handle.recv();
                match event {
                    ARQ(ae_req, ae_chan) =>
                        may_transition!(self.handle_append_entries_req(ae_req, ae_chan)),
                    ARS(ae_res) =>
                        may_transition!(self.handle_append_entries_res(ae_res)),
                    VRQ(vote_req, vote_chan) =>
                        may_transition!(self.handle_vote_req(vote_req, vote_chan)),
                    VRS(vote_res) =>
                        may_transition!(self.handle_vote_res(vote_res)),
                    StopReq => {
                        may_transition!(Stop);
                    }
                }
            }
            else if endpoint_handle.id() == ready_id {
                // An Event Message from an Endpoint
                let (req, chan) = endpoint_handle.recv();
                may_transition!(self.handle_application_req(req, chan));
            }
        }

        unsafe {
            timer_handle.remove();
            peer_handle.remove();
            endpoint_handle.remove();
        }
    }

    //
    // Event handlers (called from main_loop(...))
    fn handle_setup(&mut self) -> RaftStateTransition {
        if !self.is_setup {
            let res = state_proxy!(leader_setup,
                                   candidate_setup,
                                   follower_setup);
            self.is_setup = true;
            res
        }
        else {
            Continue
        }
    }

    fn handle_teardown(&mut self) {
        state_proxy!(leader_teardown,
                     candidate_teardown,
                     follower_teardown)
    }

    // This is called every heartbeat_interval msecs. I believe it
    // should only be used by the leader, but I could be wrong.
    fn handle_heartbeat(&mut self) -> RaftStateTransition {
        if self.is_leader() {
            self.leader_heartbeat()
        }
        else {
            Continue
        }
    }

    fn handle_append_entries_req(&mut self, req: AppendEntriesReq, chan: Sender<AppendEntriesRes>) -> RaftStateTransition {
        state_proxy!(leader_append_entries_req,
                     candidate_append_entries_req,
                     follower_append_entries_req,
                     req, chan)
    }

    fn handle_append_entries_res(&mut self, res: AppendEntriesRes) -> RaftStateTransition {
        state_proxy!(leader_append_entries_res,
                     candidate_append_entries_res,
                     follower_append_entries_res,
                     res)
    }

    fn handle_vote_req(&mut self, req: VoteReq, chan: Sender<VoteRes>) -> RaftStateTransition {
        state_proxy!(leader_vote_req,
                     candidate_vote_req,
                     follower_vote_req,
                     req, chan)
    }

    fn handle_vote_res(&mut self, res: VoteRes) -> RaftStateTransition {
        state_proxy!(leader_vote_res,
                     candidate_vote_res,
                     follower_vote_res,
                     res)
    }

    // In these, it's probably just easier to call the functions
    // in the Leader trait directly.
    fn handle_application_req(&mut self, req: ClientCmdReq, chan: Sender<ClientCmdRes>) -> RaftStateTransition {
        Continue
        // if self.is_leader() {
        //     pass to application state machine
        // }
        // else {
        //     reply with info on how to talk to the leader
        // }
    }

    //
    // Generic Helper Methods
    //

    fn is_leader(&self) -> bool {
        self.current_state == RaftLeader
    }

}

// STATE MACHINE
/* NOTES
    pass as <~str>
    LockReq -> LockResp(bool, id)  //using Option<int>
    UnlockReq(<id>) -> UnlockResp(bool)

loop {
next_msg = Rec(Msg).recv();
let mut state = Option<id>;
match state {
    None => state = Unlocked;
    Some<id> => state = Locked(id: ---)
}
*/

pub enum State {
    Locked,
    Unlocked
}
pub struct Locked {
    locked: bool,
    state: Option<int>,
    id: Option<int>
}

pub struct Unlocked {
    unlocked: bool,
    state: Option<int>,
    id: Option<int>
}

pub struct LockRes {
    new_state: Option<State>,
    status: bool,
    id: Option<int>
}

pub struct UnlockRes {
    new_state: Option<State>,
    status: bool,
    id: Option<int>
}

/*
impl Unlocked {

    fn lock_request(&mut self) -> LockRes {
        if self.unlocked {
            //update with some deterministic but RANDOM NUMBER
            let result = LockRes { new_state: Some(Locked), status: true, id: Some(1) };
            //- send lock msg on a Chan
            //- send "true" and <id> on Chan
        }

        else if !self.unlocked {
            //already locked do nothing
        }
    }

    fn unlock_request(&mut self) -> UnlockRes {
        if self.unlocked {
            //already unlocked
            }
        // else if !self.locked {
        //     Continue //already unlocked do nothing
        // }
    }
}

impl Locked {

    fn unlock_request(&mut self) -> UnlockRes {
        if self.locked {
            match self.id {
                //if unlock request (but different lock <id>) continue / do nothing
                //if unlock request (with same <id>) send unlock msg on Chan + "true" and <id> on Chan
                None => Unlocked,
                Some(id) => Locked,

            }

            let result = UnlockRes{new_state: Some(Unlocked), status: true, id: None};
            result
        }

        else if !self.locked {
            //already unlocked do nothing
        }
    }

    fn lock_request(&mut self) -> LockRes {
        if self.locked {
            //already locked
        }

        // else if !self.locked {
        //     Continue //already locked do nothing
        // }
    }
}
*/

<|endoftext|>


<commit_before>
extern crate rustfmt_nightly;
extern crate difference;
extern crate regex;

use difference::Changeset;
use rustfmt_nightly as rustfmt;

use std::fs;
use std::io::Read;

// Given the default Rust test runner doesn't expose programmatic test cases
// we are using single "check_expansions" test to process all the data files.
//
// This is similar approach to what rustfmt does.

#[test]
fn check_expansions() {

    // Get the source test data files.
    let test_data = fs::read_dir( "tests/data" ).unwrap();
    let source_paths = test_data
            .into_iter()
            .map( |e| e.expect("Failed to read entry").path() )
            .map( |p| p.to_str().unwrap().to_owned() )
            .filter( |p| p.ends_with( ".source.rs" ) )
            .collect::<Vec<_>>();

    // Process each source file. Track the failures.
    let mut failed = 0;
    for source_path in source_paths {

        // Construct the target file path by replacing the ".source.rs" with a
        // ".target.rs". There's a small discrepancy here as the .source.rs had
        // to be at the end for the file to count as source file, but here
        // we are replacing the .target. everywhere in the file name.
        //
        // This shouldn't matter in practice as these are test files and we can
        // decide on their naming as we write them.
        let mut target_file = fs::File::open( source_path.replace(
                ".source.rs",
                ".target.rs" ) ).unwrap();

        // Get the source and target code.
        //
        // The source is compiled using rustc and the target is just read
        // from the disk.
        let mut source_code = build( &source_path );
        let mut target_code = String::new();
        target_file.read_to_string( &mut target_code )
                    .expect( "Failed to read target" );

        // Generate diffs for both sources.
        //
        // Use rustfmt to format both pieces of code so that we have a
        // canonical format for them. Without rustfmt we'd need to match the
        // compiler pretty print format in the reference target files - which,
        // despite its name, isn't very pretty.
        let changeset = Changeset::new(
                &format( source_code.trim() ),
                &format( target_code.trim() ),
                "\n" );

        // If these were equal, there's only one "Same" diff segment.
        // If there is more than one, they differed.
        if changeset.diffs.len() > 1 {

            // Print the changeset for debugging purposes and increment the
            // amount of failed items. By default this prints nice colored diff.
            println!( "{}", changeset );
            failed += 1;
        }
    }

    // Ensure there were no failures.
    //
    // If we fail here, cargo will display our printlns to the user.
    assert_eq!( failed, 0, "{} tests failed", failed );
}

/// Compiles a single file using rustc using similar options than what
/// cargo would have used.
fn build( path : &str ) -> String {

    // Launch rustc.
    let output = std::process::Command::new( "rustc" )
            .args( &[
                "--crate-name", "source",
                "--crate-type", "lib",
                path,
                "--out-dir", "tests/out",
                "-L", "dependency=../target/debug/deps",
                "--extern", "intercom=../target/debug/libintercom.rlib",
                "--pretty=expanded",
                "-Z", "unstable-options",
            ] )
            .output()
            .expect( "Failed to execute" );

    // Ensure the compilation was successful.
    if ! output.status.success() {
        println!( "FAILED TO COMPILE SOURCE {}", path );
        panic!( format!( "{}", String::from_utf8( output.stderr ).unwrap() ) );
    }

    // stdout is utf8 byte stream. Parse it into a string.
    String::from_utf8( output.stdout ).expect( "Bad output" )
}

/// Removes comments from the code.
fn strip_comments( code : &str ) -> String {
    let re = regex::Regex::new( r"//.*" ).expect( "Bad regex" );
    re.replace_all( code, "" ).into_owned()
}

fn format( code : &str ) -> String {

    // Strip comments. This allows us to embed comments in the target files
    // without requiring the attributes to expand these comments.
    let code = strip_comments( code );

    // Use default config but instead of altering the source/target files just
    // "display" the formatted code. This results in the output being available
    // in the 'out' parameter.
    let mut config = rustfmt::config::Config::default();
    config.override_value( "write_mode", "Display" );

    let mut out : Vec<u8> = vec![];
    rustfmt::format_input(
            rustfmt::Input::Text( code ),
            &config,
            Some( &mut out ) ).expect( "Failed to format" );

    // Convert the UTF-8 output into a string.
    String::from_utf8( out ).expect( "Bad output" )
}
<commit_msg>Try fixing AppVeyor test breakage<commit_after>
extern crate rustfmt_nightly;
extern crate difference;
extern crate regex;

use difference::Changeset;
use rustfmt_nightly as rustfmt;

use std::fs;
use std::io::Read;

// Given the default Rust test runner doesn't expose programmatic test cases
// we are using single "check_expansions" test to process all the data files.
//
// This is similar approach to what rustfmt does.

#[test]
fn check_expansions() {

    // Get the source test data files.
    let test_data = fs::read_dir( "tests/data" ).unwrap();
    let source_paths = test_data
            .into_iter()
            .map( |e| e.expect("Failed to read entry").path() )
            .map( |p| p.to_str().unwrap().to_owned() )
            .filter( |p| p.ends_with( ".source.rs" ) )
            .collect::<Vec<_>>();

    // Process each source file. Track the failures.
    let mut failed = 0;
    for source_path in source_paths {

        // Construct the target file path by replacing the ".source.rs" with a
        // ".target.rs". There's a small discrepancy here as the .source.rs had
        // to be at the end for the file to count as source file, but here
        // we are replacing the .target. everywhere in the file name.
        //
        // This shouldn't matter in practice as these are test files and we can
        // decide on their naming as we write them.
        let mut target_file = fs::File::open( source_path.replace(
                ".source.rs",
                ".target.rs" ) ).unwrap();

        // Get the source and target code.
        //
        // The source is compiled using rustc and the target is just read
        // from the disk.
        let mut source_code = build( &source_path );
        let mut target_code = String::new();
        target_file.read_to_string( &mut target_code )
                    .expect( "Failed to read target" );

        // Generate diffs for both sources
        // Ensure the linebreaks are the same for both. This seems to be
        // somewhat of an issue on AppVeyor.
        target = target.replace( "\r", "" );
        source = source.replace( "\r", "" );.

        //
        // Use rustfmt to format both pieces of code so that we have a
        // canonical format for them. Without rustfmt we'd need to match the
        // compiler pretty print format in the reference target files - which,
        // despite its name, isn't very pretty.
        let changeset = Changeset::new(
                &format( source_code.trim() ),
                &format( target_code.trim() ),
                "\n" );

        // If these were equal, there's only one "Same" diff segment.
        // If there is more than one, they differed.
        if changeset.diffs.len() > 1 {

            // Print the changeset for debugging purposes and increment the
            // amount of failed items. By default this prints nice colored diff.
            println!( "{}", changeset );
            failed += 1;
        }
    }

    // Ensure there were no failures.
    //
    // If we fail here, cargo will display our printlns to the user.
    assert_eq!( failed, 0, "{} tests failed", failed );
}

/// Compiles a single file using rustc using similar options than what
/// cargo would have used.
fn build( path : &str ) -> String {

    // Launch rustc.
    let output = std::process::Command::new( "rustc" )
            .args( &[
                "--crate-name", "source",
                "--crate-type", "lib",
                path,
                "--out-dir", "tests/out",
                "-L", "dependency=../target/debug/deps",
                "--extern", "intercom=../target/debug/libintercom.rlib",
                "--pretty=expanded",
                "-Z", "unstable-options",
            ] )
            .output()
            .expect( "Failed to execute" );

    // Ensure the compilation was successful.
    if ! output.status.success() {
        println!( "FAILED TO COMPILE SOURCE {}", path );
        panic!( format!( "{}", String::from_utf8( output.stderr ).unwrap() ) );
    }

    // stdout is utf8 byte stream. Parse it into a string.
    String::from_utf8( output.stdout ).expect( "Bad output" )
}

/// Removes comments from the code.
fn strip_comments( code : &str ) -> String {
    let re = regex::Regex::new( r"//.*" ).expect( "Bad regex" );
    re.replace_all( code, "" ).into_owned()
}

fn format( code : &str ) -> String {

    // Strip comments. This allows us to embed comments in the target files
    // without requiring the attributes to expand these comments.
    let code = strip_comments( code );

    // Use default config but instead of altering the source/target files just
    // "display" the formatted code. This results in the output being available
    // in the 'out' parameter.
    let mut config = rustfmt::config::Config::default();
    config.override_value( "write_mode", "Display" );

    let mut out : Vec<u8> = vec![];
    rustfmt::format_input(
            rustfmt::Input::Text( code ),
            &config,
            Some( &mut out ) ).expect( "Failed to format" );

    // Convert the UTF-8 output into a string.
    String::from_utf8( out ).expect( "Bad output" )
}
<|endoftext|>


<commit_before>use {Point3, Result};
use std::path::Path;

macro_rules! setting {
    ($settings:expr, $name:expr) => {{
        use Error;
        *$settings.get($name).ok_or(Error::MissingCameraSetting($name.to_string()))?
    }}
}

/// A camera calibration.
#[derive(Clone, Copy, Debug)]
pub struct Camera {
    fx: f64,
    fy: f64,
    cx: f64,
    cy: f64,
    k1: f64,
    k2: f64,
    k3: f64,
    k4: f64,
    p1: f64,
    p2: f64,
    nx: usize,
    ny: usize,
    dx: f64,
    dy: f64,
}

impl Camera {
    /// Reads a camera calibration from a path.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Camera;
    /// let camera = Camera::from_path("data/camera.cam").unwrap();
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Camera> {
        use std::fs::File;
        use std::io::{BufRead, BufReader};
        use std::collections::HashMap;

        let settings: HashMap<String, f64> = BufReader::new(File::open(path)?)
            .lines()
            .filter_map(|line| {
                line.ok().and_then(|line| {
                    let words = line.split('=').collect::<Vec<_>>();
                    if words.len() == 2 {
                        words[1].parse().ok().map(|n| (words[0].to_string().to_lowercase(), n))
                    } else {
                        None
                    }
                })
            })
            .collect();
        Ok(Camera {
               fx: setting!(settings, "fx"),
               fy: setting!(settings, "fy"),
               cx: setting!(settings, "cx"),
               cy: setting!(settings, "cy"),
               k1: setting!(settings, "k1"),
               k2: setting!(settings, "k2"),
               k3: setting!(settings, "k3"),
               k4: setting!(settings, "k4"),
               p1: setting!(settings, "p1"),
               p2: setting!(settings, "p2"),
               nx: setting!(settings, "nx") as usize,
               ny: setting!(settings, "ny") as usize,
               dx: setting!(settings, "dx"),
               dy: setting!(settings, "dy"),
           })
    }

    /// Convert camera's coordinates to image coordinate space.
    ///
    /// Returns the distorted coordinates.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::{Camera, Point3};
    /// let camera = Camera::from_path("data/camera.cam").unwrap();
    /// let point = Point3::new(1., 2., 3.);
    /// let (u, v) = camera.cmcs_to_ics(point);
    /// ```
    pub fn cmcs_to_ics(&self, point: Point3) -> (f64, f64) {
        use nalgebra::Matrix3;

        let a = Matrix3::new(self.fx, 0., self.cx, 0., self.fy, self.cy, 0., 0., 1.);
        unimplemented!()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use Point3;

    #[test]
    fn from_path() {
        let camera = Camera::from_path("data/camera.cam").unwrap();
        assert_relative_eq!(883.5230667826110700, camera.fx);
        assert_relative_eq!(884.2400341059731200, camera.fy);
        assert_relative_eq!(-0.4164950117338272, camera.k1);
        assert_relative_eq!(0.1101340143848572, camera.k2);
        assert_relative_eq!(-0.1163151291620893, camera.k3);
        assert_relative_eq!(0.0141611215992979, camera.k4);
        assert_relative_eq!(529.9796605360121600, camera.cx);
        assert_relative_eq!(400.7770650611840000, camera.cy);
        assert_relative_eq!(0.0007262701857370, camera.p1);
        assert_relative_eq!(-0.0001515209871080, camera.p2);
        assert_eq!(1024, camera.nx);
        assert_eq!(768, camera.ny);
        assert_relative_eq!(0.0000170000000000, camera.dx);
        assert_relative_eq!(0.0000170000000000, camera.dy);
    }

    #[test]
    fn cmcs_to_ics() {
        let point = Point3::new(1., 2., 3.);
        let camera = Camera::from_path("data/camera.cam").unwrap();
        let (u, v) = camera.cmcs_to_ics(point);
        assert_relative_eq!(777.5760, u);
        assert_relative_eq!(896.7450, v);
    }
}
<commit_msg>Coordinate conversions for camera calibrations<commit_after>use {Point3, Result};
use std::path::Path;

macro_rules! setting {
    ($settings:expr, $name:expr) => {{
        use Error;
        *$settings.get($name).ok_or(Error::MissingCameraSetting($name.to_string()))?
    }}
}

/// A camera calibration.
#[derive(Clone, Copy, Debug)]
pub struct Camera {
    fx: f64,
    fy: f64,
    cx: f64,
    cy: f64,
    k1: f64,
    k2: f64,
    k3: f64,
    k4: f64,
    p1: f64,
    p2: f64,
    nx: usize,
    ny: usize,
    dx: f64,
    dy: f64,
}

impl Camera {
    /// Reads a camera calibration from a path.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::Camera;
    /// let camera = Camera::from_path("data/camera.cam").unwrap();
    /// ```
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Camera> {
        use std::fs::File;
        use std::io::{BufRead, BufReader};
        use std::collections::HashMap;

        let settings: HashMap<String, f64> = BufReader::new(File::open(path)?)
            .lines()
            .filter_map(|line| {
                line.ok().and_then(|line| {
                    let words = line.split('=').collect::<Vec<_>>();
                    if words.len() == 2 {
                        words[1].parse().ok().map(|n| (words[0].to_string().to_lowercase(), n))
                    } else {
                        None
                    }
                })
            })
            .collect();
        Ok(Camera {
               fx: setting!(settings, "fx"),
               fy: setting!(settings, "fy"),
               cx: setting!(settings, "cx"),
               cy: setting!(settings, "cy"),
               k1: setting!(settings, "k1"),
               k2: setting!(settings, "k2"),
               k3: setting!(settings, "k3"),
               k4: setting!(settings, "k4"),
               p1: setting!(settings, "p1"),
               p2: setting!(settings, "p2"),
               nx: setting!(settings, "nx") as usize,
               ny: setting!(settings, "ny") as usize,
               dx: setting!(settings, "dx"),
               dy: setting!(settings, "dy"),
           })
    }

    /// Convert camera's coordinates to image coordinate space.
    ///
    /// Returns the distorted coordinates.
    ///
    /// # Examples
    ///
    /// ```
    /// use riscan_pro::{Camera, Point3};
    /// let camera = Camera::from_path("data/camera.cam").unwrap();
    /// let point = Point3::new(1., 2., 3.);
    /// let (u, v) = camera.cmcs_to_ics(point);
    /// ```
    pub fn cmcs_to_ics(&self, point: Point3) -> (f64, f64) {
        use nalgebra::Matrix3;

        let a = Matrix3::new(self.fx, 0., self.cx, 0., self.fy, self.cy, 0., 0., 1.);
        let ud_prime = a * point;
        let u = ud_prime[0] / ud_prime[2];
        let v = ud_prime[1] / ud_prime[2];
        let x = (u - self.cx) / self.fx;
        let y = (v - self.cy) / self.fy;
        let r = (x.powi(2) + y.powi(2))
            .sqrt()
            .atan()
            .powi(2)
            .sqrt();
        let r_term = self.k1 * r.powi(2) + self.k2 * r.powi(4) + self.k3 * r.powi(6) +
                     self.k4 * r.powi(8);
        let u = u + x * self.fx * r_term + 2. * self.fx * x * y * self.p1 +
                self.p2 * self.fx * (r.powi(2) + 2. * x.powi(2));
        let v = v + y * self.fy * r_term + 2. * self.fy * x * y * self.p2 +
                self.p1 * self.fy * (r.powi(2) + 2. * y.powi(2));
        (u, v)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use Point3;

    #[test]
    fn from_path() {
        let camera = Camera::from_path("data/camera.cam").unwrap();
        assert_relative_eq!(883.5230667826110700, camera.fx);
        assert_relative_eq!(884.2400341059731200, camera.fy);
        assert_relative_eq!(-0.4164950117338272, camera.k1);
        assert_relative_eq!(0.1101340143848572, camera.k2);
        assert_relative_eq!(-0.1163151291620893, camera.k3);
        assert_relative_eq!(0.0141611215992979, camera.k4);
        assert_relative_eq!(529.9796605360121600, camera.cx);
        assert_relative_eq!(400.7770650611840000, camera.cy);
        assert_relative_eq!(0.0007262701857370, camera.p1);
        assert_relative_eq!(-0.0001515209871080, camera.p2);
        assert_eq!(1024, camera.nx);
        assert_eq!(768, camera.ny);
        assert_relative_eq!(0.0000170000000000, camera.dx);
        assert_relative_eq!(0.0000170000000000, camera.dy);
    }

    #[test]
    fn cmcs_to_ics() {
        let point = Point3::new(1., 2., 3.);
        let camera = Camera::from_path("data/camera.cam").unwrap();
        let (u, v) = camera.cmcs_to_ics(point);
        assert_relative_eq!(777.5760, u, epsilon = 1e-4);
        assert_relative_eq!(896.7450, v, epsilon = 1e-4);
    }
}
<|endoftext|>


<commit_before>use either::Either;
use hir::{db::AstDatabase, InFile};
use ide_db::{assists::Assist, source_change::SourceChange};
use stdx::format_to;
use syntax::{algo, ast::make, AstNode, SyntaxNodePtr};
use text_edit::TextEdit;

use crate::{fix, Diagnostic, DiagnosticsContext};

// Diagnostic: missing-fields
//
// This diagnostic is triggered if record lacks some fields that exist in the corresponding structure.
//
// Example:
//
// ```rust
// struct A { a: u8, b: u8 }
//
// let a = A { a: 10 };
// ```
pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Diagnostic {
    let mut message = String::from("missing structure fields:\n");
    for field in &d.missed_fields {
        format_to!(message, "- {}\n", field);
    }

    let ptr = InFile::new(
        d.file,
        d.field_list_parent_path
            .clone()
            .map(SyntaxNodePtr::from)
            .unwrap_or_else(|| d.field_list_parent.clone().either(|it| it.into(), |it| it.into())),
    );

    Diagnostic::new("missing-fields", message, ctx.sema.diagnostics_display_range(ptr).range)
        .with_fixes(fixes(ctx, d))
}

fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Assist>> {
    // Note that although we could add a diagnostics to
    // fill the missing tuple field, e.g :
    // `struct A(usize);`
    // `let a = A { 0: () }`
    // but it is uncommon usage and it should not be encouraged.
    if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
        return None;
    }

    let root = ctx.sema.db.parse_or_expand(d.file)?;
    let field_list_parent = match &d.field_list_parent {
        Either::Left(record_expr) => record_expr.to_node(&root),
        // FIXE: patterns should be fixable as well.
        Either::Right(_) => return None,
    };
    let old_field_list = field_list_parent.record_expr_field_list()?;
    let new_field_list = old_field_list.clone_for_update();
    for f in d.missed_fields.iter() {
        let field =
            make::record_expr_field(make::name_ref(&f.to_string()), Some(make::expr_unit()))
                .clone_for_update();
        new_field_list.add_field(field);
    }

    let edit = {
        let mut builder = TextEdit::builder();
        algo::diff(old_field_list.syntax(), new_field_list.syntax()).into_text_edit(&mut builder);
        builder.finish()
    };
    Some(vec![fix(
        "fill_missing_fields",
        "Fill struct fields",
        SourceChange::from_text_edit(d.file.original_file(ctx.sema.db), edit),
        ctx.sema.original_range(field_list_parent.syntax()).range,
    )])
}

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

    #[test]
    fn missing_record_pat_field_diagnostic() {
        check_diagnostics(
            r#"
struct S { foo: i32, bar: () }
fn baz(s: S) {
    let S { foo: _ } = s;
      //^ error: missing structure fields:
      //| - bar
}
"#,
        );
    }

    #[test]
    fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
        check_diagnostics(
            r"
struct S { foo: i32, bar: () }
fn baz(s: S) -> i32 {
    match s {
        S { foo, .. } => foo,
    }
}
",
        )
    }

    #[test]
    fn missing_record_pat_field_box() {
        check_diagnostics(
            r"
struct S { s: Box<u32> }
fn x(a: S) {
    let S { box s } = a;
}
",
        )
    }

    #[test]
    fn missing_record_pat_field_ref() {
        check_diagnostics(
            r"
struct S { s: u32 }
fn x(a: S) {
    let S { ref s } = a;
}
",
        )
    }

    #[test]
    fn range_mapping_out_of_macros() {
        // FIXME: this is very wrong, but somewhat tricky to fix.
        check_fix(
            r#"
fn some() {}
fn items() {}
fn here() {}

macro_rules! id { ($($tt:tt)*) => { $($tt)*}; }

fn main() {
    let _x = id![Foo { a: $042 }];
}

pub struct Foo { pub a: i32, pub b: i32 }
"#,
            r#"
fn some(, b: () ) {}
fn items() {}
fn here() {}

macro_rules! id { ($($tt:tt)*) => { $($tt)*}; }

fn main() {
    let _x = id![Foo { a: 42 }];
}

pub struct Foo { pub a: i32, pub b: i32 }
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_empty() {
        check_fix(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct {$0};
}
"#,
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct { one: (), two: () };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_self() {
        check_fix(
            r#"
struct TestStruct { one: i32 }

impl TestStruct {
    fn test_fn() { let s = Self {$0}; }
}
"#,
            r#"
struct TestStruct { one: i32 }

impl TestStruct {
    fn test_fn() { let s = Self { one: () }; }
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_enum() {
        check_fix(
            r#"
enum Expr {
    Bin { lhs: Box<Expr>, rhs: Box<Expr> }
}

impl Expr {
    fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
        Expr::Bin {$0 }
    }
}
"#,
            r#"
enum Expr {
    Bin { lhs: Box<Expr>, rhs: Box<Expr> }
}

impl Expr {
    fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
        Expr::Bin { lhs: (), rhs: () }
    }
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_partial() {
        check_fix(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct{ two: 2$0 };
}
"#,
            r"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct{ two: 2, one: () };
}
",
        );
    }

    #[test]
    fn test_fill_struct_fields_raw_ident() {
        check_fix(
            r#"
struct TestStruct { r#type: u8 }

fn test_fn() {
    TestStruct { $0 };
}
"#,
            r"
struct TestStruct { r#type: u8 }

fn test_fn() {
    TestStruct { r#type: ()  };
}
",
        );
    }

    #[test]
    fn test_fill_struct_fields_no_diagnostic() {
        check_diagnostics(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let one = 1;
    let s = TestStruct{ one, two: 2 };
}
        "#,
        );
    }

    #[test]
    fn test_fill_struct_fields_no_diagnostic_on_spread() {
        check_diagnostics(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let one = 1;
    let s = TestStruct{ ..a };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_blank_line() {
        check_fix(
            r#"
struct S { a: (), b: () }

fn f() {
    S {
        $0
    };
}
"#,
            r#"
struct S { a: (), b: () }

fn f() {
    S {
        a: (),
        b: (),
    };
}
"#,
        );
    }

    #[test]
    fn import_extern_crate_clash_with_inner_item() {
        // This is more of a resolver test, but doesn't really work with the hir_def testsuite.

        check_diagnostics(
            r#"
//- /lib.rs crate:lib deps:jwt
mod permissions;

use permissions::jwt;

fn f() {
    fn inner() {}
    jwt::Claims {}; // should resolve to the local one with 0 fields, and not get a diagnostic
}

//- /permissions.rs
pub mod jwt  {
    pub struct Claims {}
}

//- /jwt/lib.rs crate:jwt
pub struct Claims {
    field: u8,
}
        "#,
        );
    }
}
<commit_msg>Use struct init shorthand in fill struct fields assist<commit_after>use either::Either;
use hir::{db::AstDatabase, InFile};
use ide_db::{assists::Assist, source_change::SourceChange};
use rustc_hash::FxHashMap;
use stdx::format_to;
use syntax::{algo, ast::make, AstNode, SyntaxNodePtr};
use text_edit::TextEdit;

use crate::{fix, Diagnostic, DiagnosticsContext};

// Diagnostic: missing-fields
//
// This diagnostic is triggered if record lacks some fields that exist in the corresponding structure.
//
// Example:
//
// ```rust
// struct A { a: u8, b: u8 }
//
// let a = A { a: 10 };
// ```
pub(crate) fn missing_fields(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Diagnostic {
    let mut message = String::from("missing structure fields:\n");
    for field in &d.missed_fields {
        format_to!(message, "- {}\n", field);
    }

    let ptr = InFile::new(
        d.file,
        d.field_list_parent_path
            .clone()
            .map(SyntaxNodePtr::from)
            .unwrap_or_else(|| d.field_list_parent.clone().either(|it| it.into(), |it| it.into())),
    );

    Diagnostic::new("missing-fields", message, ctx.sema.diagnostics_display_range(ptr).range)
        .with_fixes(fixes(ctx, d))
}

fn fixes(ctx: &DiagnosticsContext<'_>, d: &hir::MissingFields) -> Option<Vec<Assist>> {
    // Note that although we could add a diagnostics to
    // fill the missing tuple field, e.g :
    // `struct A(usize);`
    // `let a = A { 0: () }`
    // but it is uncommon usage and it should not be encouraged.
    if d.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
        return None;
    }

    let root = ctx.sema.db.parse_or_expand(d.file)?;
    let field_list_parent = match &d.field_list_parent {
        Either::Left(record_expr) => record_expr.to_node(&root),
        // FIXE: patterns should be fixable as well.
        Either::Right(_) => return None,
    };
    let old_field_list = field_list_parent.record_expr_field_list()?;
    let new_field_list = old_field_list.clone_for_update();
    let mut locals = FxHashMap::default();
    ctx.sema.scope(field_list_parent.syntax()).process_all_names(&mut |name, def| {
        if let hir::ScopeDef::Local(local) = def {
            locals.insert(name.clone(), local);
        }
    });
    let missing_fields = ctx.sema.record_literal_missing_fields(&field_list_parent);
    for (f, ty) in missing_fields.iter() {
        let field_expr = if let Some(local_candidate) = locals.get(&f.name(ctx.sema.db)) {
            let candidate_ty = local_candidate.ty(ctx.sema.db);
            if ty.could_unify_with(ctx.sema.db, &candidate_ty) {
                None
            } else {
                Some(make::expr_unit())
            }
        } else {
            Some(make::expr_unit())
        };
        let field =
            make::record_expr_field(make::name_ref(&f.name(ctx.sema.db).to_string()), field_expr)
                .clone_for_update();
        new_field_list.add_field(field);
    }

    let edit = {
        let mut builder = TextEdit::builder();
        algo::diff(old_field_list.syntax(), new_field_list.syntax()).into_text_edit(&mut builder);
        builder.finish()
    };
    Some(vec![fix(
        "fill_missing_fields",
        "Fill struct fields",
        SourceChange::from_text_edit(d.file.original_file(ctx.sema.db), edit),
        ctx.sema.original_range(field_list_parent.syntax()).range,
    )])
}

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

    #[test]
    fn missing_record_pat_field_diagnostic() {
        check_diagnostics(
            r#"
struct S { foo: i32, bar: () }
fn baz(s: S) {
    let S { foo: _ } = s;
      //^ error: missing structure fields:
      //| - bar
}
"#,
        );
    }

    #[test]
    fn missing_record_pat_field_no_diagnostic_if_not_exhaustive() {
        check_diagnostics(
            r"
struct S { foo: i32, bar: () }
fn baz(s: S) -> i32 {
    match s {
        S { foo, .. } => foo,
    }
}
",
        )
    }

    #[test]
    fn missing_record_pat_field_box() {
        check_diagnostics(
            r"
struct S { s: Box<u32> }
fn x(a: S) {
    let S { box s } = a;
}
",
        )
    }

    #[test]
    fn missing_record_pat_field_ref() {
        check_diagnostics(
            r"
struct S { s: u32 }
fn x(a: S) {
    let S { ref s } = a;
}
",
        )
    }

    #[test]
    fn range_mapping_out_of_macros() {
        // FIXME: this is very wrong, but somewhat tricky to fix.
        check_fix(
            r#"
fn some() {}
fn items() {}
fn here() {}

macro_rules! id { ($($tt:tt)*) => { $($tt)*}; }

fn main() {
    let _x = id![Foo { a: $042 }];
}

pub struct Foo { pub a: i32, pub b: i32 }
"#,
            r#"
fn some(, b: () ) {}
fn items() {}
fn here() {}

macro_rules! id { ($($tt:tt)*) => { $($tt)*}; }

fn main() {
    let _x = id![Foo { a: 42 }];
}

pub struct Foo { pub a: i32, pub b: i32 }
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_empty() {
        check_fix(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct {$0};
}
"#,
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct { one: (), two: () };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_self() {
        check_fix(
            r#"
struct TestStruct { one: i32 }

impl TestStruct {
    fn test_fn() { let s = Self {$0}; }
}
"#,
            r#"
struct TestStruct { one: i32 }

impl TestStruct {
    fn test_fn() { let s = Self { one: () }; }
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_enum() {
        check_fix(
            r#"
enum Expr {
    Bin { lhs: Box<Expr>, rhs: Box<Expr> }
}

impl Expr {
    fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
        Expr::Bin {$0 }
    }
}
"#,
            r#"
enum Expr {
    Bin { lhs: Box<Expr>, rhs: Box<Expr> }
}

impl Expr {
    fn new_bin(lhs: Box<Expr>, rhs: Box<Expr>) -> Expr {
        Expr::Bin { lhs: (), rhs: () }
    }
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_partial() {
        check_fix(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct{ two: 2$0 };
}
"#,
            r"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let s = TestStruct{ two: 2, one: () };
}
",
        );
    }

    #[test]
    fn test_fill_struct_fields_raw_ident() {
        check_fix(
            r#"
struct TestStruct { r#type: u8 }

fn test_fn() {
    TestStruct { $0 };
}
"#,
            r"
struct TestStruct { r#type: u8 }

fn test_fn() {
    TestStruct { r#type: ()  };
}
",
        );
    }

    #[test]
    fn test_fill_struct_fields_no_diagnostic() {
        check_diagnostics(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let one = 1;
    let s = TestStruct{ one, two: 2 };
}
        "#,
        );
    }

    #[test]
    fn test_fill_struct_fields_no_diagnostic_on_spread() {
        check_diagnostics(
            r#"
struct TestStruct { one: i32, two: i64 }

fn test_fn() {
    let one = 1;
    let s = TestStruct{ ..a };
}
"#,
        );
    }

    #[test]
    fn test_fill_struct_fields_blank_line() {
        check_fix(
            r#"
struct S { a: (), b: () }

fn f() {
    S {
        $0
    };
}
"#,
            r#"
struct S { a: (), b: () }

fn f() {
    S {
        a: (),
        b: (),
    };
}
"#,
        );
    }

    #[test]
    fn import_extern_crate_clash_with_inner_item() {
        // This is more of a resolver test, but doesn't really work with the hir_def testsuite.

        check_diagnostics(
            r#"
//- /lib.rs crate:lib deps:jwt
mod permissions;

use permissions::jwt;

fn f() {
    fn inner() {}
    jwt::Claims {}; // should resolve to the local one with 0 fields, and not get a diagnostic
}

//- /permissions.rs
pub mod jwt  {
    pub struct Claims {}
}

//- /jwt/lib.rs crate:jwt
pub struct Claims {
    field: u8,
}
        "#,
        );
    }
}
<|endoftext|>


<commit_before>use platform::io;

pub static PF: u8 = 8;
pub static DF: u8 = 14;

/*
#[lang="fail_"]
#[fixed_stack_segment]
pub fn fail(expr: *u8, file: *u8, line: uint) -> ! {
    unsafe {
        io::puts(0, expr);
        io::puts(80, file);
        io::puti(80*2, line as int);

        zero::abort();
    }
}

#[lang="fail_bounds_check"]
#[fixed_stack_segment]
pub fn fail_bounds_check(file: *u8, line: uint, index: uint, len: uint) {
    unsafe {
        io::puts(0, file);
        io::puti(80, line as int);
        io::puti(80*2, index as int);
        io::puti(80*3, len as int);

        zero::abort();
    }
}
*/

#[no_split_stack]
#[inline(never)]
unsafe fn ex14() {
    io::puti(0, 14);
}

#[no_split_stack]
#[inline(never)]
pub unsafe fn page_fault() -> extern "C" unsafe fn() {
    asm!("jmp skip_page_fault
      page_fault_asm:
          .word 0xa80f
          .word 0xa00f
          .byte 0x06
          .byte 0x1e
          pusha"
        :::: "intel");
          ex14();
    asm!("hlt
          popa
          .byte 0x1f
          .byte 0x07
          .word 0xa10f
          .word 0xa90f
          iretd
      skip_page_fault:"
        :::: "intel");

    page_fault_asm
}

extern "C" { pub fn page_fault_asm(); }
<commit_msg>x86: refactor exception<commit_after>use core::mem::{size_of, transmute};
use core::ptr::offset;
use platform::io;
use cpu::idt;
use kernel::allocator;
use kernel::memory::Allocator;

#[repr(u8)]
pub enum Fault {
    PF = 8,
    DF = 14
}

/*
#[lang="fail_"]
#[fixed_stack_segment]
pub fn fail(expr: *u8, file: *u8, line: uint) -> ! {
    unsafe {
        io::puts(0, expr);
        io::puts(80, file);
        io::puti(80*2, line as int);

        zero::abort();
    }
}

#[lang="fail_bounds_check"]
#[fixed_stack_segment]
pub fn fail_bounds_check(file: *u8, line: uint, index: uint, len: uint) {
    unsafe {
        io::puts(0, file);
        io::puti(80, line as int);
        io::puti(80*2, index as int);
        io::puti(80*3, len as int);

        zero::abort();
    }
}
*/

// exception info and processor state saved on stack
pub struct IsrStack {
    edi: u32, esi: u32, ebp: u32, esp: u32, ebx: u32, edx: u32, ecx: u32, eax: u32, // pushad last
    ds: u32, es: u32, fs: u32, gs: u32, // segment registers
    int_no: u32, err_code: u32, // added by ISRs
    eip: u32, cs: u32, eflags: u32, useresp: u32, ss: u32 // the cpu adds these on the interrupt
}

#[no_split_stack]
#[inline(never)]
unsafe fn blue_screen(stack: *IsrStack) {
    io::puts("Exception ");
    io::puti((*stack).int_no as int);
    asm!("hlt");
}

#[packed]
pub struct IsrWithCode {
    push: u8,
    value: Fault,
    jmp: u8,
    rel: u32
}

#[packed]
pub struct Isr {
    dec_esp: u8,
    push: u8,
    value: Fault,
    jmp: u8,
    rel: u32
}

impl IsrWithCode {
    pub unsafe fn new(val: Fault) -> idt::IdtEntry {
        let (isr_ptr, _) = allocator.alloc(size_of::<IsrWithCode>());
        let isr = isr_ptr as *mut IsrWithCode;
        *isr = IsrWithCode {
            push: 0x6a, value: val,
            jmp: 0xe9, rel: exception_handler() as u32 - offset(isr_ptr as *IsrWithCode, 1) as u32
        };
        idt::IdtEntry::new(transmute(isr_ptr), 1 << 3, idt::INTR_GATE | idt::PRESENT)
    }
}

impl Isr {
    pub unsafe fn new(val: Fault) -> idt::IdtEntry {
        let (isr_ptr, _) = allocator.alloc(size_of::<Isr>());
        let isr = isr_ptr as *mut Isr;
        *isr = Isr {
            dec_esp: 0x4c,
            push: 0x6a, value: val,
            jmp: 0xe9, rel: exception_handler() as u32 - offset(isr_ptr as *Isr, 1) as u32
        };
        idt::IdtEntry::new(transmute(isr_ptr), 1 << 3, idt::INTR_GATE | idt::PRESENT)
    }
}

#[no_split_stack]
#[inline(never)]
pub unsafe fn exception_handler() -> extern "C" unsafe fn() {
    // Points to the data on stack
    // WARN: local var should use registers
    let mut stack_ptr: *IsrStack;
    asm!("jmp skip_exception_handler
      exception_handler_asm:
          .word 0xa80f // push gs
          .word 0xa00f // push fs
          .byte 0x06 // push es
          .byte 0x1e // push ds
          pusha"
        : "={esp}"(stack_ptr) ::: "volatile", "intel");

            blue_screen(stack_ptr);

    asm!("popa
          .byte 0x1f
          .byte 0x07
          .word 0xa10f
          .word 0xa90f
          iretd
      skip_exception_handler:"
        :::: "volatile", "intel");

    exception_handler_asm
}

extern "C" { pub fn exception_handler_asm(); }
<|endoftext|>


<commit_before>// Copyright (c) 2016-2020 Fabian Schuiki

//! An implementation of the visitor pattern for the HIR.
//!
//! This module defines the [`Visitor`] trait that allows the HIR tree graph to
//! be visited.

use super::{nodes::*, HirNode};
use crate::{
    common::{name::Name, source::Spanned, NodeId},
    Context,
};

/// A visitor of the HIR.
pub trait Visitor<'a>: Sized {
    /// The type of context that this visitor uses.
    type Context: Context<'a>;

    /// Get the context to be used to resolve queries.
    fn context(&self) -> &Self::Context;

    fn visit_node_with_id(&mut self, node_id: NodeId, lvalue: bool) {
        match self.context().hir_of(node_id) {
            Ok(x) => self.visit_node(x, lvalue),
            Err(()) => (),
        }
    }

    fn visit_node(&mut self, node: HirNode<'a>, lvalue: bool) {
        match node {
            HirNode::Module(x) => self.visit_module(x),
            HirNode::Proc(x) => self.visit_proc(x),
            HirNode::Stmt(x) => self.visit_stmt(x),
            HirNode::Expr(x) => self.visit_expr(x, lvalue),
            HirNode::EventExpr(x) => self.visit_event_expr(x),
            HirNode::Typedef(x) => self.visit_typedef(x),
            HirNode::VarDecl(x) => self.visit_var_decl(x),
            HirNode::Assign(x) => self.visit_assign(x),
            _ => (),
        }
    }

    fn visit_ident(&mut self, _ident: Spanned<Name>) {}
    fn visit_unary_op(&mut self, _op: UnaryOp) {}
    fn visit_binary_op(&mut self, _op: BinaryOp) {}

    fn visit_module(&mut self, module: &'a Module) {
        walk_module(self, module)
    }

    fn visit_proc(&mut self, prok: &'a Proc) {
        walk_proc(self, prok)
    }

    fn visit_stmt(&mut self, stmt: &'a Stmt) {
        walk_stmt(self, stmt)
    }

    fn visit_expr(&mut self, expr: &'a Expr, lvalue: bool) {
        walk_expr(self, expr, lvalue);
    }

    fn visit_timing_control(&mut self, ctrl: &'a TimingControl) {
        walk_timing_control(self, ctrl);
    }

    fn visit_event_expr(&mut self, expr: &'a EventExpr) {
        walk_event_expr(self, expr);
    }

    fn visit_event(&mut self, event: &'a Event) {
        walk_event(self, event);
    }

    fn visit_typedef(&mut self, typedef: &'a Typedef) {
        walk_typedef(self, typedef);
    }

    fn visit_var_decl(&mut self, decl: &'a VarDecl) {
        walk_var_decl(self, decl);
    }

    fn visit_assign(&mut self, assign: &'a Assign) {
        walk_assign(self, assign);
    }
}

/// Walk the contents of a module.
pub fn walk_module<'a>(visitor: &mut impl Visitor<'a>, module: &'a Module) {
    for port in &module.ports_new.int {
        visitor.visit_node_with_id(port.id, false);
    }
    for port in &module.ports_new.ext_pos {
        visitor.visit_node_with_id(port.id, false);
    }
    for &id in module.params {
        visitor.visit_node_with_id(id, false);
    }
    walk_module_block(visitor, &module.block);
}

/// Walk the contents of a module block.
pub fn walk_module_block<'a>(visitor: &mut impl Visitor<'a>, blk: &'a ModuleBlock) {
    for &id in &blk.insts {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.decls {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.procs {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.gens {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.params {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.assigns {
        visitor.visit_node_with_id(id, false);
    }
}

/// Walk the contents of a procedure.
pub fn walk_proc<'a>(visitor: &mut impl Visitor<'a>, prok: &'a Proc) {
    visitor.visit_node_with_id(prok.stmt, false);
}

/// Walk the contents of a statement.
pub fn walk_stmt<'a>(visitor: &mut impl Visitor<'a>, stmt: &'a Stmt) {
    #[allow(unreachable_patterns)]
    match stmt.kind {
        StmtKind::Null => (),
        StmtKind::Block(ref stmts) => {
            for &id in stmts {
                visitor.visit_node_with_id(id, false);
            }
        }
        StmtKind::Assign { lhs, rhs, .. } => {
            visitor.visit_node_with_id(lhs, true);
            visitor.visit_node_with_id(rhs, false);
        }
        StmtKind::Timed { ref control, stmt } => {
            visitor.visit_timing_control(control);
            visitor.visit_node_with_id(stmt, false);
        }
        StmtKind::Expr(expr) => visitor.visit_node_with_id(expr, false),
        StmtKind::If {
            cond,
            main_stmt,
            else_stmt,
        } => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(main_stmt, false);
            if let Some(else_stmt) = else_stmt {
                visitor.visit_node_with_id(else_stmt, false);
            }
        }
        StmtKind::Loop { kind, body } => {
            match kind {
                LoopKind::Forever => (),
                LoopKind::Repeat(id) | LoopKind::While(id) | LoopKind::Do(id) => {
                    visitor.visit_node_with_id(id, false);
                }
                LoopKind::For(init, cond, step) => {
                    visitor.visit_node_with_id(init, false);
                    visitor.visit_node_with_id(cond, false);
                    visitor.visit_node_with_id(step, false);
                }
            }
            visitor.visit_node_with_id(body, false);
        }
        StmtKind::InlineGroup { ref stmts, .. } => {
            for &stmt in stmts {
                visitor.visit_node_with_id(stmt, false);
            }
        }
        StmtKind::Case {
            expr,
            ref ways,
            default,
            ..
        } => {
            visitor.visit_node_with_id(expr, false);
            for &(ref exprs, stmt) in ways {
                for &expr in exprs {
                    visitor.visit_node_with_id(expr, false);
                }
                visitor.visit_node_with_id(stmt, false);
            }
            if let Some(default) = default {
                visitor.visit_node_with_id(default, false);
            }
        }
    }
}

/// Walk the contents of an expression.
pub fn walk_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a Expr, lvalue: bool) {
    match expr.kind {
        ExprKind::Builtin(BuiltinCall::Unsupported)
        | ExprKind::IntConst { .. }
        | ExprKind::UnsizedConst(_)
        | ExprKind::TimeConst(_)
        | ExprKind::StringConst(_) => (),
        ExprKind::Ident(x) => {
            visitor.visit_ident(x);
        }
        ExprKind::Unary(op, arg) => {
            visitor.visit_unary_op(op);
            visitor.visit_node_with_id(arg, lvalue);
        }
        ExprKind::Binary(op, lhs, rhs) => {
            visitor.visit_binary_op(op);
            visitor.visit_node_with_id(lhs, lvalue);
            visitor.visit_node_with_id(rhs, lvalue);
        }
        ExprKind::Field(expr, _) => {
            visitor.visit_node_with_id(expr, lvalue);
        }
        ExprKind::Index(expr, mode) => {
            visitor.visit_node_with_id(expr, lvalue);
            match mode {
                IndexMode::One(expr) => visitor.visit_node_with_id(expr, false),
                IndexMode::Many(_, lhs, rhs) => {
                    visitor.visit_node_with_id(lhs, false);
                    visitor.visit_node_with_id(rhs, false);
                }
            }
        }
        ExprKind::Builtin(BuiltinCall::Clog2(arg))
        | ExprKind::Builtin(BuiltinCall::Bits(arg))
        | ExprKind::Builtin(BuiltinCall::Signed(arg))
        | ExprKind::Builtin(BuiltinCall::Unsigned(arg)) => {
            visitor.visit_node_with_id(arg, false);
        }
        ExprKind::Ternary(cond, true_expr, false_expr) => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(true_expr, lvalue);
            visitor.visit_node_with_id(false_expr, lvalue);
        }
        ExprKind::Scope(expr, _) => {
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::PositionalPattern(ref exprs) => {
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::NamedPattern(ref mappings) => {
            for &(key, value) in mappings {
                match key {
                    PatternMapping::Type(ty) => visitor.visit_node_with_id(ty, false),
                    PatternMapping::Member(expr) => visitor.visit_node_with_id(expr, false),
                    PatternMapping::Default => (),
                }
                visitor.visit_node_with_id(value, lvalue);
            }
        }
        ExprKind::RepeatPattern(count, ref exprs) => {
            visitor.visit_node_with_id(count, lvalue);
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::EmptyPattern => (),
        ExprKind::Concat(repeat, ref exprs) => {
            if let Some(repeat) = repeat {
                visitor.visit_node_with_id(repeat, false);
            }
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::Cast(ty, expr) => {
            visitor.visit_node_with_id(ty, false);
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::CastSign(_, expr) => {
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::CastSize(size_expr, expr) => {
            visitor.visit_node_with_id(size_expr, false);
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::Inside(expr, ref ranges) => {
            visitor.visit_node_with_id(expr, false);
            for r in ranges {
                match r.value {
                    InsideRange::Single(expr) => visitor.visit_node_with_id(expr, false),
                    InsideRange::Range(lo, hi) => {
                        visitor.visit_node_with_id(lo, false);
                        visitor.visit_node_with_id(hi, false);
                    }
                }
            }
        }
        ExprKind::FunctionCall(_, ref args) => {
            for &arg in args {
                if let Some(expr) = arg.expr {
                    visitor.visit_node_with_id(expr, false);
                }
            }
        }
    }
}

/// Walk the contents of a timing control block.
pub fn walk_timing_control<'a>(visitor: &mut impl Visitor<'a>, ctrl: &'a TimingControl) {
    match *ctrl {
        TimingControl::Delay(id) => visitor.visit_node_with_id(id, false),
        TimingControl::ImplicitEvent => (),
        TimingControl::ExplicitEvent(id) => visitor.visit_node_with_id(id, false),
    }
}

/// Walk the contents of an event expression.
pub fn walk_event_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a EventExpr) {
    for event in &expr.events {
        visitor.visit_event(event);
    }
}

/// Walk the contents of an event.
pub fn walk_event<'a>(visitor: &mut impl Visitor<'a>, event: &'a Event) {
    visitor.visit_node_with_id(event.expr, false);
    for &iff in &event.iff {
        visitor.visit_node_with_id(iff, false);
    }
}

/// Walk the contents of a typedef.
pub fn walk_typedef<'a>(visitor: &mut impl Visitor<'a>, typedef: &'a Typedef) {
    visitor.visit_node_with_id(typedef.ty, false);
}

/// Walk the contents of a variable declaration.
pub fn walk_var_decl<'a>(visitor: &mut impl Visitor<'a>, decl: &'a VarDecl) {
    visitor.visit_node_with_id(decl.ty, false);
    if let Some(init) = decl.init {
        visitor.visit_node_with_id(init, false);
    }
}

/// Walk the contents of an assignment.
pub fn walk_assign<'a>(visitor: &mut impl Visitor<'a>, assign: &'a Assign) {
    visitor.visit_node_with_id(assign.lhs, true);
    visitor.visit_node_with_id(assign.rhs, false);
}
<commit_msg>svlog: hir: Add ports to visitor<commit_after>// Copyright (c) 2016-2020 Fabian Schuiki

//! An implementation of the visitor pattern for the HIR.
//!
//! This module defines the [`Visitor`] trait that allows the HIR tree graph to
//! be visited.

use super::{nodes::*, HirNode};
use crate::{
    common::{name::Name, source::Spanned, NodeId},
    Context,
};

/// A visitor of the HIR.
pub trait Visitor<'a>: Sized {
    /// The type of context that this visitor uses.
    type Context: Context<'a>;

    /// Get the context to be used to resolve queries.
    fn context(&self) -> &Self::Context;

    fn visit_node_with_id(&mut self, node_id: NodeId, lvalue: bool) {
        match self.context().hir_of(node_id) {
            Ok(x) => self.visit_node(x, lvalue),
            Err(()) => (),
        }
    }

    fn visit_node(&mut self, node: HirNode<'a>, lvalue: bool) {
        match node {
            HirNode::Module(x) => self.visit_module(x),
            HirNode::Proc(x) => self.visit_proc(x),
            HirNode::Stmt(x) => self.visit_stmt(x),
            HirNode::Expr(x) => self.visit_expr(x, lvalue),
            HirNode::EventExpr(x) => self.visit_event_expr(x),
            HirNode::Typedef(x) => self.visit_typedef(x),
            HirNode::VarDecl(x) => self.visit_var_decl(x),
            HirNode::Assign(x) => self.visit_assign(x),
            HirNode::IntPort(x) => self.visit_int_port(x),
            HirNode::ExtPort(x) => self.visit_ext_port(x),
            _ => (),
        }
    }

    fn visit_ident(&mut self, _ident: Spanned<Name>) {}
    fn visit_unary_op(&mut self, _op: UnaryOp) {}
    fn visit_binary_op(&mut self, _op: BinaryOp) {}

    fn visit_module(&mut self, module: &'a Module) {
        walk_module(self, module)
    }

    fn visit_proc(&mut self, prok: &'a Proc) {
        walk_proc(self, prok)
    }

    fn visit_stmt(&mut self, stmt: &'a Stmt) {
        walk_stmt(self, stmt)
    }

    fn visit_expr(&mut self, expr: &'a Expr, lvalue: bool) {
        walk_expr(self, expr, lvalue);
    }

    fn visit_timing_control(&mut self, ctrl: &'a TimingControl) {
        walk_timing_control(self, ctrl);
    }

    fn visit_event_expr(&mut self, expr: &'a EventExpr) {
        walk_event_expr(self, expr);
    }

    fn visit_event(&mut self, event: &'a Event) {
        walk_event(self, event);
    }

    fn visit_typedef(&mut self, typedef: &'a Typedef) {
        walk_typedef(self, typedef);
    }

    fn visit_var_decl(&mut self, decl: &'a VarDecl) {
        walk_var_decl(self, decl);
    }

    fn visit_assign(&mut self, assign: &'a Assign) {
        walk_assign(self, assign);
    }

    fn visit_int_port(&mut self, int_port: &'a IntPort) {
        walk_int_port(self, int_port);
    }

    fn visit_ext_port(&mut self, ext_port: &'a ExtPort) {
        walk_ext_port(self, ext_port);
    }
}

/// Walk the contents of a module.
pub fn walk_module<'a>(visitor: &mut impl Visitor<'a>, module: &'a Module) {
    for port in &module.ports_new.int {
        visitor.visit_node_with_id(port.id, false);
    }
    for port in &module.ports_new.ext_pos {
        visitor.visit_node_with_id(port.id, false);
    }
    for &id in module.params {
        visitor.visit_node_with_id(id, false);
    }
    walk_module_block(visitor, &module.block);
}

/// Walk the contents of a module block.
pub fn walk_module_block<'a>(visitor: &mut impl Visitor<'a>, blk: &'a ModuleBlock) {
    for &id in &blk.insts {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.decls {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.procs {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.gens {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.params {
        visitor.visit_node_with_id(id, false);
    }
    for &id in &blk.assigns {
        visitor.visit_node_with_id(id, false);
    }
}

/// Walk the contents of a procedure.
pub fn walk_proc<'a>(visitor: &mut impl Visitor<'a>, prok: &'a Proc) {
    visitor.visit_node_with_id(prok.stmt, false);
}

/// Walk the contents of a statement.
pub fn walk_stmt<'a>(visitor: &mut impl Visitor<'a>, stmt: &'a Stmt) {
    #[allow(unreachable_patterns)]
    match stmt.kind {
        StmtKind::Null => (),
        StmtKind::Block(ref stmts) => {
            for &id in stmts {
                visitor.visit_node_with_id(id, false);
            }
        }
        StmtKind::Assign { lhs, rhs, .. } => {
            visitor.visit_node_with_id(lhs, true);
            visitor.visit_node_with_id(rhs, false);
        }
        StmtKind::Timed { ref control, stmt } => {
            visitor.visit_timing_control(control);
            visitor.visit_node_with_id(stmt, false);
        }
        StmtKind::Expr(expr) => visitor.visit_node_with_id(expr, false),
        StmtKind::If {
            cond,
            main_stmt,
            else_stmt,
        } => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(main_stmt, false);
            if let Some(else_stmt) = else_stmt {
                visitor.visit_node_with_id(else_stmt, false);
            }
        }
        StmtKind::Loop { kind, body } => {
            match kind {
                LoopKind::Forever => (),
                LoopKind::Repeat(id) | LoopKind::While(id) | LoopKind::Do(id) => {
                    visitor.visit_node_with_id(id, false);
                }
                LoopKind::For(init, cond, step) => {
                    visitor.visit_node_with_id(init, false);
                    visitor.visit_node_with_id(cond, false);
                    visitor.visit_node_with_id(step, false);
                }
            }
            visitor.visit_node_with_id(body, false);
        }
        StmtKind::InlineGroup { ref stmts, .. } => {
            for &stmt in stmts {
                visitor.visit_node_with_id(stmt, false);
            }
        }
        StmtKind::Case {
            expr,
            ref ways,
            default,
            ..
        } => {
            visitor.visit_node_with_id(expr, false);
            for &(ref exprs, stmt) in ways {
                for &expr in exprs {
                    visitor.visit_node_with_id(expr, false);
                }
                visitor.visit_node_with_id(stmt, false);
            }
            if let Some(default) = default {
                visitor.visit_node_with_id(default, false);
            }
        }
    }
}

/// Walk the contents of an expression.
pub fn walk_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a Expr, lvalue: bool) {
    match expr.kind {
        ExprKind::Builtin(BuiltinCall::Unsupported)
        | ExprKind::IntConst { .. }
        | ExprKind::UnsizedConst(_)
        | ExprKind::TimeConst(_)
        | ExprKind::StringConst(_) => (),
        ExprKind::Ident(x) => {
            visitor.visit_ident(x);
        }
        ExprKind::Unary(op, arg) => {
            visitor.visit_unary_op(op);
            visitor.visit_node_with_id(arg, lvalue);
        }
        ExprKind::Binary(op, lhs, rhs) => {
            visitor.visit_binary_op(op);
            visitor.visit_node_with_id(lhs, lvalue);
            visitor.visit_node_with_id(rhs, lvalue);
        }
        ExprKind::Field(expr, _) => {
            visitor.visit_node_with_id(expr, lvalue);
        }
        ExprKind::Index(expr, mode) => {
            visitor.visit_node_with_id(expr, lvalue);
            match mode {
                IndexMode::One(expr) => visitor.visit_node_with_id(expr, false),
                IndexMode::Many(_, lhs, rhs) => {
                    visitor.visit_node_with_id(lhs, false);
                    visitor.visit_node_with_id(rhs, false);
                }
            }
        }
        ExprKind::Builtin(BuiltinCall::Clog2(arg))
        | ExprKind::Builtin(BuiltinCall::Bits(arg))
        | ExprKind::Builtin(BuiltinCall::Signed(arg))
        | ExprKind::Builtin(BuiltinCall::Unsigned(arg)) => {
            visitor.visit_node_with_id(arg, false);
        }
        ExprKind::Ternary(cond, true_expr, false_expr) => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(true_expr, lvalue);
            visitor.visit_node_with_id(false_expr, lvalue);
        }
        ExprKind::Scope(expr, _) => {
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::PositionalPattern(ref exprs) => {
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::NamedPattern(ref mappings) => {
            for &(key, value) in mappings {
                match key {
                    PatternMapping::Type(ty) => visitor.visit_node_with_id(ty, false),
                    PatternMapping::Member(expr) => visitor.visit_node_with_id(expr, false),
                    PatternMapping::Default => (),
                }
                visitor.visit_node_with_id(value, lvalue);
            }
        }
        ExprKind::RepeatPattern(count, ref exprs) => {
            visitor.visit_node_with_id(count, lvalue);
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::EmptyPattern => (),
        ExprKind::Concat(repeat, ref exprs) => {
            if let Some(repeat) = repeat {
                visitor.visit_node_with_id(repeat, false);
            }
            for &expr in exprs {
                visitor.visit_node_with_id(expr, lvalue);
            }
        }
        ExprKind::Cast(ty, expr) => {
            visitor.visit_node_with_id(ty, false);
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::CastSign(_, expr) => {
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::CastSize(size_expr, expr) => {
            visitor.visit_node_with_id(size_expr, false);
            visitor.visit_node_with_id(expr, false);
        }
        ExprKind::Inside(expr, ref ranges) => {
            visitor.visit_node_with_id(expr, false);
            for r in ranges {
                match r.value {
                    InsideRange::Single(expr) => visitor.visit_node_with_id(expr, false),
                    InsideRange::Range(lo, hi) => {
                        visitor.visit_node_with_id(lo, false);
                        visitor.visit_node_with_id(hi, false);
                    }
                }
            }
        }
        ExprKind::FunctionCall(_, ref args) => {
            for &arg in args {
                if let Some(expr) = arg.expr {
                    visitor.visit_node_with_id(expr, false);
                }
            }
        }
    }
}

/// Walk the contents of a timing control block.
pub fn walk_timing_control<'a>(visitor: &mut impl Visitor<'a>, ctrl: &'a TimingControl) {
    match *ctrl {
        TimingControl::Delay(id) => visitor.visit_node_with_id(id, false),
        TimingControl::ImplicitEvent => (),
        TimingControl::ExplicitEvent(id) => visitor.visit_node_with_id(id, false),
    }
}

/// Walk the contents of an event expression.
pub fn walk_event_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a EventExpr) {
    for event in &expr.events {
        visitor.visit_event(event);
    }
}

/// Walk the contents of an event.
pub fn walk_event<'a>(visitor: &mut impl Visitor<'a>, event: &'a Event) {
    visitor.visit_node_with_id(event.expr, false);
    for &iff in &event.iff {
        visitor.visit_node_with_id(iff, false);
    }
}

/// Walk the contents of a typedef.
pub fn walk_typedef<'a>(visitor: &mut impl Visitor<'a>, typedef: &'a Typedef) {
    visitor.visit_node_with_id(typedef.ty, false);
}

/// Walk the contents of a variable declaration.
pub fn walk_var_decl<'a>(visitor: &mut impl Visitor<'a>, decl: &'a VarDecl) {
    visitor.visit_node_with_id(decl.ty, false);
    if let Some(init) = decl.init {
        visitor.visit_node_with_id(init, false);
    }
}

/// Walk the contents of an assignment.
pub fn walk_assign<'a>(visitor: &mut impl Visitor<'a>, assign: &'a Assign) {
    visitor.visit_node_with_id(assign.lhs, true);
    visitor.visit_node_with_id(assign.rhs, false);
}

/// Walk the contents of an internal port.
pub fn walk_int_port<'a>(visitor: &mut impl Visitor<'a>, int_port: &'a IntPort) {
    if let Some(data) = &int_port.data {
        visitor.visit_node_with_id(data.ty, false);
        if let Some(default) = data.default {
            visitor.visit_node_with_id(default, false);
        }
    }
}

/// Walk the contents of an external port.
pub fn walk_ext_port<'a>(_visitor: &mut impl Visitor<'a>, _ext_port: &'a ExtPort) {}
<|endoftext|>


<commit_before>use super::Config;

use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};

pub fn get_template_source(tpl_path: &Path) -> String {
    let mut f = match File::open(tpl_path) {
        Err(_) => panic!("unable to open template file '{}'", tpl_path.to_str().unwrap()),
        Ok(f) => f,
    };

    let mut s = String::new();
    f.read_to_string(&mut s).unwrap();
    if s.ends_with('\n') {
        let _ = s.pop();
    }
    s
}

pub fn find_template_from_path(path: &str, start_at: Option<&Path>) -> PathBuf {
    if let Some(root) = start_at {
        let relative = root.with_file_name(path);
        if relative.exists() {
            return relative.to_owned();
        }
    }

    let config = Config::new();
    for dir in &config.dirs {
        let rooted = dir.join(path);
        if rooted.exists() {
            return rooted;
        }
    }

    panic!("template {:?} not found in directories {:?}", path, config.dirs)
}

#[cfg(test)]
mod tests {
    use super::{find_template_from_path, get_template_source};

    #[test]
    fn get_source() {
        let path = find_template_from_path("sub/b.html", None);
        assert_eq!(get_template_source(&path), "bar");
    }

    #[test]
    fn find_absolute() {
        let root = find_template_from_path("a.html", None);
        let path = find_template_from_path("sub/b.html", Some(&root));
        assert!(path.to_str().unwrap().ends_with("sub/b.html"));
    }

    #[test]
    #[should_panic]
    fn find_relative_nonexistent() {
        let root = find_template_from_path("a.html", None);
        find_template_from_path("b.html", Some(&root));
    }

    #[test]
    fn find_relative() {
        let root = find_template_from_path("sub/b.html", None);
        let path = find_template_from_path("c.html", Some(&root));
        assert!(path.to_str().unwrap().ends_with("sub/c.html"));
    }

    #[test]
    fn find_relative_sub() {
        let root = find_template_from_path("sub/b.html", None);
        let path = find_template_from_path("sub1/d.html", Some(&root));
        assert!(path.to_str().unwrap().ends_with("sub/sub1/d.html"));
    }
}
<commit_msg>Simplify get_template_source() by using fs::read_to_string()<commit_after>use super::Config;

use std::fs;
use std::path::{Path, PathBuf};

pub fn get_template_source(tpl_path: &Path) -> String {
    match fs::read_to_string(tpl_path) {
        Err(_) => panic!("unable to open template file '{}'", tpl_path.to_str().unwrap()),
        Ok(mut source) => {
            if source.ends_with('\n') {
                let _ = source.pop();
            }
            source
        }
    }
}

pub fn find_template_from_path(path: &str, start_at: Option<&Path>) -> PathBuf {
    if let Some(root) = start_at {
        let relative = root.with_file_name(path);
        if relative.exists() {
            return relative.to_owned();
        }
    }

    let config = Config::new();
    for dir in &config.dirs {
        let rooted = dir.join(path);
        if rooted.exists() {
            return rooted;
        }
    }

    panic!("template {:?} not found in directories {:?}", path, config.dirs)
}

#[cfg(test)]
mod tests {
    use super::{find_template_from_path, get_template_source};

    #[test]
    fn get_source() {
        let path = find_template_from_path("sub/b.html", None);
        assert_eq!(get_template_source(&path), "bar");
    }

    #[test]
    fn find_absolute() {
        let root = find_template_from_path("a.html", None);
        let path = find_template_from_path("sub/b.html", Some(&root));
        assert!(path.to_str().unwrap().ends_with("sub/b.html"));
    }

    #[test]
    #[should_panic]
    fn find_relative_nonexistent() {
        let root = find_template_from_path("a.html", None);
        find_template_from_path("b.html", Some(&root));
    }

    #[test]
    fn find_relative() {
        let root = find_template_from_path("sub/b.html", None);
        let path = find_template_from_path("c.html", Some(&root));
        assert!(path.to_str().unwrap().ends_with("sub/c.html"));
    }

    #[test]
    fn find_relative_sub() {
        let root = find_template_from_path("sub/b.html", None);
        let path = find_template_from_path("sub1/d.html", Some(&root));
        assert!(path.to_str().unwrap().ends_with("sub/sub1/d.html"));
    }
}
<|endoftext|>


<commit_before>//! Implements the basic XTEA cipher routines as described in the
//! paper (http://en.wikipedia.org/wiki/XTEA).  These functions only
//! deal with a single 64-bit block of data at a time.

static NUM_ROUNDS: u32 = 32;

use super::{Key, Block};

/// Encrypts 64 bits of `input` using the `key`.
///
/// # Example:
/// ```
/// use tea::cipher;
///
/// let key = [5, 6, 7, 8];
/// let plaintext = [128, 256];
/// assert!(cipher::encipher(&key, &plaintext) != plaintext);
/// ```
pub fn encipher(key: &Key, input: &Block) -> Block {
    let [mut v0, mut v1] = *input;
    let delta = 0x9E3779B9;
    let mut sum: u32 = 0;
    for _ in 0..NUM_ROUNDS {
        v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[(sum & 3) as usize]);
        sum += delta;
        v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[((sum>>11) & 3) as usize])
    }
    [v0, v1]
}

/// Decrypts 64 bits of `input` using the `key`.
///
/// # Example:
/// ```
/// use tea::cipher;
///
/// let key = [5, 6, 7, 8];
/// let plaintext = [128, 256];
/// let crypted = cipher::encipher(&key, &plaintext);
/// assert_eq!(cipher::decipher(&key, &crypted), plaintext);
/// ```
pub fn decipher(key: &Key, input: &Block) -> Block {
    let [mut v0, mut v1] = *input;
    let delta = 0x9E3779B9;
    let mut sum = delta * NUM_ROUNDS;
    for _ in 0..NUM_ROUNDS {
        v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[((sum>>11) & 3) as usize]);
        sum -= delta;
        v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[(sum & 3) as usize]);
    }
    [v0, v1]
}

#[test]
fn it_works() {
    let key: Key = [10, 20, 30, 42];
    let plaintext: Block = [300, 400];
    let ciphertext = encipher(&key, &plaintext);
    assert!(plaintext != ciphertext);
    assert_eq!(plaintext, decipher(&key, &ciphertext));
}
<commit_msg>switched to wrapping math to avoid overflow checking<commit_after>//! Implements the basic XTEA cipher routines as described in the
//! paper (http://en.wikipedia.org/wiki/XTEA).  These functions only
//! deal with a single 64-bit block of data at a time.

static NUM_ROUNDS: u32 = 32;

use super::{Key, Block};

/// Encrypts 64 bits of `input` using the `key`.
///
/// # Example:
/// ```
/// use tea::cipher;
///
/// let key = [5, 6, 7, 8];
/// let plaintext = [128, 256];
/// assert!(cipher::encipher(&key, &plaintext) != plaintext);
/// ```
pub fn encipher(key: &Key, input: &Block) -> Block {
    let [mut v0, mut v1] = *input;
    let delta = 0x9E3779B9;
    let mut sum: u32 = 0;
    for _ in 0..NUM_ROUNDS {
        v0 = v0.wrapping_add((((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) ^ (sum.wrapping_add(key[(sum & 3) as usize])));
        sum = sum.wrapping_add(delta);
        v1 = v1.wrapping_add((((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) ^ (sum.wrapping_add(key[((sum>>11) & 3) as usize])))
    }
    [v0, v1]
}

/// Decrypts 64 bits of `input` using the `key`.
///
/// # Example:
/// ```
/// use tea::cipher;
///
/// let key = [5, 6, 7, 8];
/// let plaintext = [128, 256];
/// let crypted = cipher::encipher(&key, &plaintext);
/// assert_eq!(cipher::decipher(&key, &crypted), plaintext);
/// ```
pub fn decipher(key: &Key, input: &Block) -> Block {
    let [mut v0, mut v1] = *input;
    let delta = 0x9E3779B9;
    let mut sum = delta.wrapping_mul(NUM_ROUNDS);
    for _ in 0..NUM_ROUNDS {
        v1 = v1.wrapping_sub((((v0 << 4) ^ (v0 >> 5)).wrapping_add(v0)) ^ (sum.wrapping_add(key[((sum>>11) & 3) as usize])));
        sum = sum.wrapping_sub(delta);
        v0 = v0.wrapping_sub((((v1 << 4) ^ (v1 >> 5)).wrapping_add(v1)) ^ (sum.wrapping_add(key[(sum & 3) as usize])));
    }
    [v0, v1]
}

#[test]
fn it_works() {
    let key: Key = [10, 20, 30, 42];
    let plaintext: Block = [300, 400];
    let ciphertext = encipher(&key, &plaintext);
    assert!(plaintext != ciphertext);
    assert_eq!(plaintext, decipher(&key, &ciphertext));
}
<|endoftext|>