<commit_before>extern crate ansi_term;
extern crate rand;

use ansi_term::Colour::*;
use rand::Rng;
use std::io;

enum Card {
    ClubsAce,
    ClubsTen,
    ClubsKing,
    ClubsQueen,
    ClubsJack,
    ClubsNine,
    ClubsEight,
    ClubsSeven,
    SpadesAce,
    SpadesTen,
    SpadesKing,
    SpadesQueen,
    SpadesJack,
    SpadesNine,
    SpadesEight,
    SpadesSeven,
    HeartsAce,
    HeartsTen,
    HeartsKing,
    HeartsQueen,
    HeartsJack,
    HeartsNine,
    HeartsEight,
    HeartsSeven,
    DiamondsAce,
    DiamondsTen,
    DiamondsKing,
    DiamondsQueen,
    DiamondsJack,
    DiamondsNine,
    DiamondsEight,
    DiamondsSeven,
}

enum Game {
    Suit,
    Grand,
    Null,
}

enum PlayerId {
    A,
    B,
    C,
}

struct Player {
    id: u8,
    cards: Vec<u8>,
}

impl Player {
    fn print_cards(&self) {
        match self.id {
            0 => println!("player A:"),
            1 => println!("player B:"),
            2 => println!("player C:"),
            _ => panic!("Unknown player {}", self.id),
            }
        for index in 0..10 {
            print!("{}:", index);
            print_card(self.cards[index]);
        }
    }
}

struct PlayerBuilder {
    id: u8,
    cards: Vec<u8>,
}

impl PlayerBuilder {
    fn new() -> PlayerBuilder {
        PlayerBuilder { cards: Vec::new(), id: 3, }
    }

    fn add(&mut self, newCard: u8) -> &mut PlayerBuilder {
        self.cards.push(newCard);
        self
    }

    fn id(&mut self, newId: u8) -> &mut PlayerBuilder {
        self.id = newId;
        self
    }

    fn finalize(&self) -> Player {
        Player { id: self.id, cards: self.cards.to_vec(), }
    }
}

fn announce(player: u8) -> Game {
    Game::Suit
}

fn bid(dealer: u8) -> (u8, u8) {
    let winner: u8 = dealer;
    let highest: u8 = 18;
    // TODO
    (winner, highest)
}

fn deal(dealerId: u8) {
    let mut cards: Vec<u8> = Vec::new();
    // initialize cards
    for n in 0..32 {
        cards.push(n);
    }
    // shuffle cards
    let mut upper: u8 = 32;
    let mut shuffled: Vec<u8> = Vec::new();
    for n in 0..32 {
        // randomly select card
        let pile_index: u8 = rand::thread_rng().gen_range(0, upper - n);
        // remove selected card from old pile
        let card = cards.remove(pile_index as usize);
        // add selected card to new pile
        shuffled.push(card);
    }
    // create dealer with the first 10 cards
    let dealer = PlayerBuilder::new()
        .id(dealerId)
        .add(shuffled[0])
        .add(shuffled[1])
        .add(shuffled[2])
        .add(shuffled[3])
        .add(shuffled[4])
        .add(shuffled[5])
        .add(shuffled[6])
        .add(shuffled[7])
        .add(shuffled[8])
        .add(shuffled[9])
        .finalize();
    // let the dealer print his own cards
    dealer.print_cards();
    println!("");
    // create the left player (will play first card)
    let left = PlayerBuilder::new()
        .id((dealerId + 1) % 3)
        .add(shuffled[10])
        .add(shuffled[11])
        .add(shuffled[12])
        .add(shuffled[13])
        .add(shuffled[14])
        .add(shuffled[15])
        .add(shuffled[16])
        .add(shuffled[17])
        .add(shuffled[18])
        .add(shuffled[19])
        .finalize();
    left.print_cards();
    println!("");
    // create the right player (will play bid first)
    let right = PlayerBuilder::new()
        .id((dealerId + 2) % 3)
        .add(shuffled[10])
        .add(shuffled[11])
        .add(shuffled[12])
        .add(shuffled[13])
        .add(shuffled[14])
        .add(shuffled[15])
        .add(shuffled[16])
        .add(shuffled[17])
        .add(shuffled[18])
        .add(shuffled[19])
        .finalize();
    right.print_cards();
    println!("");
    // Skat
    println!("Skat:");
    for n in 30..32 {
        print_card(shuffled[n]);
    };
    println!("");
}

fn print_card(card: u8) {
    let club    = "♣";
    let spade   = "♠";
    let heart   = "♥";
    let diamond = "♦";
    match card {
        0 => {
            let mut ace = " A".to_string();
            ace.push_str(club);
            print!("{} ", Black.bold().paint(&ace));
        },
        1 => {
            let mut ten = "10".to_string();
            ten.push_str(club);
            print!("{} ", Black.bold().paint(&ten));
        },
        2 => {
            let mut king = " K".to_string();
            king.push_str(club);
            print!("{} ", Black.bold().paint(&king));
        },
        3 => {
            let mut queen = " Q".to_string();
            queen.push_str(club);
            print!("{} ", Black.bold().paint(&queen));
        },
        4 => {
            let mut jack = " J".to_string();
            jack.push_str(club);
            print!("{} ", Black.bold().paint(&jack));
        },
        5 => {
            let mut nine = " 9".to_string();
            nine.push_str(club);
            print!("{} ", Black.bold().paint(&nine));
        },
        6 => {
            let mut eight = " 8".to_string();
            eight.push_str(club);
            print!("{} ", Black.bold().paint(&eight));
        },
        7 => {
            let mut seven = " 7".to_string();
            seven.push_str(club);
            print!("{} ", Black.bold().paint(&seven));
        },
        8 => {
            let mut ace = " A".to_string();
            ace.push_str(spade);
            print!("{} ", Green.bold().paint(&ace));
        },
        9 => {
            let mut ten = "10".to_string();
            ten.push_str(spade);
            print!("{} ", Green.bold().paint(&ten));
        },
        10 => {
            let mut king = " K".to_string();
            king.push_str(spade);
            print!("{} ", Green.bold().paint(&king));
        },
        11 => {
            let mut queen = " Q".to_string();
            queen.push_str(spade);
            print!("{} ", Green.bold().paint(&queen));
        },
        12 => {
            let mut jack = " J".to_string();
            jack.push_str(spade);
            print!("{} ", Green.bold().paint(&jack));
        },
        13 => {
            let mut nine = " 9".to_string();
            nine.push_str(spade);
            print!("{} ", Green.bold().paint(&nine));
        },
        14 => {
            let mut eight = " 8".to_string();
            eight.push_str(spade);
            print!("{} ", Green.bold().paint(&eight));
        },
        15 => {
            let mut seven = " 7".to_string();
            seven.push_str(spade);
            print!("{} ", Green.bold().paint(&seven));
        },
        16 => {
            let mut ace = " A".to_string();
            ace.push_str(heart);
            print!("{} ", Red.bold().paint(&ace));
        },
        17 => {
            let mut ten = "10".to_string();
            ten.push_str(heart);
            print!("{} ", Red.bold().paint(&ten));
        },
        18 => {
            let mut king = " K".to_string();
            king.push_str(heart);
            print!("{} ", Red.bold().paint(&king));
        },
        19 => {
            let mut queen = " Q".to_string();
            queen.push_str(heart);
            print!("{} ", Red.bold().paint(&queen));
        },
        20 => {
            let mut jack = " J".to_string();
            jack.push_str(heart);
            print!("{} ", Red.bold().paint(&jack));
        },
        21 => {
            let mut nine = " 9".to_string();
            nine.push_str(heart);
            print!("{} ", Red.bold().paint(&nine));
        },
        22 => {
            let mut eight = " 8".to_string();
            eight.push_str(heart);
            print!("{} ", Red.bold().paint(&eight));
        },
        23 => {
            let mut seven = " 7".to_string();
            seven.push_str(heart);
            print!("{} ", Red.bold().paint(&seven));
        },
        24 => {
            let mut ace = " A".to_string();
            ace.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&ace));
        },
        25 => {
            let mut ten = "10".to_string();
            ten.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&ten));
        },
        26 => {
            let mut king = " K".to_string();
            king.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&king));
        },
        27 => {
            let mut queen = " Q".to_string();
            queen.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&queen));
        },
        28 => {
            let mut jack = " J".to_string();
            jack.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&jack));
        },
        29 => {
            let mut nine = " 9".to_string();
            nine.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&nine));
        },
        30 => {
            let mut eight = " 8".to_string();
            eight.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&eight));
        },
        31 => {
            let mut seven = " 7".to_string();
            seven.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&seven));
        },
        _ => panic!("Unknown card"),
    }
}

fn main() {
    // randomly select player
    let player_id: u8 = rand::thread_rng().gen_range(0, 3);
    loop {
        // player with player_id is dealing
        deal(player_id);
        // bid
        let (player, bid) = bid(player_id);
        // announce
        let game = announce(player);
        // play 10 tricks in a row
        for trick in 0..10 {
            println!("trick #{}:", trick);
            // ask for input
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                .ok()
                .expect("failed to read line");
            let input: u8 = match input.trim().parse() {
                Ok(num) => num,
                Err(_) => break,
            };
            // is input valid?
        };
        println!("New game?");
        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .ok()
            .expect("failed to read line");
        let input: u8 = match input.trim().parse() {
            Ok(num) => num,
            Err(_) => break,
        };
        println!("your input: {}", input);
        if input != 1 {
            break;
        }
    }
}
<commit_msg>Print cards before and after sorting them.<commit_after>extern crate ansi_term;
extern crate rand;

use ansi_term::Colour::*;
use rand::Rng;
use std::io;

enum Card {
    ClubsAce,      //  0
    ClubsTen,      //  1
    ClubsKing,     //  2
    ClubsQueen,    //  3
    ClubsJack,     //  4
    ClubsNine,     //  5
    ClubsEight,    //  6
    ClubsSeven,    //  7
    SpadesAce,     //  8
    SpadesTen,     //  9
    SpadesKing,    // 10
    SpadesQueen,   // 11
    SpadesJack,    // 12
    SpadesNine,    // 13
    SpadesEight,   // 14
    SpadesSeven,   // 15
    HeartsAce,     // 16
    HeartsTen,     // 17
    HeartsKing,    // 18
    HeartsQueen,   // 19
    HeartsJack,    // 20
    HeartsNine,    // 21
    HeartsEight,   // 22
    HeartsSeven,   // 23
    DiamondsAce,   // 24
    DiamondsTen,   // 25
    DiamondsKing,  // 26
    DiamondsQueen, // 27
    DiamondsJack,  // 28
    DiamondsNine,  // 29
    DiamondsEight, // 30
    DiamondsSeven, // 31
}

enum Game {
    Suit,
    Grand,
    Null,
}

enum PlayerId {
    A,
    B,
    C,
}

struct Player {
    id: u8,
    cards: Vec<u8>,
}

impl Player {
    fn print_cards(&self) {
        match self.id {
            0 => println!("player A:"),
            1 => println!("player B:"),
            2 => println!("player C:"),
            _ => panic!("Unknown player {}", self.id),
            }
        for index in 0..10 {
            print!("{}:", index);
            print_card(self.cards[index]);
        }
    }
    fn sort_cards(&mut self) {
        let mut sorted: Vec<u8> = Vec::new();
        let mut clubs: Vec<u8> = Vec::new();
        let mut spades: Vec<u8> = Vec::new();
        let mut hearts: Vec<u8> = Vec::new();
        let mut diamonds: Vec<u8> = Vec::new();
        // first find Jacks
        for n in 0..10 {
            match self.cards[n] {
                // ClubsJack
                4 => sorted.push(self.cards[n]),
                // SpadesJack
                12 => sorted.push(self.cards[n]),
                // HeartsJack
                20 => sorted.push(self.cards[n]),
                // DiamondsJack
                28 => sorted.push(self.cards[n]),
                // Clubs
                0 ... 7 => clubs.push(self.cards[n]),
                // Spades
                8 ... 15 => spades.push(self.cards[n]),
                // Hearts
                16 ... 23 => hearts.push(self.cards[n]),
                // Diamonds
                24 ... 31 => diamonds.push(self.cards[n]),
                _ => panic!("Unknown card"),
            }
        }
        clubs.sort();
        //clubs.reverse();
        spades.sort();
        //spades.reverse();
        hearts.sort();
        //hearts.reverse();
        diamonds.sort();
        //diamonds.reverse();
        // then add the suit with the highest count
        let empty: Vec<u8> = Vec::new();
        let mut highest: &Vec<u8> = ∅
        let mut max: u8 = 0u8;
        if clubs.len() > max as usize {
            max = clubs.len() as u8;
            highest = ♣
        }
        if spades.len() > max as usize {
            max = spades.len() as u8;
            highest = ♠
        }
        if hearts.len() > max as usize {
            max = hearts.len() as u8;
            highest = ♥
        }
        if diamonds.len() > max as usize {
            max = diamonds.len() as u8;
            highest = &diamonds;
        }
        // append highest
        if highest == &clubs {
            // append clubs
            for n in 0..clubs.len() {
                sorted.push(clubs[n]);
            }
        }
        if highest == &spades {
            // append spades
            for n in 0..spades.len() {
                sorted.push(spades[n]);
            }
        }
        if highest == &hearts {
            // append hearts
            for n in 0..hearts.len() {
                sorted.push(hearts[n]);
            }
        }
        if highest == &diamonds {
            // append diamonds
            for n in 0..diamonds.len() {
                sorted.push(diamonds[n]);
            }
        }
        // append others
        if highest != &clubs {
            // append clubs
            for n in 0..clubs.len() {
                sorted.push(clubs[n]);
            }
        }
        if highest != &spades {
            // append spades
            for n in 0..spades.len() {
                sorted.push(spades[n]);
            }
        }
        if highest != &hearts {
            // append hearts
            for n in 0..hearts.len() {
                sorted.push(hearts[n]);
            }
        }
        if highest != &diamonds {
            // append diamonds
            for n in 0..diamonds.len() {
                sorted.push(diamonds[n]);
            }
        }
        self.cards = sorted;
    }
}

struct PlayerBuilder {
    id: u8,
    cards: Vec<u8>,
}

impl PlayerBuilder {
    fn new() -> PlayerBuilder {
        PlayerBuilder { cards: Vec::new(), id: 3, }
    }

    fn add(&mut self, newCard: u8) -> &mut PlayerBuilder {
        self.cards.push(newCard);
        self
    }

    fn id(&mut self, newId: u8) -> &mut PlayerBuilder {
        self.id = newId;
        self
    }

    fn finalize(&self) -> Player {
        Player { id: self.id, cards: self.cards.to_vec(), }
    }
}

fn announce(player: u8) -> Game {
    Game::Suit
}

fn bid(dealer: u8) -> (u8, u8) {
    let winner: u8 = dealer;
    let highest: u8 = 18;
    // TODO
    (winner, highest)
}

fn deal(dealerId: u8) {
    let mut cards: Vec<u8> = Vec::new();
    // initialize cards
    for n in 0..32 {
        cards.push(n);
    }
    // shuffle cards
    let mut upper: u8 = 32;
    let mut shuffled: Vec<u8> = Vec::new();
    for n in 0..32 {
        // randomly select card
        let pile_index: u8 = rand::thread_rng().gen_range(0, upper - n);
        // remove selected card from old pile
        let card = cards.remove(pile_index as usize);
        // add selected card to new pile
        shuffled.push(card);
    }
    // create dealer with the first 10 cards
    let mut dealer = PlayerBuilder::new()
        .id(dealerId)
        .add(shuffled[0])
        .add(shuffled[1])
        .add(shuffled[2])
        .add(shuffled[3])
        .add(shuffled[4])
        .add(shuffled[5])
        .add(shuffled[6])
        .add(shuffled[7])
        .add(shuffled[8])
        .add(shuffled[9])
        .finalize();
    // let the dealer print his own cards
    dealer.print_cards();
    dealer.sort_cards();
    println!("");
    dealer.print_cards();
    println!("");
    // create the left player (will play first card)
    let mut left = PlayerBuilder::new()
        .id((dealerId + 1) % 3)
        .add(shuffled[10])
        .add(shuffled[11])
        .add(shuffled[12])
        .add(shuffled[13])
        .add(shuffled[14])
        .add(shuffled[15])
        .add(shuffled[16])
        .add(shuffled[17])
        .add(shuffled[18])
        .add(shuffled[19])
        .finalize();
    left.print_cards();
    left.sort_cards();
    println!("");
    left.print_cards();
    println!("");
    // create the right player (will play bid first)
    let mut right = PlayerBuilder::new()
        .id((dealerId + 2) % 3)
        .add(shuffled[10])
        .add(shuffled[11])
        .add(shuffled[12])
        .add(shuffled[13])
        .add(shuffled[14])
        .add(shuffled[15])
        .add(shuffled[16])
        .add(shuffled[17])
        .add(shuffled[18])
        .add(shuffled[19])
        .finalize();
    right.print_cards();
    right.sort_cards();
    println!("");
    right.print_cards();
    println!("");
    // Skat
    println!("Skat:");
    for n in 30..32 {
        print_card(shuffled[n]);
    };
    println!("");
}

fn print_card(card: u8) {
    let club    = "♣";
    let spade   = "♠";
    let heart   = "♥";
    let diamond = "♦";
    match card {
        0 => {
            let mut ace = " A".to_string();
            ace.push_str(club);
            print!("{} ", Black.bold().paint(&ace));
        },
        1 => {
            let mut ten = "10".to_string();
            ten.push_str(club);
            print!("{} ", Black.bold().paint(&ten));
        },
        2 => {
            let mut king = " K".to_string();
            king.push_str(club);
            print!("{} ", Black.bold().paint(&king));
        },
        3 => {
            let mut queen = " Q".to_string();
            queen.push_str(club);
            print!("{} ", Black.bold().paint(&queen));
        },
        4 => {
            let mut jack = " J".to_string();
            jack.push_str(club);
            print!("{} ", Black.bold().paint(&jack));
        },
        5 => {
            let mut nine = " 9".to_string();
            nine.push_str(club);
            print!("{} ", Black.bold().paint(&nine));
        },
        6 => {
            let mut eight = " 8".to_string();
            eight.push_str(club);
            print!("{} ", Black.bold().paint(&eight));
        },
        7 => {
            let mut seven = " 7".to_string();
            seven.push_str(club);
            print!("{} ", Black.bold().paint(&seven));
        },
        8 => {
            let mut ace = " A".to_string();
            ace.push_str(spade);
            print!("{} ", Green.bold().paint(&ace));
        },
        9 => {
            let mut ten = "10".to_string();
            ten.push_str(spade);
            print!("{} ", Green.bold().paint(&ten));
        },
        10 => {
            let mut king = " K".to_string();
            king.push_str(spade);
            print!("{} ", Green.bold().paint(&king));
        },
        11 => {
            let mut queen = " Q".to_string();
            queen.push_str(spade);
            print!("{} ", Green.bold().paint(&queen));
        },
        12 => {
            let mut jack = " J".to_string();
            jack.push_str(spade);
            print!("{} ", Green.bold().paint(&jack));
        },
        13 => {
            let mut nine = " 9".to_string();
            nine.push_str(spade);
            print!("{} ", Green.bold().paint(&nine));
        },
        14 => {
            let mut eight = " 8".to_string();
            eight.push_str(spade);
            print!("{} ", Green.bold().paint(&eight));
        },
        15 => {
            let mut seven = " 7".to_string();
            seven.push_str(spade);
            print!("{} ", Green.bold().paint(&seven));
        },
        16 => {
            let mut ace = " A".to_string();
            ace.push_str(heart);
            print!("{} ", Red.bold().paint(&ace));
        },
        17 => {
            let mut ten = "10".to_string();
            ten.push_str(heart);
            print!("{} ", Red.bold().paint(&ten));
        },
        18 => {
            let mut king = " K".to_string();
            king.push_str(heart);
            print!("{} ", Red.bold().paint(&king));
        },
        19 => {
            let mut queen = " Q".to_string();
            queen.push_str(heart);
            print!("{} ", Red.bold().paint(&queen));
        },
        20 => {
            let mut jack = " J".to_string();
            jack.push_str(heart);
            print!("{} ", Red.bold().paint(&jack));
        },
        21 => {
            let mut nine = " 9".to_string();
            nine.push_str(heart);
            print!("{} ", Red.bold().paint(&nine));
        },
        22 => {
            let mut eight = " 8".to_string();
            eight.push_str(heart);
            print!("{} ", Red.bold().paint(&eight));
        },
        23 => {
            let mut seven = " 7".to_string();
            seven.push_str(heart);
            print!("{} ", Red.bold().paint(&seven));
        },
        24 => {
            let mut ace = " A".to_string();
            ace.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&ace));
        },
        25 => {
            let mut ten = "10".to_string();
            ten.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&ten));
        },
        26 => {
            let mut king = " K".to_string();
            king.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&king));
        },
        27 => {
            let mut queen = " Q".to_string();
            queen.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&queen));
        },
        28 => {
            let mut jack = " J".to_string();
            jack.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&jack));
        },
        29 => {
            let mut nine = " 9".to_string();
            nine.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&nine));
        },
        30 => {
            let mut eight = " 8".to_string();
            eight.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&eight));
        },
        31 => {
            let mut seven = " 7".to_string();
            seven.push_str(diamond);
            print!("{} ", Yellow.bold().paint(&seven));
        },
        _ => panic!("Unknown card"),
    }
}

fn main() {
    // randomly select player
    let player_id: u8 = rand::thread_rng().gen_range(0, 3);
    loop {
        // player with player_id is dealing
        deal(player_id);
        // bid
        let (player, bid) = bid(player_id);
        // announce
        let game = announce(player);
        // play 10 tricks in a row
        for trick in 0..10 {
            println!("trick #{}:", trick);
            // ask for input
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                .ok()
                .expect("failed to read line");
            let input: u8 = match input.trim().parse() {
                Ok(num) => num,
                Err(_) => break,
            };
            // is input valid?
        };
        println!("New game?");
        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .ok()
            .expect("failed to read line");
        let input: u8 = match input.trim().parse() {
            Ok(num) => num,
            Err(_) => break,
        };
        println!("your input: {}", input);
        if input != 1 {
            break;
        }
    }
}
<|endoftext|>


<commit_before>use crate::utils::{match_qpath, paths, snippet, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Checks usage of `std::fs::create_dir` and suggest using `std::fs::create_dir_all` instead.
    ///
    /// **Why is this bad?** Sometimes `std::fs::crate_dir` is mistakenly chosen over `std::fs::create_dir_all`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// std::fs::create_dir("foo");
    /// ```
    /// Use instead:
    /// ```rust
    /// std::fs::create_dir_all("foo");
    /// ```
    pub CREATE_DIR,
    restriction,
    "calling `std::fs::create_dir` instead of `std::fs::create_dir_all`"
}

declare_lint_pass!(CreateDir => [CREATE_DIR]);

impl LateLintPass<'_> for CreateDir {
    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
        if_chain! {
            if let ExprKind::Call(ref func, ref args) = expr.kind;
            if let ExprKind::Path(ref path) = func.kind;
            if match_qpath(path, &paths::STD_FS_CREATE_DIR);
            then {
                span_lint_and_sugg(
                    cx,
                    CREATE_DIR,
                    expr.span,
                    "calling `std::fs::create_dir` where there may be a better way",
                    "consider calling `std::fs::create_dir_all` instead",
                    format!("std::fs::create_dir_all({})", snippet(cx, args[0].span, "..")),
                    Applicability::MachineApplicable,
                )
            }
        }
    }
}
<commit_msg>Downgrade applicability of `create_dir`<commit_after>use crate::utils::{match_qpath, paths, snippet, span_lint_and_sugg};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
    /// **What it does:** Checks usage of `std::fs::create_dir` and suggest using `std::fs::create_dir_all` instead.
    ///
    /// **Why is this bad?** Sometimes `std::fs::crate_dir` is mistakenly chosen over `std::fs::create_dir_all`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// std::fs::create_dir("foo");
    /// ```
    /// Use instead:
    /// ```rust
    /// std::fs::create_dir_all("foo");
    /// ```
    pub CREATE_DIR,
    restriction,
    "calling `std::fs::create_dir` instead of `std::fs::create_dir_all`"
}

declare_lint_pass!(CreateDir => [CREATE_DIR]);

impl LateLintPass<'_> for CreateDir {
    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
        if_chain! {
            if let ExprKind::Call(ref func, ref args) = expr.kind;
            if let ExprKind::Path(ref path) = func.kind;
            if match_qpath(path, &paths::STD_FS_CREATE_DIR);
            then {
                span_lint_and_sugg(
                    cx,
                    CREATE_DIR,
                    expr.span,
                    "calling `std::fs::create_dir` where there may be a better way",
                    "consider calling `std::fs::create_dir_all` instead",
                    format!("std::fs::create_dir_all({})", snippet(cx, args[0].span, "..")),
                    Applicability::MaybeIncorrect,
                )
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (C) 2016  ParadoxSpiral
//
// This file is part of mpv-rs.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use mpv;
use mpv::{MpvInstance, MpvError, Parent, PlaylistOp};
use mpv::utils;
use mpv::protocol::*;

use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::mem;
use std::path::Path;
use std::slice;
use std::time::Duration;
use std::thread;

fn open(cookie: *mut File, _: &mut (), uri: &str) -> Result<(), MpvError> {
    unsafe {
        // Strip the `filereader://` part
        *cookie = File::open(&uri[13..]).unwrap()
    };
    println!("Opened file, ready for orders o7");
    Ok(())
}

fn close(_: Box<File>) {
    println!("Closing file, bye bye~~");
}

fn read(cookie: &mut File, buf: *mut i8, nbytes: u64) -> i64 {
    unsafe {
        let slice = slice::from_raw_parts_mut(buf, nbytes as _);
        let forbidden_magic = mem::transmute::<&mut [i8], &mut [u8]>(slice);

        cookie.read(forbidden_magic).unwrap() as _
    }
}

fn seek(cookie: &mut File, offset: i64) -> i64 {
    cookie.seek(SeekFrom::Start(offset as u64)).unwrap() as _
}

fn size(cookie: &mut File) -> i64 {
    cookie.metadata().unwrap().len() as _
}

pub fn exec() {
    let path = format!("filereader://{}", ::std::env::args().nth(1).unwrap());

    let protocol = unsafe {
        Protocol::new("filereader".into(),
                      (),
                      box open,
                      box close,
                      box read,
                      Some(box seek),
                      Some(box size))
    };

    let mpv = Parent::new(false).unwrap();
    mpv.register_protocol(protocol).unwrap();

    mpv.set_property("volume", 40).unwrap();

    mpv.playlist(&PlaylistOp::Loadfiles(&[utils::File::new(Path::new(&path),
                                                           utils::FileState::AppendPlay,
                                                           None)]))
       .unwrap();

    thread::sleep(Duration::from_secs(10));

    mpv.seek(&mpv::Seek::RelativeForward(Duration::from_secs(15))).unwrap();

    thread::sleep(Duration::from_secs(5));
}
<commit_msg>Lower volume in protocol example<commit_after>// Copyright (C) 2016  ParadoxSpiral
//
// This file is part of mpv-rs.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use mpv;
use mpv::{MpvInstance, MpvError, Parent, PlaylistOp};
use mpv::utils;
use mpv::protocol::*;

use std::fs::File;
use std::io::{Read, Seek, SeekFrom};
use std::mem;
use std::path::Path;
use std::slice;
use std::time::Duration;
use std::thread;

fn open(cookie: *mut File, _: &mut (), uri: &str) -> Result<(), MpvError> {
    unsafe {
        // Strip the `filereader://` part
        *cookie = File::open(&uri[13..]).unwrap()
    };
    println!("Opened file, ready for orders o7");
    Ok(())
}

fn close(_: Box<File>) {
    println!("Closing file, bye bye~~");
}

fn read(cookie: &mut File, buf: *mut i8, nbytes: u64) -> i64 {
    unsafe {
        let slice = slice::from_raw_parts_mut(buf, nbytes as _);
        let forbidden_magic = mem::transmute::<&mut [i8], &mut [u8]>(slice);

        cookie.read(forbidden_magic).unwrap() as _
    }
}

fn seek(cookie: &mut File, offset: i64) -> i64 {
    cookie.seek(SeekFrom::Start(offset as u64)).unwrap() as _
}

fn size(cookie: &mut File) -> i64 {
    cookie.metadata().unwrap().len() as _
}

pub fn exec() {
    let path = format!("filereader://{}", ::std::env::args().nth(1).unwrap());

    let protocol = unsafe {
        Protocol::new("filereader".into(),
                      (),
                      box open,
                      box close,
                      box read,
                      Some(box seek),
                      Some(box size))
    };

    let mpv = Parent::new(false).unwrap();
    mpv.register_protocol(protocol).unwrap();

    mpv.set_property("volume", 30).unwrap();

    mpv.playlist(&PlaylistOp::Loadfiles(&[utils::File::new(Path::new(&path),
                                                           utils::FileState::AppendPlay,
                                                           None)]))
       .unwrap();

    thread::sleep(Duration::from_secs(10));

    mpv.seek(&mpv::Seek::RelativeForward(Duration::from_secs(15))).unwrap();

    thread::sleep(Duration::from_secs(5));
}
<|endoftext|>


<commit_before>//! Implementation of a simple uTP client and server.

extern crate utp;
use std::old_io::net::ip::{Ipv4Addr, SocketAddr};

macro_rules! iotry {
    ($e:expr) => (match $e { Ok(v) => v, Err(e) => panic!("{}", e), })
}

fn usage() {
    println!("Usage: utp [-s|-c] <address> <port>");
}

fn main() {
    use utp::UtpStream;
    use std::str::FromStr;
    use std::old_io::{stdin, stdout, stderr};

    enum Mode {
        Server,
        Client
    }
    let mut mode: Mode;

    // Provide a default address
    let mut addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 };

    let args = std::os::args();
    let mut args = args.iter().map(|arg| arg.as_slice());

    // Skip program name
    args.next();

    match args.next() {
        Some("-s") => mode = Mode::Server,
        Some("-c") => mode = Mode::Client,
        _ => { usage(); return; }
    }

    match args.collect::<Vec<_>>().as_slice() {
        [] => (),
        [ip, port] => {
            let ip = match FromStr::from_str(ip) {
                Ok(x) => x,
                Err(_) => { println!("Invalid address"); return }
            };
            let port = match FromStr::from_str(port) {
                Ok(x) => x,
                Err(_) => { println!("Invalid port"); return }
            };
            addr = SocketAddr {
                ip:   ip,
                port: port,
            };
        }
        _ => { usage(); return; }
    }

    match mode {
        Mode::Server => {
            let mut stream = UtpStream::bind(addr);
            let mut writer = stdout();
            let _ = writeln!(&mut stderr(), "Serving on {}", addr);

            let payload = iotry!(stream.read_to_end());
            iotry!(writer.write(payload.as_slice()));
        }
        Mode::Client => {
            let mut stream = iotry!(UtpStream::connect(addr));
            let mut reader = stdin();

            let payload = iotry!(reader.read_to_end());
            iotry!(stream.write(payload.as_slice()));
            iotry!(stream.close());
            drop(stream);
        }
    }
}
<commit_msg>Use `stdin`, `stdout` and `stderr` from the new io module.<commit_after>//! Implementation of a simple uTP client and server.

extern crate utp;
use std::old_io::net::ip::{Ipv4Addr, SocketAddr};

macro_rules! iotry {
    ($e:expr) => (match $e { Ok(v) => v, Err(e) => panic!("{}", e), })
}

fn usage() {
    println!("Usage: utp [-s|-c] <address> <port>");
}

fn main() {
    use utp::UtpStream;
    use std::str::FromStr;
    use std::io::{stdin, stdout, stderr, Read, Write};

    enum Mode {
        Server,
        Client
    }
    let mut mode: Mode;

    // Provide a default address
    let mut addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 8080 };

    let args = std::os::args();
    let mut args = args.iter().map(|arg| arg.as_slice());

    // Skip program name
    args.next();

    match args.next() {
        Some("-s") => mode = Mode::Server,
        Some("-c") => mode = Mode::Client,
        _ => { usage(); return; }
    }

    match args.collect::<Vec<_>>().as_slice() {
        [] => (),
        [ip, port] => {
            let ip = match FromStr::from_str(ip) {
                Ok(x) => x,
                Err(_) => { println!("Invalid address"); return }
            };
            let port = match FromStr::from_str(port) {
                Ok(x) => x,
                Err(_) => { println!("Invalid port"); return }
            };
            addr = SocketAddr {
                ip:   ip,
                port: port,
            };
        }
        _ => { usage(); return; }
    }

    match mode {
        Mode::Server => {
            let mut stream = UtpStream::bind(addr);
            let mut writer = stdout();
            let _ = writeln!(&mut stderr(), "Serving on {}", addr);

            let payload = iotry!(stream.read_to_end());
            iotry!(writer.write(payload.as_slice()));
        }
        Mode::Client => {
            let mut stream = iotry!(UtpStream::connect(addr));
            let mut reader = stdin();

            let mut payload = vec!();
            iotry!(reader.read_to_end(&mut payload));
            iotry!(stream.write(payload.as_slice()));
            iotry!(stream.close());
            drop(stream);
        }
    }
}
<|endoftext|>


<commit_before>//! Tests for --unit-graph option.

use cargo_test_support::project;
use cargo_test_support::registry::Package;

#[cargo_test]
fn gated() {
    let p = project().file("src/lib.rs", "").build();
    p.cargo("build --unit-graph")
        .with_status(101)
        .with_stderr(
            "\
[ERROR] the `--unit-graph` flag is unstable[..]
See [..]
See [..]
",
        )
        .run();
}

#[cargo_test]
fn simple() {
    Package::new("a", "1.0.0")
        .dep("b", "1.0")
        .feature("feata", &["b/featb"])
        .publish();
    Package::new("b", "1.0.0")
        .dep("c", "1.0")
        .feature("featb", &["c/featc"])
        .publish();
    Package::new("c", "1.0.0").feature("featc", &[]).publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [dependencies]
            a = "1.0"
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build --features a/feata --unit-graph -Zunstable-options")
        .masquerade_as_nightly_cargo()
        .with_json(
            r#"{
              "version": 1,
              "units": [
                {
                  "pkg_id": "a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
                  "target": {
                    "kind": [
                      "lib"
                    ],
                    "crate_types": [
                      "lib"
                    ],
                    "name": "a",
                    "src_path": "[..]/a-1.0.0/src/lib.rs",
                    "edition": "2015",
                    "doc": true,
                    "doctest": true,
                    "test": true
                  },
                  "profile": {
                    "name": "dev",
                    "opt_level": "0",
                    "lto": "false",
                    "codegen_units": null,
                    "debuginfo": 2,
                    "debug_assertions": true,
                    "overflow_checks": true,
                    "rpath": false,
                    "incremental": false,
                    "panic": "unwind",
                    "strip": "none",
                    "split_debuginfo": "{...}"
                  },
                  "platform": null,
                  "mode": "build",
                  "features": [
                    "feata"
                  ],
                  "dependencies": [
                    {
                      "index": 1,
                      "extern_crate_name": "b",
                      "public": false,
                      "noprelude": false
                    }
                  ]
                },
                {
                  "pkg_id": "b 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
                  "target": {
                    "kind": [
                      "lib"
                    ],
                    "crate_types": [
                      "lib"
                    ],
                    "name": "b",
                    "src_path": "[..]/b-1.0.0/src/lib.rs",
                    "edition": "2015",
                    "doc": true,
                    "doctest": true,
                    "test": true
                  },
                  "profile": {
                    "name": "dev",
                    "opt_level": "0",
                    "lto": "false",
                    "codegen_units": null,
                    "debuginfo": 2,
                    "debug_assertions": true,
                    "overflow_checks": true,
                    "rpath": false,
                    "incremental": false,
                    "panic": "unwind",
                    "strip": "none",
                    "split_debuginfo": "{...}"
                  },
                  "platform": null,
                  "mode": "build",
                  "features": [
                    "featb"
                  ],
                  "dependencies": [
                    {
                      "index": 2,
                      "extern_crate_name": "c",
                      "public": false,
                      "noprelude": false
                    }
                  ]
                },
                {
                  "pkg_id": "c 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
                  "target": {
                    "kind": [
                      "lib"
                    ],
                    "crate_types": [
                      "lib"
                    ],
                    "name": "c",
                    "src_path": "[..]/c-1.0.0/src/lib.rs",
                    "edition": "2015",
                    "test": true,
                    "doc": true,
                    "doctest": true
                  },
                  "profile": {
                    "name": "dev",
                    "opt_level": "0",
                    "lto": "false",
                    "codegen_units": null,
                    "debuginfo": 2,
                    "debug_assertions": true,
                    "overflow_checks": true,
                    "rpath": false,
                    "incremental": false,
                    "panic": "unwind",
                    "strip": "none",
                    "split_debuginfo": "{...}"
                  },
                  "platform": null,
                  "mode": "build",
                  "features": [
                    "featc"
                  ],
                  "dependencies": []
                },
                {
                  "pkg_id": "foo 0.1.0 (path+file://[..]/foo)",
                  "target": {
                    "kind": [
                      "lib"
                    ],
                    "crate_types": [
                      "lib"
                    ],
                    "name": "foo",
                    "src_path": "[..]/foo/src/lib.rs",
                    "edition": "2015",
                    "test": true,
                    "doc": true,
                    "doctest": true
                  },
                  "profile": {
                    "name": "dev",
                    "opt_level": "0",
                    "lto": "false",
                    "codegen_units": null,
                    "debuginfo": 2,
                    "debug_assertions": true,
                    "overflow_checks": true,
                    "rpath": false,
                    "incremental": false,
                    "panic": "unwind",
                    "strip": "none",
                    "split_debuginfo": "{...}"
                  },
                  "platform": null,
                  "mode": "build",
                  "features": [],
                  "dependencies": [
                    {
                      "index": 0,
                      "extern_crate_name": "a",
                      "public": false,
                      "noprelude": false
                    }
                  ]
                }
              ],
              "roots": [3]
            }
            "#,
        )
        .run();
}
<commit_msg>Update test<commit_after>//! Tests for --unit-graph option.

use cargo_test_support::project;
use cargo_test_support::registry::Package;

#[cargo_test]
fn gated() {
    let p = project().file("src/lib.rs", "").build();
    p.cargo("build --unit-graph")
        .with_status(101)
        .with_stderr(
            "\
[ERROR] the `--unit-graph` flag is unstable[..]
See [..]
See [..]
",
        )
        .run();
}

#[cargo_test]
fn simple() {
    Package::new("a", "1.0.0")
        .dep("b", "1.0")
        .feature("feata", &["b/featb"])
        .publish();
    Package::new("b", "1.0.0")
        .dep("c", "1.0")
        .feature("featb", &["c/featc"])
        .publish();
    Package::new("c", "1.0.0").feature("featc", &[]).publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [package]
            name = "foo"
            version = "0.1.0"

            [dependencies]
            a = "1.0"
            "#,
        )
        .file("src/lib.rs", "")
        .build();

    p.cargo("build --features a/feata --unit-graph -Zunstable-options")
        .masquerade_as_nightly_cargo()
        .with_json(
            r#"{
              "roots": [
                3
              ],
              "units": [
                {
                  "dependencies": [
                    {
                      "extern_crate_name": "b",
                      "index": 1,
                      "noprelude": false,
                      "public": false
                    }
                  ],
                  "features": [
                    "feata"
                  ],
                  "mode": "build",
                  "pkg_id": "a 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
                  "platform": null,
                  "profile": {
                    "codegen_backend": null,
                    "codegen_units": null,
                    "debug_assertions": true,
                    "debuginfo": 2,
                    "incremental": false,
                    "lto": "false",
                    "name": "dev",
                    "opt_level": "0",
                    "overflow_checks": true,
                    "panic": "unwind",
                    "rpath": false,
                    "split_debuginfo": null,
                    "strip": "none"
                  },
                  "target": {
                    "crate_types": [
                      "lib"
                    ],
                    "doc": true,
                    "doctest": true,
                    "edition": "2015",
                    "kind": [
                      "lib"
                    ],
                    "name": "a",
                    "src_path": "[..]/a-1.0.0/src/lib.rs",
                    "test": true
                  }
                },
                {
                  "dependencies": [
                    {
                      "extern_crate_name": "c",
                      "index": 2,
                      "noprelude": false,
                      "public": false
                    }
                  ],
                  "features": [
                    "featb"
                  ],
                  "mode": "build",
                  "pkg_id": "b 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
                  "platform": null,
                  "profile": {
                    "codegen_backend": null,
                    "codegen_units": null,
                    "debug_assertions": true,
                    "debuginfo": 2,
                    "incremental": false,
                    "lto": "false",
                    "name": "dev",
                    "opt_level": "0",
                    "overflow_checks": true,
                    "panic": "unwind",
                    "rpath": false,
                    "split_debuginfo": null,
                    "strip": "none"
                  },
                  "target": {
                    "crate_types": [
                      "lib"
                    ],
                    "doc": true,
                    "doctest": true,
                    "edition": "2015",
                    "kind": [
                      "lib"
                    ],
                    "name": "b",
                    "src_path": "[..]/b-1.0.0/src/lib.rs",
                    "test": true
                  }
                },
                {
                  "dependencies": [],
                  "features": [
                    "featc"
                  ],
                  "mode": "build",
                  "pkg_id": "c 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
                  "platform": null,
                  "profile": {
                    "codegen_backend": null,
                    "codegen_units": null,
                    "debug_assertions": true,
                    "debuginfo": 2,
                    "incremental": false,
                    "lto": "false",
                    "name": "dev",
                    "opt_level": "0",
                    "overflow_checks": true,
                    "panic": "unwind",
                    "rpath": false,
                    "split_debuginfo": null,
                    "strip": "none"
                  },
                  "target": {
                    "crate_types": [
                      "lib"
                    ],
                    "doc": true,
                    "doctest": true,
                    "edition": "2015",
                    "kind": [
                      "lib"
                    ],
                    "name": "c",
                    "src_path": "[..]/c-1.0.0/src/lib.rs",
                    "test": true
                  }
                },
                {
                  "dependencies": [
                    {
                      "extern_crate_name": "a",
                      "index": 0,
                      "noprelude": false,
                      "public": false
                    }
                  ],
                  "features": [],
                  "mode": "build",
                  "pkg_id": "foo 0.1.0 (path+file://[..]/foo)",
                  "platform": null,
                  "profile": {
                    "codegen_backend": null,
                    "codegen_units": null,
                    "debug_assertions": true,
                    "debuginfo": 2,
                    "incremental": false,
                    "lto": "false",
                    "name": "dev",
                    "opt_level": "0",
                    "overflow_checks": true,
                    "panic": "unwind",
                    "rpath": false,
                    "split_debuginfo": null,
                    "strip": "none"
                  },
                  "target": {
                    "crate_types": [
                      "lib"
                    ],
                    "doc": true,
                    "doctest": true,
                    "edition": "2015",
                    "kind": [
                      "lib"
                    ],
                    "name": "foo",
                    "src_path": "[..]/foo/src/lib.rs",
                    "test": true
                  }
                }
              ],
              "version": 1
            }
            "#,
        )
        .run();
}
<|endoftext|>


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

use std::{collections::HashMap, collections::HashSet};

use crate::{
    conversion::{
        api::{ApiDetail, ParseResults, TypeApiDetails, UnanalyzedApi},
        ConvertError,
    },
    types::make_ident,
    types::Namespace,
    types::TypeName,
};
use autocxx_parser::TypeConfig;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{parse_quote, Fields, Item};

use super::{
    super::{api::Use, utilities::generate_utilities},
    type_converter::TypeConverter,
};

use super::parse_foreign_mod::ParseForeignMod;

/// Parses a bindgen mod in order to understand the APIs within it.
pub(crate) struct ParseBindgen<'a> {
    type_config: &'a TypeConfig,
    results: ParseResults,
    /// Here we track the last struct which bindgen told us about.
    /// Any subsequent "extern 'C'" blocks are methods belonging to that type,
    /// even if the 'this' is actually recorded as void in the
    /// function signature.
    latest_virtual_this_type: Option<TypeName>,
}

impl<'a> ParseBindgen<'a> {
    pub(crate) fn new(type_config: &'a TypeConfig) -> Self {
        ParseBindgen {
            type_config,
            results: ParseResults {
                apis: Vec::new(),
                type_converter: TypeConverter::new(),
                use_stmts_by_mod: HashMap::new(),
            },
            latest_virtual_this_type: None,
        }
    }

    /// Parses items found in the `bindgen` output and returns a set of
    /// `Api`s together with some other data.
    pub(crate) fn parse_items(
        mut self,
        items: Vec<Item>,
        exclude_utilities: bool,
    ) -> Result<ParseResults, ConvertError> {
        let items = Self::find_items_in_root(items)?;
        if !exclude_utilities {
            generate_utilities(&mut self.results.apis);
        }
        let root_ns = Namespace::new();
        self.parse_mod_items(items, root_ns)?;
        Ok(self.results)
    }

    fn find_items_in_root(items: Vec<Item>) -> Result<Vec<Item>, ConvertError> {
        for item in items {
            match item {
                Item::Mod(root_mod) => {
                    // With namespaces enabled, bindgen always puts everything
                    // in a mod called 'root'. We don't want to pass that
                    // onto cxx, so jump right into it.
                    assert!(root_mod.ident == "root");
                    if let Some((_, items)) = root_mod.content {
                        return Ok(items);
                    }
                }
                _ => return Err(ConvertError::UnexpectedOuterItem),
            }
        }
        Ok(Vec::new())
    }

    /// Interpret the bindgen-generated .rs for a particular
    /// mod, which corresponds to a C++ namespace.
    fn parse_mod_items(&mut self, items: Vec<Item>, ns: Namespace) -> Result<(), ConvertError> {
        // This object maintains some state specific to this namespace, i.e.
        // this particular mod.
        let mut mod_converter = ParseForeignMod::new(ns.clone());
        let mut use_statements_for_this_mod = Vec::new();
        for item in items {
            match item {
                Item::ForeignMod(fm) => {
                    mod_converter.convert_foreign_mod_items(
                        fm.items,
                        self.latest_virtual_this_type.clone(),
                    )?;
                }
                Item::Struct(s) => {
                    if s.ident.to_string().ends_with("__bindgen_vtable") {
                        continue;
                    }
                    let tyname = TypeName::new(&ns, &s.ident.to_string());
                    let is_forward_declaration = Self::spot_forward_declaration(&s.fields);
                    // cxx::bridge can't cope with type aliases to generic
                    // types at the moment.
                    self.parse_type(
                        tyname.clone(),
                        is_forward_declaration,
                        HashSet::new(),
                        Some(Item::Struct(s)),
                    );
                    self.latest_virtual_this_type = Some(tyname);
                }
                Item::Enum(e) => {
                    let tyname = TypeName::new(&ns, &e.ident.to_string());
                    self.parse_type(tyname, false, HashSet::new(), Some(Item::Enum(e)));
                }
                Item::Impl(imp) => {
                    // We *mostly* ignore all impl blocks generated by bindgen.
                    // Methods also appear in 'extern "C"' blocks which
                    // we will convert instead. At that time we'll also construct
                    // synthetic impl blocks.
                    // We do however record which methods were spotted, since
                    // we have no other way of working out which functions are
                    // static methods vs plain functions.
                    mod_converter.convert_impl_items(imp);
                }
                Item::Mod(itm) => {
                    if let Some((_, items)) = itm.content {
                        let new_ns = ns.push(itm.ident.to_string());
                        self.parse_mod_items(items, new_ns)?;
                    }
                }
                Item::Use(_) => {
                    use_statements_for_this_mod.push(item);
                }
                Item::Const(const_item) => {
                    // The following puts this constant into
                    // the global namespace which is bug
                    // https://github.com/google/autocxx/issues/133
                    self.results.apis.push(UnanalyzedApi {
                        id: const_item.ident.clone(),
                        ns: ns.clone(),
                        deps: HashSet::new(),
                        use_stmt: Use::Unused,
                        detail: ApiDetail::Const { const_item },
                        additional_cpp: None,
                    });
                }
                Item::Type(mut ity) => {
                    let tyname = TypeName::new(&ns, &ity.ident.to_string());
                    let mut final_type = self
                        .results
                        .type_converter
                        .convert_type(*ity.ty, &ns, false)?;
                    ity.ty = Box::new(final_type.ty.clone());
                    self.results
                        .type_converter
                        .insert_typedef(tyname, final_type.ty);
                    self.results.apis.append(&mut final_type.extra_apis);
                    self.results.apis.push(UnanalyzedApi {
                        id: ity.ident.clone(),
                        ns: ns.clone(),
                        deps: final_type.types_encountered,
                        use_stmt: Use::Unused,
                        additional_cpp: None,
                        detail: ApiDetail::Typedef { type_item: ity },
                    });
                }
                _ => return Err(ConvertError::UnexpectedItemInMod),
            }
        }
        mod_converter.finished(&mut self.results.apis);

        // We don't immediately blat 'use' statements into any particular
        // `Api`. We'll squirrel them away and insert them into the output mod later
        // iff this mod ends up having any output items after garbage collection
        // of unnecessary APIs.
        let supers = std::iter::repeat(make_ident("super")).take(ns.depth() + 2);
        use_statements_for_this_mod.push(Item::Use(parse_quote! {
            #[allow(unused_imports)]
            use self::
                #(#supers)::*
            ::cxxbridge;
        }));
        for thing in &["UniquePtr", "CxxString"] {
            let thing = make_ident(thing);
            use_statements_for_this_mod.push(Item::Use(parse_quote! {
                #[allow(unused_imports)]
                use cxx:: #thing;
            }));
        }
        use_statements_for_this_mod.push(Item::Use(parse_quote! {
            #[allow(unused_imports)]
            use std::pin::Pin;
        }));
        self.results
            .use_stmts_by_mod
            .insert(ns, use_statements_for_this_mod);
        Ok(())
    }

    fn spot_forward_declaration(s: &Fields) -> bool {
        s.iter()
            .filter_map(|f| f.ident.as_ref())
            .any(|id| id == "_unused")
    }

    /// Record the Api for a type, e.g. enum or struct.
    /// Code generated includes the bindgen entry itself,
    /// various entries for the cxx::bridge to ensure cxx
    /// is aware of the type, and 'use' statements for the final
    /// output mod hierarchy. All are stored in the Api which
    /// this adds.
    fn parse_type(
        &mut self,
        tyname: TypeName,
        is_forward_declaration: bool,
        deps: HashSet<TypeName>,
        bindgen_mod_item: Option<Item>,
    ) {
        let final_ident = make_ident(tyname.get_final_ident());
        if self.type_config.is_on_blocklist(&tyname.to_cpp_name()) {
            return;
        }
        let tynamestring = tyname.to_cpp_name();
        let mut for_extern_c_ts = if tyname.has_namespace() {
            let ns_string = tyname
                .ns_segment_iter()
                .cloned()
                .collect::<Vec<String>>()
                .join("::");
            quote! {
                #[namespace = #ns_string]
            }
        } else {
            TokenStream2::new()
        };

        let mut fulltypath: Vec<_> = ["bindgen", "root"].iter().map(make_ident).collect();
        for_extern_c_ts.extend(quote! {
            type #final_ident = super::bindgen::root::
        });
        for segment in tyname.ns_segment_iter() {
            let id = make_ident(segment);
            for_extern_c_ts.extend(quote! {
                #id::
            });
            fulltypath.push(id);
        }
        for_extern_c_ts.extend(quote! {
            #final_ident;
        });
        fulltypath.push(final_ident.clone());
        let api = UnanalyzedApi {
            ns: tyname.get_namespace().clone(),
            id: final_ident.clone(),
            use_stmt: Use::Used,
            deps,
            additional_cpp: None,
            detail: ApiDetail::Type {
                ty_details: TypeApiDetails {
                    fulltypath,
                    final_ident,
                    tynamestring,
                },
                for_extern_c_ts,
                is_forward_declaration,
                bindgen_mod_item,
                analysis: (),
            },
        };
        self.results.apis.push(api);
        self.results.type_converter.push(tyname);
    }
}
<commit_msg>Skipping parse of unhandled items<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::{collections::HashMap, collections::HashSet};

use crate::{
    conversion::{
        api::{ApiDetail, ParseResults, TypeApiDetails, UnanalyzedApi},
        ConvertError,
    },
    types::make_ident,
    types::Namespace,
    types::TypeName,
};
use autocxx_parser::TypeConfig;
use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{parse_quote, Fields, Item};

use super::{
    super::{api::Use, utilities::generate_utilities},
    type_converter::TypeConverter,
};

use super::parse_foreign_mod::ParseForeignMod;

/// Parses a bindgen mod in order to understand the APIs within it.
pub(crate) struct ParseBindgen<'a> {
    type_config: &'a TypeConfig,
    results: ParseResults,
    /// Here we track the last struct which bindgen told us about.
    /// Any subsequent "extern 'C'" blocks are methods belonging to that type,
    /// even if the 'this' is actually recorded as void in the
    /// function signature.
    latest_virtual_this_type: Option<TypeName>,
}

impl<'a> ParseBindgen<'a> {
    pub(crate) fn new(type_config: &'a TypeConfig) -> Self {
        ParseBindgen {
            type_config,
            results: ParseResults {
                apis: Vec::new(),
                type_converter: TypeConverter::new(),
                use_stmts_by_mod: HashMap::new(),
            },
            latest_virtual_this_type: None,
        }
    }

    /// Parses items found in the `bindgen` output and returns a set of
    /// `Api`s together with some other data.
    pub(crate) fn parse_items(
        mut self,
        items: Vec<Item>,
        exclude_utilities: bool,
    ) -> Result<ParseResults, ConvertError> {
        let items = Self::find_items_in_root(items)?;
        if !exclude_utilities {
            generate_utilities(&mut self.results.apis);
        }
        let root_ns = Namespace::new();
        self.parse_mod_items(items, root_ns);
        Ok(self.results)
    }

    fn find_items_in_root(items: Vec<Item>) -> Result<Vec<Item>, ConvertError> {
        for item in items {
            match item {
                Item::Mod(root_mod) => {
                    // With namespaces enabled, bindgen always puts everything
                    // in a mod called 'root'. We don't want to pass that
                    // onto cxx, so jump right into it.
                    assert!(root_mod.ident == "root");
                    if let Some((_, items)) = root_mod.content {
                        return Ok(items);
                    }
                }
                _ => return Err(ConvertError::UnexpectedOuterItem),
            }
        }
        Ok(Vec::new())
    }

    /// Interpret the bindgen-generated .rs for a particular
    /// mod, which corresponds to a C++ namespace.
    fn parse_mod_items(&mut self, items: Vec<Item>, ns: Namespace) {
        // This object maintains some state specific to this namespace, i.e.
        // this particular mod.
        let mut mod_converter = ParseForeignMod::new(ns.clone());
        let mut use_statements_for_this_mod = Vec::new();
        for item in items {
            let r = self.parse_item(item, &mut mod_converter, &ns, &mut use_statements_for_this_mod);
            match r {
                Err(err) if err.is_ignorable() => {
                    eprintln!("Ignored item discovered whilst parsing: {}", err)
                }
                Err(_) => r.unwrap(),
                Ok(_) => {},
            }
        }
        mod_converter.finished(&mut self.results.apis);

        // We don't immediately blat 'use' statements into any particular
        // `Api`. We'll squirrel them away and insert them into the output mod later
        // iff this mod ends up having any output items after garbage collection
        // of unnecessary APIs.
        let supers = std::iter::repeat(make_ident("super")).take(ns.depth() + 2);
        use_statements_for_this_mod.push(Item::Use(parse_quote! {
            #[allow(unused_imports)]
            use self::
                #(#supers)::*
            ::cxxbridge;
        }));
        for thing in &["UniquePtr", "CxxString"] {
            let thing = make_ident(thing);
            use_statements_for_this_mod.push(Item::Use(parse_quote! {
                #[allow(unused_imports)]
                use cxx:: #thing;
            }));
        }
        use_statements_for_this_mod.push(Item::Use(parse_quote! {
            #[allow(unused_imports)]
            use std::pin::Pin;
        }));
        self.results
            .use_stmts_by_mod
            .insert(ns, use_statements_for_this_mod);
    }

    fn parse_item(&mut self, item: Item, mod_converter: &mut ParseForeignMod, ns: &Namespace, use_statements_for_this_mod: &mut Vec<Item>) -> Result<(),ConvertError> {
        match item {
            Item::ForeignMod(fm) => {
                mod_converter.convert_foreign_mod_items(
                    fm.items,
                    self.latest_virtual_this_type.clone(),
                )
            }
            Item::Struct(s) => {
                if s.ident.to_string().ends_with("__bindgen_vtable") {
                    return Ok(());
                }
                let tyname = TypeName::new(ns, &s.ident.to_string());
                let is_forward_declaration = Self::spot_forward_declaration(&s.fields);
                // cxx::bridge can't cope with type aliases to generic
                // types at the moment.
                self.parse_type(
                    tyname.clone(),
                    is_forward_declaration,
                    HashSet::new(),
                    Some(Item::Struct(s)),
                );
                self.latest_virtual_this_type = Some(tyname);
                Ok(())
            }
            Item::Enum(e) => {
                let tyname = TypeName::new(ns, &e.ident.to_string());
                self.parse_type(tyname, false, HashSet::new(), Some(Item::Enum(e)));
                Ok(())
            }
            Item::Impl(imp) => {
                // We *mostly* ignore all impl blocks generated by bindgen.
                // Methods also appear in 'extern "C"' blocks which
                // we will convert instead. At that time we'll also construct
                // synthetic impl blocks.
                // We do however record which methods were spotted, since
                // we have no other way of working out which functions are
                // static methods vs plain functions.
                mod_converter.convert_impl_items(imp);
                Ok(())
            }
            Item::Mod(itm) => {
                if let Some((_, items)) = itm.content {
                    let new_ns = ns.push(itm.ident.to_string());
                    self.parse_mod_items(items, new_ns);
                }
                Ok(())
            }
            Item::Use(_) => {
                use_statements_for_this_mod.push(item);
                Ok(())
            }
            Item::Const(const_item) => {
                // The following puts this constant into
                // the global namespace which is bug
                // https://github.com/google/autocxx/issues/133
                self.results.apis.push(UnanalyzedApi {
                    id: const_item.ident.clone(),
                    ns: ns.clone(),
                    deps: HashSet::new(),
                    use_stmt: Use::Unused,
                    detail: ApiDetail::Const { const_item },
                    additional_cpp: None,
                });
                Ok(())
            }
            Item::Type(mut ity) => {
                let tyname = TypeName::new(ns, &ity.ident.to_string());
                let mut final_type = self
                    .results
                    .type_converter
                    .convert_type(*ity.ty, ns, false)?;
                ity.ty = Box::new(final_type.ty.clone());
                self.results
                    .type_converter
                    .insert_typedef(tyname, final_type.ty);
                self.results.apis.append(&mut final_type.extra_apis);
                self.results.apis.push(UnanalyzedApi {
                    id: ity.ident.clone(),
                    ns: ns.clone(),
                    deps: final_type.types_encountered,
                    use_stmt: Use::Unused,
                    additional_cpp: None,
                    detail: ApiDetail::Typedef { type_item: ity },
                });
                Ok(())
            }
            _ => Err(ConvertError::UnexpectedItemInMod),
        }
    }

    fn spot_forward_declaration(s: &Fields) -> bool {
        s.iter()
            .filter_map(|f| f.ident.as_ref())
            .any(|id| id == "_unused")
    }

    /// Record the Api for a type, e.g. enum or struct.
    /// Code generated includes the bindgen entry itself,
    /// various entries for the cxx::bridge to ensure cxx
    /// is aware of the type, and 'use' statements for the final
    /// output mod hierarchy. All are stored in the Api which
    /// this adds.
    fn parse_type(
        &mut self,
        tyname: TypeName,
        is_forward_declaration: bool,
        deps: HashSet<TypeName>,
        bindgen_mod_item: Option<Item>,
    ) {
        let final_ident = make_ident(tyname.get_final_ident());
        if self.type_config.is_on_blocklist(&tyname.to_cpp_name()) {
            return;
        }
        let tynamestring = tyname.to_cpp_name();
        let mut for_extern_c_ts = if tyname.has_namespace() {
            let ns_string = tyname
                .ns_segment_iter()
                .cloned()
                .collect::<Vec<String>>()
                .join("::");
            quote! {
                #[namespace = #ns_string]
            }
        } else {
            TokenStream2::new()
        };

        let mut fulltypath: Vec<_> = ["bindgen", "root"].iter().map(make_ident).collect();
        for_extern_c_ts.extend(quote! {
            type #final_ident = super::bindgen::root::
        });
        for segment in tyname.ns_segment_iter() {
            let id = make_ident(segment);
            for_extern_c_ts.extend(quote! {
                #id::
            });
            fulltypath.push(id);
        }
        for_extern_c_ts.extend(quote! {
            #final_ident;
        });
        fulltypath.push(final_ident.clone());
        let api = UnanalyzedApi {
            ns: tyname.get_namespace().clone(),
            id: final_ident.clone(),
            use_stmt: Use::Used,
            deps,
            additional_cpp: None,
            detail: ApiDetail::Type {
                ty_details: TypeApiDetails {
                    fulltypath,
                    final_ident,
                    tynamestring,
                },
                for_extern_c_ts,
                is_forward_declaration,
                bindgen_mod_item,
                analysis: (),
            },
        };
        self.results.apis.push(api);
        self.results.type_converter.push(tyname);
    }
}
<|endoftext|>


<commit_before>/// A trait for fixed size u8 array.

// Inspired by ArrayVec and SmallVec, but no unsafe.

// Use this trait so that we don't have to use `Vec` for some semi-fixed length buffers and
// input/output types.
pub trait U8Array: Sized {
    /// Create a new array filled with all zeros.
    fn new() -> Self;
    /// Create a new array filled with a same value.
    fn new_with(u8) -> Self;
    /// Create a new array from a slice.
    ///
    /// # Panics
    ///
    /// The slice must be of the same length.
    fn from_slice(&[u8]) -> Self;
    /// Length of the array.
    fn len() -> usize;
    /// As slice.
    fn as_slice(&self) -> &[u8];
    /// As mutable slice.
    fn as_mut(&mut self) -> &mut [u8];
    // Cannot just impl `Clone`, that will conflict with [u8; 32].
    /// Clone.
    fn clone(&self) -> Self {
        Self::from_slice(self.as_slice())
    }
}

macro_rules! impl_array {
    ($len:expr) => {
        impl U8Array for [u8; $len] {
            fn new() -> Self {
                [0u8; $len]
            }

            fn new_with(x: u8) -> Self {
                [x; $len]
            }

            fn from_slice(data: &[u8]) -> Self {
                let mut a = [0u8; $len];
                a.copy_from_slice(data);
                a
            }

            fn len() -> usize {
                $len
            }

            fn as_slice(&self) -> &[u8] {
                self
            }

            fn as_mut(&mut self) -> &mut [u8] {
                self
            }
        }
    }
}

impl_array!(32);
impl_array!(64);
impl_array!(128);

/// A DH.
pub trait DH {
    /// Type of private key.
    type Key: U8Array;
    /// Type of pubkey key.
    type Pubkey: U8Array;
    /// Type of output.
    type Output: U8Array;

    /// Name of this DH function, e.g., “25519”.
    fn name() -> &'static str;

    /// Randomly generate a new private key.
    fn genkey() -> Self::Key;

    /// Calculate public key from a private key.
    fn pubkey(&Self::Key) -> Self::Pubkey;

    /// Perform DH key exchange.
    fn dh(&Self::Key, &Self::Pubkey) -> Result<Self::Output, ()>;
}

/// An AEAD.
pub trait Cipher {
    /// Name of this cipher function.
    fn name() -> &'static str;
    /// Type of key.
    type Key: U8Array;

    /// Length of key.
    fn key_len() -> usize {
        Self::Key::len()
    }

    /// Length of auth tag.
    ///
    /// All ciphers specified in the spec has tag length 16.
    fn tag_len() -> usize {
        16
    }

    /// AEAD encryption.
    ///
    /// out.len() == plaintext.len() + Self::tag_len()
    fn encrypt(k: &Self::Key, nonce: u64, ad: &[u8], plaintext: &[u8], out: &mut [u8]);

    /// AEAD decryption.
    ///
    /// out.len() == ciphertext.len() - Self::tag_len()
    fn decrypt(k: &Self::Key,
               nonce: u64,
               ad: &[u8],
               ciphertext: &[u8],
               out: &mut [u8])
               -> Result<(), ()>;

    /// Rekey. Returns a new cipher key as a pseudorandom function of k.
    fn rekey(k: &Self::Key) -> Self::Key {
        let mut k1 = Self::Key::new();
        Self::encrypt(&k, 0u64.wrapping_sub(1), &[], &[0; 32], k1.as_mut());
        k1
    }
}

/// A hash function.
pub trait Hash: Default {
    /// Name of the hash function.
    fn name() -> &'static str;

    /// Type of a block.
    type Block: U8Array;
    /// Type of output.
    type Output: U8Array;

    /// Length of block.
    fn block_len() -> usize {
        Self::Block::len()
    }

    /// Length of hash output, in number of bytes.
    fn hash_len() -> usize {
        Self::Output::len()
    }

    /// Reset state of hash context.
    fn reset(&mut self) {
        *self = Default::default();
    }

    /// Update hash context with some input.
    fn input(&mut self, data: &[u8]);

    /// Get hash result.
    fn result(&mut self) -> Self::Output;

    /// Calculate hash of some data.
    fn hash(data: &[u8]) -> Self::Output {
        let mut h: Self = Default::default();
        h.input(data);
        h.result()
    }

    /// Calculate HMAC-THIS-HASH, with some `key` and several messages.
    fn hmac_many(key: &[u8], data: &[&[u8]]) -> Self::Output {
        assert!(key.len() <= Self::block_len());

        let mut ipad = Self::Block::new_with(0x36u8);
        let mut opad = Self::Block::new_with(0x5cu8);

        for count in 0..key.len() {
            ipad.as_mut()[count] ^= key[count];
            opad.as_mut()[count] ^= key[count];
        }

        let mut hasher: Self = Default::default();
        hasher.input(ipad.as_slice());
        for d in data {
            hasher.input(d);
        }
        let inner_output = hasher.result();

        hasher.reset();
        hasher.input(opad.as_slice());
        hasher.input(inner_output.as_slice());
        hasher.result()
    }

    /// Calculate HMAC-THIS-HASH, with some `key` and a message.
    fn hmac(key: &[u8], data: &[u8]) -> Self::Output {
        Self::hmac_many(key, &[data])
    }

    /// Calculate HKDF, as specified in the noise spec.
    fn hkdf(chaining_key: &[u8], input_key_material: &[u8]) -> (Self::Output, Self::Output) {
        let temp_key = Self::hmac(chaining_key, input_key_material);
        let out1 = Self::hmac(temp_key.as_slice(), &[1u8]);
        let out2 = Self::hmac_many(temp_key.as_slice(), &[out1.as_slice(), &[2u8]]);
        (out1, out2)
    }
}
<commit_msg>Fix rekey<commit_after>/// A trait for fixed size u8 array.

// Inspired by ArrayVec and SmallVec, but no unsafe.

// Use this trait so that we don't have to use `Vec` for some semi-fixed length buffers and
// input/output types.
pub trait U8Array: Sized {
    /// Create a new array filled with all zeros.
    fn new() -> Self;
    /// Create a new array filled with a same value.
    fn new_with(u8) -> Self;
    /// Create a new array from a slice.
    ///
    /// # Panics
    ///
    /// The slice must be of the same length.
    fn from_slice(&[u8]) -> Self;
    /// Length of the array.
    fn len() -> usize;
    /// As slice.
    fn as_slice(&self) -> &[u8];
    /// As mutable slice.
    fn as_mut(&mut self) -> &mut [u8];
    // Cannot just impl `Clone`, that will conflict with [u8; 32].
    /// Clone.
    fn clone(&self) -> Self {
        Self::from_slice(self.as_slice())
    }
}

macro_rules! impl_array {
    ($len:expr) => {
        impl U8Array for [u8; $len] {
            fn new() -> Self {
                [0u8; $len]
            }

            fn new_with(x: u8) -> Self {
                [x; $len]
            }

            fn from_slice(data: &[u8]) -> Self {
                let mut a = [0u8; $len];
                a.copy_from_slice(data);
                a
            }

            fn len() -> usize {
                $len
            }

            fn as_slice(&self) -> &[u8] {
                self
            }

            fn as_mut(&mut self) -> &mut [u8] {
                self
            }
        }
    }
}

impl_array!(32);
impl_array!(64);
impl_array!(128);

/// A DH.
pub trait DH {
    /// Type of private key.
    type Key: U8Array;
    /// Type of pubkey key.
    type Pubkey: U8Array;
    /// Type of output.
    type Output: U8Array;

    /// Name of this DH function, e.g., “25519”.
    fn name() -> &'static str;

    /// Randomly generate a new private key.
    fn genkey() -> Self::Key;

    /// Calculate public key from a private key.
    fn pubkey(&Self::Key) -> Self::Pubkey;

    /// Perform DH key exchange.
    fn dh(&Self::Key, &Self::Pubkey) -> Result<Self::Output, ()>;
}

/// An AEAD.
pub trait Cipher {
    /// Name of this cipher function.
    fn name() -> &'static str;
    /// Type of key.
    type Key: U8Array;

    /// Length of key.
    fn key_len() -> usize {
        Self::Key::len()
    }

    /// Length of auth tag.
    ///
    /// All ciphers specified in the spec has tag length 16.
    fn tag_len() -> usize {
        16
    }

    /// AEAD encryption.
    ///
    /// out.len() == plaintext.len() + Self::tag_len()
    fn encrypt(k: &Self::Key, nonce: u64, ad: &[u8], plaintext: &[u8], out: &mut [u8]);

    /// AEAD decryption.
    ///
    /// out.len() == ciphertext.len() - Self::tag_len()
    fn decrypt(k: &Self::Key,
               nonce: u64,
               ad: &[u8],
               ciphertext: &[u8],
               out: &mut [u8])
               -> Result<(), ()>;

    /// Rekey. Returns a new cipher key as a pseudorandom function of k.
    fn rekey(k: &Self::Key) -> Self::Key {
        // XXX: `k1` is not zeroed.
        let mut k1 = [0u8; 48];
        Self::encrypt(k, 0u64.wrapping_sub(1), &[], &[0; 32], &mut k1);
        Self::Key::from_slice(&k1[..32])
    }
}

/// A hash function.
pub trait Hash: Default {
    /// Name of the hash function.
    fn name() -> &'static str;

    /// Type of a block.
    type Block: U8Array;
    /// Type of output.
    type Output: U8Array;

    /// Length of block.
    fn block_len() -> usize {
        Self::Block::len()
    }

    /// Length of hash output, in number of bytes.
    fn hash_len() -> usize {
        Self::Output::len()
    }

    /// Reset state of hash context.
    fn reset(&mut self) {
        *self = Default::default();
    }

    /// Update hash context with some input.
    fn input(&mut self, data: &[u8]);

    /// Get hash result.
    fn result(&mut self) -> Self::Output;

    /// Calculate hash of some data.
    fn hash(data: &[u8]) -> Self::Output {
        let mut h: Self = Default::default();
        h.input(data);
        h.result()
    }

    /// Calculate HMAC-THIS-HASH, with some `key` and several messages.
    fn hmac_many(key: &[u8], data: &[&[u8]]) -> Self::Output {
        assert!(key.len() <= Self::block_len());

        let mut ipad = Self::Block::new_with(0x36u8);
        let mut opad = Self::Block::new_with(0x5cu8);

        for count in 0..key.len() {
            ipad.as_mut()[count] ^= key[count];
            opad.as_mut()[count] ^= key[count];
        }

        let mut hasher: Self = Default::default();
        hasher.input(ipad.as_slice());
        for d in data {
            hasher.input(d);
        }
        let inner_output = hasher.result();

        hasher.reset();
        hasher.input(opad.as_slice());
        hasher.input(inner_output.as_slice());
        hasher.result()
    }

    /// Calculate HMAC-THIS-HASH, with some `key` and a message.
    fn hmac(key: &[u8], data: &[u8]) -> Self::Output {
        Self::hmac_many(key, &[data])
    }

    /// Calculate HKDF, as specified in the noise spec.
    fn hkdf(chaining_key: &[u8], input_key_material: &[u8]) -> (Self::Output, Self::Output) {
        let temp_key = Self::hmac(chaining_key, input_key_material);
        let out1 = Self::hmac(temp_key.as_slice(), &[1u8]);
        let out2 = Self::hmac_many(temp_key.as_slice(), &[out1.as_slice(), &[2u8]]);
        (out1, out2)
    }
}
<|endoftext|>


<commit_before>use super::Gba;
use arm::Cycles;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;

pub type EventFn = fn(gba: &mut Gba, late: Cycles);

#[derive(Default, Clone)]
pub struct Scheduler {
    inner: Rc<RefCell<Inner>>,
}

impl Scheduler {
    pub fn schedule(&self, callback: EventFn, cycles: impl Into<Cycles>) {
        self.inner.borrow_mut().schedule(Event {
            callback,
            cycles_remaining: cycles.into(),
        });
    }

    pub fn advance(&self, cycles: impl Into<Cycles>) -> Option<(EventFn, Cycles)> {
        self.inner.borrow_mut().advance(cycles.into())
    }

    #[cfg(test)]
    pub fn dump(&self) {
        for (idx, event) in self.inner.borrow().events.iter().enumerate() {
            println!("EVENT{}: {} cycles", idx, event.cycles_remaining);
        }
    }
}

pub struct Event {
    callback: EventFn,
    cycles_remaining: Cycles,
}

#[derive(Default)]
struct Inner {
    events: VecDeque<Event>,
}

impl Inner {
    fn schedule(&mut self, mut new_event: Event) {
        let mut insert_idx = self.events.len();
        for (idx, event) in self.events.iter_mut().enumerate() {
            if new_event.cycles_remaining < event.cycles_remaining {
                event.cycles_remaining -= new_event.cycles_remaining;
                insert_idx = idx;
                break;
            }
            new_event.cycles_remaining -= event.cycles_remaining;
        }
        self.events.insert(insert_idx, new_event);
    }

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if let Some(event) = self.events.front_mut() {
            if event.cycles_remaining > cycles {
                event.cycles_remaining -= cycles;
                return None;
            }
        } else {
            return None;
        }

        let event = self.events.pop_front().unwrap();
        Some((event.callback, cycles - event.cycles_remaining))
    }
}

#[cfg(test)]
mod test {
    use arm::Cycles;

    use crate::Gba;

    use super::Scheduler;

    #[test]
    fn basic_scheduling() {
        let mut gba = Gba::default();
        let mut scheduler = Scheduler::default();

        scheduler.schedule(|_, _| data()[0] = 1, 10u32);
        scheduler.schedule(|_, _| data()[3] = 1, 17u32);
        scheduler.schedule(|_, _| data()[1] = 1, 13u32);
        scheduler.schedule(|_, _| data()[2] = 1, 13u32);
        scheduler.dump();

        assert!(scheduler.advance(6u32).is_none());
        assert_eq!(data()[0], 0);

        let (cb, cycles) = scheduler.advance(6u32).expect("expected event");
        assert_eq!(cycles, Cycles::from(2u32));
        cb(&mut gba, cycles);
        assert!(scheduler.advance(cycles).is_none());
        assert_eq!(*data(), [1, 0, 0, 0]);

        let (cb, cycles) = scheduler.advance(Cycles::ONE).expect("expected event");
        assert_eq!(cycles, Cycles::ZERO);
        cb(&mut gba, cycles);
        assert_eq!(*data(), [1, 1, 0, 0]);
        let (cb, cycles) = scheduler.advance(cycles).expect("expected event");
        assert_eq!(cycles, Cycles::ZERO);
        cb(&mut gba, cycles);
        assert!(scheduler.advance(cycles).is_none());
        assert_eq!(*data(), [1, 1, 1, 0]);

        let (cb, cycles) = scheduler.advance(8).expect("expected event");
        assert_eq!(cycles, Cycles::from(4u32));
        cb(&mut gba, cycles);
        assert!(scheduler.advance(cycles).is_none());
        assert_eq!(*data(), [1, 1, 1, 1]);

        static mut DATA: [u32; 4] = [0; 4];
        fn data() -> &'static mut [u32; 4] {
            unsafe { &mut DATA }
        }
    }
}
<commit_msg>Fix warning in scheduler tests.<commit_after>use super::Gba;
use arm::Cycles;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;

pub type EventFn = fn(gba: &mut Gba, late: Cycles);

#[derive(Default, Clone)]
pub struct Scheduler {
    inner: Rc<RefCell<Inner>>,
}

impl Scheduler {
    pub fn schedule(&self, callback: EventFn, cycles: impl Into<Cycles>) {
        self.inner.borrow_mut().schedule(Event {
            callback,
            cycles_remaining: cycles.into(),
        });
    }

    pub fn advance(&self, cycles: impl Into<Cycles>) -> Option<(EventFn, Cycles)> {
        self.inner.borrow_mut().advance(cycles.into())
    }

    #[cfg(test)]
    pub fn dump(&self) {
        for (idx, event) in self.inner.borrow().events.iter().enumerate() {
            println!("EVENT{}: {} cycles", idx, event.cycles_remaining);
        }
    }
}

pub struct Event {
    callback: EventFn,
    cycles_remaining: Cycles,
}

#[derive(Default)]
struct Inner {
    events: VecDeque<Event>,
}

impl Inner {
    fn schedule(&mut self, mut new_event: Event) {
        let mut insert_idx = self.events.len();
        for (idx, event) in self.events.iter_mut().enumerate() {
            if new_event.cycles_remaining < event.cycles_remaining {
                event.cycles_remaining -= new_event.cycles_remaining;
                insert_idx = idx;
                break;
            }
            new_event.cycles_remaining -= event.cycles_remaining;
        }
        self.events.insert(insert_idx, new_event);
    }

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if let Some(event) = self.events.front_mut() {
            if event.cycles_remaining > cycles {
                event.cycles_remaining -= cycles;
                return None;
            }
        } else {
            return None;
        }

        let event = self.events.pop_front().unwrap();
        Some((event.callback, cycles - event.cycles_remaining))
    }
}

#[cfg(test)]
mod test {
    use arm::Cycles;

    use crate::Gba;

    use super::Scheduler;

    #[test]
    fn basic_scheduling() {
        let mut gba = Gba::default();
        let scheduler = Scheduler::default();

        scheduler.schedule(|_, _| data()[0] = 1, 10u32);
        scheduler.schedule(|_, _| data()[3] = 1, 17u32);
        scheduler.schedule(|_, _| data()[1] = 1, 13u32);
        scheduler.schedule(|_, _| data()[2] = 1, 13u32);
        scheduler.dump();

        assert!(scheduler.advance(6u32).is_none());
        assert_eq!(data()[0], 0);

        let (cb, cycles) = scheduler.advance(6u32).expect("expected event");
        assert_eq!(cycles, Cycles::from(2u32));
        cb(&mut gba, cycles);
        assert!(scheduler.advance(cycles).is_none());
        assert_eq!(*data(), [1, 0, 0, 0]);

        let (cb, cycles) = scheduler.advance(Cycles::ONE).expect("expected event");
        assert_eq!(cycles, Cycles::ZERO);
        cb(&mut gba, cycles);
        assert_eq!(*data(), [1, 1, 0, 0]);
        let (cb, cycles) = scheduler.advance(cycles).expect("expected event");
        assert_eq!(cycles, Cycles::ZERO);
        cb(&mut gba, cycles);
        assert!(scheduler.advance(cycles).is_none());
        assert_eq!(*data(), [1, 1, 1, 0]);

        let (cb, cycles) = scheduler.advance(8).expect("expected event");
        assert_eq!(cycles, Cycles::from(4u32));
        cb(&mut gba, cycles);
        assert!(scheduler.advance(cycles).is_none());
        assert_eq!(*data(), [1, 1, 1, 1]);

        static mut DATA: [u32; 4] = [0; 4];
        fn data() -> &'static mut [u32; 4] {
            unsafe { &mut DATA }
        }
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate handlebars_iron as hbs;
extern crate rustc_serialize;

use std::error::Error;
use iron::prelude::*;
use iron::{status, AfterMiddleware};
use hbs::{Template, HandlebarsEngine, DirectorySource};

/// the handler
fn hello_world(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();

    let data = "".to_owned();
    resp.set_mut(Template::new("not-exist", data)).set_mut(status::Ok);
    Ok(resp)
}

struct ErrorReporter;

impl AfterMiddleware for ErrorReporter {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        println!("{}", err.description());
        Err(err)
    }
}

fn main() {
    let mut chain = Chain::new(hello_world);
    let mut hbse = HandlebarsEngine::new2();
    hbse.add(Box::new(DirectorySource::new("./examples/templates/", ".hbs")));
    // success of panic
    if let Err(r) = hbse.reload() {
        panic!("{}", r.description());
    }

    chain.link_after(hbse);
    chain.link_after(ErrorReporter);
    println!("Server running at http://localhost:3000/");
    Iron::new(chain).http("localhost:3000").unwrap();
}
<commit_msg>(fix) remove unused imports<commit_after>extern crate iron;
extern crate handlebars_iron as hbs;

use std::error::Error;
use iron::prelude::*;
use iron::{status, AfterMiddleware};
use hbs::{Template, HandlebarsEngine, DirectorySource};

/// the handler
fn hello_world(_: &mut Request) -> IronResult<Response> {
    let mut resp = Response::new();

    let data = "".to_owned();
    resp.set_mut(Template::new("not-exist", data)).set_mut(status::Ok);
    Ok(resp)
}

struct ErrorReporter;

impl AfterMiddleware for ErrorReporter {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        println!("{}", err.description());
        Err(err)
    }
}

fn main() {
    let mut chain = Chain::new(hello_world);
    let mut hbse = HandlebarsEngine::new2();
    hbse.add(Box::new(DirectorySource::new("./examples/templates/", ".hbs")));
    // success of panic
    if let Err(r) = hbse.reload() {
        panic!("{}", r.description());
    }

    chain.link_after(hbse);
    chain.link_after(ErrorReporter);
    println!("Server running at http://localhost:3000/");
    Iron::new(chain).http("localhost:3000").unwrap();
}
<|endoftext|>